Skip to content

Commit 0c8457a

Browse files
committed
podman support: Enable Podman support.
Signed-off-by: Paweł Szulik <[email protected]>
1 parent f20fbe1 commit 0c8457a

File tree

8 files changed

+238
-37
lines changed

8 files changed

+238
-37
lines changed

cmd/internal/api/versions.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,7 @@ func GetRequestOptions(r *http.Request) (v2.RequestOptions, error) {
531531
supportedTypes := map[string]bool{
532532
v2.TypeName: true,
533533
v2.TypeDocker: true,
534+
v2.TypePodman: true,
534535
}
535536
// fill in the defaults.
536537
opt := v2.RequestOptions{

cmd/internal/container/install/install.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ import (
2121
_ "github.com/google/cadvisor/container/containerd/install"
2222
_ "github.com/google/cadvisor/container/crio/install"
2323
_ "github.com/google/cadvisor/container/docker/install"
24+
_ "github.com/google/cadvisor/container/podman/install"
2425
_ "github.com/google/cadvisor/container/systemd/install"
2526
)

cmd/internal/pages/assets/html/containers.html

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ <h1>{{.DisplayName}}</h1>
5050
<div class="col-sm-12">
5151
<h4><a href="../docker">Docker Containers</a></h4>
5252
</div>
53+
<div class="col-sm-12">
54+
<h4><a href="../podman">Podman Containers</a></h4>
55+
</div>
5356
{{end}}
5457
{{if .Subcontainers}}
5558
<div class="col-sm-12">
@@ -250,8 +253,7 @@ <h4>Top Memory Usage:
250253
class="subcontainer-display-input"
251254
value=10>
252255
</h4>
253-
<span class="subcontroller-display-block">
254-
<span>
256+
<span class="subcontroller-display-block"/>
255257
<div id="memory-per-subcontainer-usage-chart">
256258
</div>
257259
</div>

cmd/internal/pages/pages.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,29 @@ func dockerHandler(containerManager manager.Manager) auth.AuthenticatedHandlerFu
9999
}
100100
}
101101

