Skip to content

Commit

Permalink
podman support: Enable Podman support.
Browse files Browse the repository at this point in the history
Signed-off-by: Paweł Szulik <paul.szulik@gmail.com>
  • Loading branch information
Creatone committed Jun 27, 2023
1 parent f20fbe1 commit 0c8457a
Show file tree
Hide file tree
Showing 8 changed files with 238 additions and 37 deletions.
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
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))
}
6 changes: 3 additions & 3 deletions cmd/internal/pages/templates.go

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions docs/runtime_options.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ From [glog](https://github.com/golang/glog) here are some flags we find useful:
--docker-tls-ca="ca.pem": trusted CA for TLS-connection with docker
```

## Podman

```bash
--podman="unix:///var/run/podman/podman.sock": podman endpoint (default "unix:///var/run/podman/podman.sock")
```

## Housekeeping

Housekeeping is the periodic actions cAdvisor takes. During these actions, cAdvisor will gather container stats. These flags control how and when cAdvisor performs housekeeping.
Expand Down
Loading

0 comments on commit 0c8457a

Please sign in to comment.