Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Podman support. #3021

Merged
merged 3 commits into from
Jun 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/internal/api/versions.go
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,7 @@ func GetRequestOptions(r *http.Request) (v2.RequestOptions, error) {
supportedTypes := map[string]bool{
v2.TypeName: true,
v2.TypeDocker: true,
v2.TypePodman: true,
}
// fill in the defaults.
opt := v2.RequestOptions{
Expand Down
1 change: 1 addition & 0 deletions cmd/internal/container/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ import (
_ "github.com/google/cadvisor/container/containerd/install"
_ "github.com/google/cadvisor/container/crio/install"
_ "github.com/google/cadvisor/container/docker/install"
_ "github.com/google/cadvisor/container/podman/install"
_ "github.com/google/cadvisor/container/systemd/install"
)
6 changes: 4 additions & 2 deletions cmd/internal/pages/assets/html/containers.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ <h1>{{.DisplayName}}</h1>
<div class="col-sm-12">
<h4><a href="../docker">Docker Containers</a></h4>
</div>
<div class="col-sm-12">
<h4><a href="../podman">Podman Containers</a></h4>
</div>
{{end}}
{{if .Subcontainers}}
<div class="col-sm-12">
Expand Down Expand Up @@ -250,8 +253,7 @@ <h4>Top Memory Usage:
class="subcontainer-display-input"
value=10>
</h4>
<span class="subcontroller-display-block">
<span>
<span class="subcontroller-display-block"/>
<div id="memory-per-subcontainer-usage-chart">
</div>
</div>
Expand Down
11 changes: 6 additions & 5 deletions cmd/internal/pages/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"time"

"github.com/google/cadvisor/container/docker"
dockerutil "github.com/google/cadvisor/container/docker/utils"
info "github.com/google/cadvisor/info/v1"
"github.com/google/cadvisor/manager"

Expand All @@ -39,12 +40,12 @@ func toStatusKV(status info.DockerStatus) ([]keyVal, []keyVal) {
ds = append(ds, keyVal{Key: k, Value: v})
}
return []keyVal{
{Key: "Docker Version", Value: status.Version},
{Key: "Docker API Version", Value: status.APIVersion},
{Key: "Version", Value: status.Version},
{Key: "API Version", Value: status.APIVersion},
{Key: "Kernel Version", Value: status.KernelVersion},
{Key: "OS Version", Value: status.OS},
{Key: "Host Name", Value: status.Hostname},
{Key: "Docker Root Directory", Value: status.RootDir},
{Key: "Root Directory", Value: status.RootDir},
{Key: "Execution Driver", Value: status.ExecDriver},
{Key: "Number of Images", Value: strconv.Itoa(status.NumImages)},
{Key: "Number of Containers", Value: strconv.Itoa(status.NumContainers)},
Expand Down Expand Up @@ -73,7 +74,7 @@ func serveDockerPage(m manager.Manager, w http.ResponseWriter, u *url.URL) {
for _, cont := range conts {
subcontainers = append(subcontainers, link{
Text: getContainerDisplayName(cont.ContainerReference),
Link: path.Join(rootDir, DockerPage, docker.ContainerNameToDockerId(cont.ContainerReference.Name)),
Link: path.Join(rootDir, DockerPage, dockerutil.ContainerNameToId(cont.ContainerReference.Name)),
})
}

Expand Down Expand Up @@ -126,7 +127,7 @@ func serveDockerPage(m manager.Manager, w http.ResponseWriter, u *url.URL) {
})
parentContainers = append(parentContainers, link{
Text: displayName,
Link: path.Join(rootDir, DockerPage, docker.ContainerNameToDockerId(cont.Name)),
Link: path.Join(rootDir, DockerPage, dockerutil.ContainerNameToId(cont.Name)),
})

// Get the MachineInfo
Expand Down
20 changes: 20 additions & 0 deletions cmd/internal/pages/pages.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,29 @@ func dockerHandler(containerManager manager.Manager) auth.AuthenticatedHandlerFu
}
}

func podmanHandlerNoAuth(containerManager manager.Manager) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
servePodmanPage(containerManager, w, r.URL)
}
}

func podmanHandler(containerManager manager.Manager) auth.AuthenticatedHandlerFunc {
return func(w http.ResponseWriter, r *auth.AuthenticatedRequest) {
servePodmanPage(containerManager, w, r.URL)
}
}