102+
func podmanHandlerNoAuth(containerManager manager.Manager) http.HandlerFunc {
103+
return func(w http.ResponseWriter, r *http.Request) {
104+
servePodmanPage(containerManager, w, r.URL)
105+
}
106+
}
107+
108+
func podmanHandler(containerManager manager.Manager) auth.AuthenticatedHandlerFunc {
109+
return func(w http.ResponseWriter, r *auth.AuthenticatedRequest) {
110+
servePodmanPage(containerManager, w, r.URL)
111+
}
112+
}
113+
102114
// Register http handlers
103115
func RegisterHandlersDigest(mux httpmux.Mux, containerManager manager.Manager, authenticator *auth.DigestAuth, urlBasePrefix string) error {
104116
// Register the handler for the containers page.
105117
if authenticator != nil {
106118
mux.HandleFunc(ContainersPage, authenticator.Wrap(containerHandler(containerManager)))
107119
mux.HandleFunc(DockerPage, authenticator.Wrap(dockerHandler(containerManager)))
120+
mux.HandleFunc(PodmanPage, authenticator.Wrap(podmanHandler(containerManager)))
108121
} else {
109122
mux.HandleFunc(ContainersPage, containerHandlerNoAuth(containerManager))
110123
mux.HandleFunc(DockerPage, dockerHandlerNoAuth(containerManager))
124+
mux.HandleFunc(PodmanPage, podmanHandlerNoAuth(containerManager))
111125
}
112126

113127
if ContainersPage[len(ContainersPage)-1] == '/' {
@@ -118,6 +132,10 @@ func RegisterHandlersDigest(mux httpmux.Mux, containerManager manager.Manager, a
118132
redirectHandler := http.RedirectHandler(urlBasePrefix+DockerPage, http.StatusMovedPermanently)
119133
mux.Handle(DockerPage[0:len(DockerPage)-1], redirectHandler)
120134
}
135+
if PodmanPage[len(PodmanPage)-1] == '/' {
136+
redirectHandler := http.RedirectHandler(urlBasePrefix+PodmanPage, http.StatusMovedPermanently)
137+
mux.Handle(PodmanPage[0:len(PodmanPage)-1], redirectHandler)
138+
}
121139

122140
return nil
123141
}
@@ -127,9 +145,11 @@ func RegisterHandlersBasic(mux httpmux.Mux, containerManager manager.Manager, au
127145
if authenticator != nil {
128146
mux.HandleFunc(ContainersPage, authenticator.Wrap(containerHandler(containerManager)))
129147
mux.HandleFunc(DockerPage, authenticator.Wrap(dockerHandler(containerManager)))
148+
mux.HandleFunc(PodmanPage, authenticator.Wrap(podmanHandler(containerManager)))
130149
} else {
131150
mux.HandleFunc(ContainersPage, containerHandlerNoAuth(containerManager))
132151
mux.HandleFunc(DockerPage, dockerHandlerNoAuth(containerManager))
152+
mux.HandleFunc(PodmanPage, podmanHandlerNoAuth(containerManager))
133153
}
134154

135155
if ContainersPage[len(ContainersPage)-1] == '/' {

cmd/internal/pages/podman.go

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// Copyright 2021 Google Inc. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package pages
16+
17+
import (
18+
"fmt"
19+
"net/http"
20+
"net/url"
21+
"path"
22+
"time"
23+
24+
dockerutil "github.com/google/cadvisor/container/docker/utils"
25+
"github.com/google/cadvisor/container/podman"
26+
info "github.com/google/cadvisor/info/v1"
27+
"github.com/google/cadvisor/manager"
28+
29+
"k8s.io/klog/v2"
30+
)
31+
32+
const PodmanPage = "/podman/"
33+
34+
func servePodmanPage(m manager.Manager, w http.ResponseWriter, u *url.URL) {
35+
start := time.Now()
36+
37+
containerName := u.Path[len(PodmanPage)-1:]
38+
rootDir := getRootDir(containerName)
39+
40+
var data *pageData
41+
42+
if containerName == "/" {
43+
// Scenario for all containers.
44+
status, err := podman.Status()
45+
if err != nil {
46+
http.Error(w, fmt.Sprintf("failed to get podman info: %v", err), http.StatusInternalServerError)
47+
return
48+
}
49+
images, err := podman.Images()
50+
if err != nil {
51+
http.Error(w, fmt.Sprintf("failed to get podman images: %v", err), http.StatusInternalServerError)
52+
return
53+
}
54+
55+
reqParams := info.ContainerInfoRequest{
56+
NumStats: 0,
57+
}
58+
conts, err := m.AllPodmanContainers(&reqParams)
59+
if err != nil {
60+
http.Error(w, fmt.Sprintf("failed to get container %q with error: %v", containerName, err), http.StatusNotFound)
61+
return
62+
}
63+
subcontainers := make([]link, 0, len(conts))
64+
for _, cont := range conts {
65+
subcontainers = append(subcontainers, link{
66+
Text: getContainerDisplayName(cont.ContainerReference),
67+
Link: path.Join(rootDir, PodmanPage, dockerutil.ContainerNameToId(cont.ContainerReference.Name)),
68+
})
69+
}
70+
71+
podmanStatus, driverStatus := toStatusKV(status)
72+
73+
podmanContainerText := "Podman Containers"
74+
data = &pageData{
75+
DisplayName: podmanContainerText,
76+
ParentContainers: []link{
77+
{
78+
Text: podmanContainerText,
79+
Link: path.Join(rootDir, PodmanPage),
80+
}},
81+
Subcontainers: subcontainers,
82+
Root: rootDir,
83+
DockerStatus: podmanStatus,
84+
DockerDriverStatus: driverStatus,
85+
DockerImages: images,
86+
}
87+
} else {
88+
// Scenario for specific container.
89+
machineInfo, err := m.GetMachineInfo()
90+
if err != nil {
91+
http.Error(w, fmt.Sprintf("failed to get machine info: %v", err), http.StatusInternalServerError)
92+
return
93+
}
94+
95+
reqParams := info.ContainerInfoRequest{
96+
NumStats: 60,
97+
}
98+
cont, err := m.PodmanContainer(containerName[1:], &reqParams)
99+
if err != nil {
100+
http.Error(w, fmt.Sprintf("failed to get container %v with error: %v", containerName, err), http.StatusNotFound)
101+
return
102+
}
103+
displayName := getContainerDisplayName(cont.ContainerReference)
104+
105+
var parentContainers []link
106+
parentContainers = append(parentContainers, link{
107+
Text: "Podman Containers",
108+
Link: path.Join(rootDir, PodmanPage),
109+
})
110+
parentContainers = append(parentContainers, link{
111+
Text: displayName,
112+
Link: path.Join(rootDir, PodmanPage, dockerutil.ContainerNameToId(cont.Name)),
113+
})
114+
115+
data = &pageData{
116+
DisplayName: displayName,
117+
ContainerName: escapeContainerName(cont.Name),
118+
ParentContainers: parentContainers,
119+
Spec: cont.Spec,
120+
Stats: cont.Stats,
121+
MachineInfo: machineInfo,
122+
ResourcesAvailable: cont.Spec.HasCpu || cont.Spec.HasMemory || cont.Spec.HasNetwork,
123+
CpuAvailable: cont.Spec.HasCpu,
124+
MemoryAvailable: cont.Spec.HasMemory,
125+
NetworkAvailable: cont.Spec.HasNetwork,
126+
FsAvailable: cont.Spec.HasFilesystem,
127+
CustomMetricsAvailable: cont.Spec.HasCustomMetrics,
128+
Root: rootDir,
129+
}
130+
}
131+
132+
err := pageTemplate.Execute(w, data)
133+
if err != nil {
134+
klog.Errorf("Failed to apply template: %s", err)
135+
}
136+
137+
klog.V(5).Infof("Request took %s", time.Since(start))
138+
}

cmd/internal/pages/templates.go

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/runtime_options.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ From [glog](https://github.com/golang/glog) here are some flags we find useful:
6363
--docker-tls-ca="ca.pem": trusted CA for TLS-connection with docker
6464
```
6565

66+
## Podman
67+
68+
```bash
69+
--podman="unix:///var/run/podman/podman.sock": podman endpoint (default "unix:///var/run/podman/podman.sock")
70+
```
71+
6672
## Housekeeping
6773

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

0 commit comments

Comments
 (0)