// Register http handlers
func RegisterHandlersDigest(mux httpmux.Mux, containerManager manager.Manager, authenticator *auth.DigestAuth, urlBasePrefix string) error {
// Register the handler for the containers page.
if authenticator != nil {
mux.HandleFunc(ContainersPage, authenticator.Wrap(containerHandler(containerManager)))
mux.HandleFunc(DockerPage, authenticator.Wrap(dockerHandler(containerManager)))
mux.HandleFunc(PodmanPage, authenticator.Wrap(podmanHandler(containerManager)))
} else {
mux.HandleFunc(ContainersPage, containerHandlerNoAuth(containerManager))
mux.HandleFunc(DockerPage, dockerHandlerNoAuth(containerManager))
mux.HandleFunc(PodmanPage, podmanHandlerNoAuth(containerManager))
}

if ContainersPage[len(ContainersPage)-1] == '/' {
Expand All @@ -118,6 +132,10 @@ func RegisterHandlersDigest(mux httpmux.Mux, containerManager manager.Manager, a
redirectHandler := http.RedirectHandler(urlBasePrefix+DockerPage, http.StatusMovedPermanently)
mux.Handle(DockerPage[0:len(DockerPage)-1], redirectHandler)
}
if PodmanPage[len(PodmanPage)-1] == '/' {
redirectHandler := http.RedirectHandler(urlBasePrefix+PodmanPage, http.StatusMovedPermanently)
mux.Handle(PodmanPage[0:len(PodmanPage)-1], redirectHandler)
}

return nil
}
Expand All @@ -127,9 +145,11 @@ func RegisterHandlersBasic(mux httpmux.Mux, containerManager manager.Manager, au
if authenticator != nil {
mux.HandleFunc(ContainersPage, authenticator.Wrap(containerHandler(containerManager)))
mux.HandleFunc(DockerPage, authenticator.Wrap(dockerHandler(containerManager)))
mux.HandleFunc(PodmanPage, authenticator.Wrap(podmanHandler(containerManager)))
} else {
mux.HandleFunc(ContainersPage, containerHandlerNoAuth(containerManager))
mux.HandleFunc(DockerPage, dockerHandlerNoAuth(containerManager))
mux.HandleFunc(PodmanPage, podmanHandlerNoAuth(containerManager))
}

if ContainersPage[len(ContainersPage)-1] == '/' {
Expand Down
138 changes: 138 additions & 0 deletions cmd/internal/pages/podman.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// Copyright 2021 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package pages

import (
"fmt"
"net/http"
"net/url"
"path"
"time"

dockerutil "github.com/google/cadvisor/container/docker/utils"
"github.com/google/cadvisor/container/podman"
info "github.com/google/cadvisor/info/v1"
"github.com/google/cadvisor/manager"

"k8s.io/klog/v2"
)

const PodmanPage = "/podman/"

func servePodmanPage(m manager.Manager, w http.ResponseWriter, u *url.URL) {
start := time.Now()

containerName := u.Path[len(PodmanPage)-1:]
rootDir := getRootDir(containerName)

var data *pageData

if containerName == "/" {
// Scenario for all containers.
status, err := podman.Status()
if err != nil {
http.Error(w, fmt.Sprintf("failed to get podman info: %v", err), http.StatusInternalServerError)
return
}
images, err := podman.Images()
if err != nil {
http.Error(w, fmt.Sprintf("failed to get podman images: %v", err), http.StatusInternalServerError)
return
}

reqParams := info.ContainerInfoRequest{
NumStats: 0,
}
conts, err := m.AllPodmanContainers(&reqParams)
if err != nil {
http.Error(w, fmt.Sprintf("failed to get container %q with error: %v", containerName, err), http.StatusNotFound)
return
}
subcontainers := make([]link, 0, len(conts))
for _, cont := range conts {
subcontainers = append(subcontainers, link{
Text: getContainerDisplayName(cont.ContainerReference),
Link: path.Join(rootDir, PodmanPage, dockerutil.ContainerNameToId(cont.ContainerReference.Name)),
})
}

podmanStatus, driverStatus := toStatusKV(status)

podmanContainerText := "Podman Containers"
data = &pageData{
DisplayName: podmanContainerText,
ParentContainers: []link{
{
Text: podmanContainerText,
Link: path.Join(rootDir, PodmanPage),
}},
Subcontainers: subcontainers,
Root: rootDir,
DockerStatus: podmanStatus,
DockerDriverStatus: driverStatus,
DockerImages: images,
}
} else {
// Scenario for specific container.
machineInfo, err := m.GetMachineInfo()
if err != nil {
http.Error(w, fmt.Sprintf("failed to get machine info: %v", err), http.StatusInternalServerError)
return
}

reqParams := info.ContainerInfoRequest{
NumStats: 60,
}
cont, err := m.PodmanContainer(containerName[1:], &reqParams)
if err != nil {
http.Error(w, fmt.Sprintf("failed to get container %v with error: %v", containerName, err), http.StatusNotFound)
return
}
displayName := getContainerDisplayName(cont.ContainerReference)

var parentContainers []link
parentContainers = append(parentContainers, link{
Text: "Podman Containers",
Link: path.Join(rootDir, PodmanPage),
})
parentContainers = append(parentContainers, link{
Text: displayName,
Link: path.Join(rootDir, PodmanPage, dockerutil.ContainerNameToId(cont.Name)),
})

data = &pageData{
DisplayName: displayName,
ContainerName: escapeContainerName(cont.Name),
ParentContainers: parentContainers,
Spec: cont.Spec,
Stats: cont.Stats,
MachineInfo: machineInfo,
ResourcesAvailable: cont.Spec.HasCpu || cont.Spec.HasMemory || cont.Spec.HasNetwork,
CpuAvailable: cont.Spec.HasCpu,
MemoryAvailable: cont.Spec.HasMemory,
NetworkAvailable: cont.Spec.HasNetwork,
FsAvailable: cont.Spec.HasFilesystem,
CustomMetricsAvailable: cont.Spec.HasCustomMetrics,
Root: rootDir,
}
}

err := pageTemplate.Execute(w, data)
if err != nil {
klog.Errorf("Failed to apply template: %s", err)
}

klog.V(5).Infof("Request took %s", time.Since(start))
}
8 changes: 4 additions & 4 deletions cmd/internal/pages/templates.go

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions container/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const (
ContainerTypeCrio
ContainerTypeContainerd
ContainerTypeMesos
ContainerTypePodman
)

// Interface for container operation handlers.
Expand Down
Loading