github.com/containers/podman/v5@v5.1.0-rc1/test/e2e/stats_test.go (about) 1 package integration 2 3 import ( 4 "fmt" 5 "strconv" 6 "time" 7 8 . "github.com/containers/podman/v5/test/utils" 9 . "github.com/onsi/ginkgo/v2" 10 . "github.com/onsi/gomega" 11 ) 12 13 // TODO: we need to check the output. Currently, we only check the exit codes 14 // which is not enough. 15 var _ = Describe("Podman stats", func() { 16 17 BeforeEach(func() { 18 SkipIfRootlessCgroupsV1("stats not supported on cgroupv1 for rootless users") 19 if isContainerized() { 20 SkipIfCgroupV1("stats not supported inside cgroupv1 container environment") 21 } 22 }) 23 24 It("podman stats with bogus container", func() { 25 session := podmanTest.Podman([]string{"stats", "--no-stream", "123"}) 26 session.WaitWithDefaultTimeout() 27 expect := `unable to get list of containers: unable to look up container 123: no container with name or ID "123" found: no such container` 28 // FIXME: #22612 29 if IsRemote() { 30 expect = "types.ContainerStatsReport.Error: decode non empty interface: can not unmarshal into nil, error found in #9 byte" 31 } 32 Expect(session).Should(ExitWithError(125, expect)) 33 }) 34 35 It("podman stats on a running container", func() { 36 session := podmanTest.RunTopContainer("") 37 session.WaitWithDefaultTimeout() 38 Expect(session).Should(ExitCleanly()) 39 cid := session.OutputToString() 40 session = podmanTest.Podman([]string{"stats", "--no-stream", cid}) 41 session.WaitWithDefaultTimeout() 42 Expect(session).Should(ExitCleanly()) 43 }) 44 45 It("podman stats on all containers", func() { 46 session := podmanTest.RunTopContainer("") 47 session.WaitWithDefaultTimeout() 48 Expect(session).Should(ExitCleanly()) 49 session = podmanTest.Podman([]string{"stats", "--no-stream", "-a"}) 50 session.WaitWithDefaultTimeout() 51 Expect(session).Should(ExitCleanly()) 52 }) 53 54 It("podman stats on all running containers", func() { 55 session := podmanTest.RunTopContainer("") 56 session.WaitWithDefaultTimeout() 57 Expect(session).Should(ExitCleanly()) 58 session = podmanTest.Podman([]string{"stats", "--no-stream"}) 59 session.WaitWithDefaultTimeout() 60 Expect(session).Should(ExitCleanly()) 61 }) 62 63 It("podman stats only output cids", func() { 64 session := podmanTest.RunTopContainer("") 65 session.WaitWithDefaultTimeout() 66 Expect(session).Should(ExitCleanly()) 67 session = podmanTest.Podman([]string{"stats", "--all", "--no-trunc", "--no-stream", "--format", "\"{{.ID}}\""}) 68 session.WaitWithDefaultTimeout() 69 Expect(session).Should(ExitCleanly()) 70 Expect(len(session.OutputToStringArray()[0])).Should(BeEquivalentTo(66)) 71 }) 72 73 It("podman stats with GO template", func() { 74 session := podmanTest.RunTopContainer("") 75 session.WaitWithDefaultTimeout() 76 Expect(session).Should(ExitCleanly()) 77 stats := podmanTest.Podman([]string{"stats", "-a", "--no-reset", "--no-stream", "--format", "table {{.ID}} {{.AVGCPU}} {{.MemUsage}} {{.CPU}} {{.NetIO}} {{.BlockIO}} {{.PIDS}}"}) 78 stats.WaitWithDefaultTimeout() 79 Expect(stats).To(ExitCleanly()) 80 }) 81 82 It("podman stats with invalid GO template", func() { 83 session := podmanTest.RunTopContainer("") 84 session.WaitWithDefaultTimeout() 85 Expect(session).Should(ExitCleanly()) 86 stats := podmanTest.Podman([]string{"stats", "-a", "--no-reset", "--no-stream", "--format", "\"table {{.ID}} {{.NoSuchField}} \""}) 87 stats.WaitWithDefaultTimeout() 88 Expect(stats).To(ExitWithError(125, `template: stats:1:28: executing "stats" at <.NoSuchField>: can't evaluate field NoSuchField in type containers.containerStats`)) 89 }) 90 91 It("podman stats with negative interval", func() { 92 session := podmanTest.RunTopContainer("") 93 session.WaitWithDefaultTimeout() 94 Expect(session).Should(ExitCleanly()) 95 stats := podmanTest.Podman([]string{"stats", "-a", "--no-reset", "--no-stream", "--interval=-1"}) 96 stats.WaitWithDefaultTimeout() 97 Expect(stats).To(ExitWithError(125, "invalid interval, must be a positive number greater zero")) 98 }) 99 100 It("podman stats with zero interval", func() { 101 session := podmanTest.RunTopContainer("") 102 session.WaitWithDefaultTimeout() 103 Expect(session).Should(ExitCleanly()) 104 stats := podmanTest.Podman([]string{"stats", "-a", "--no-reset", "--no-stream", "--interval=0"}) 105 stats.WaitWithDefaultTimeout() 106 Expect(stats).To(ExitWithError(125, "invalid interval, must be a positive number greater zero")) 107 }) 108 109 It("podman stats with interval", func() { 110 session := podmanTest.RunTopContainer("") 111 session.WaitWithDefaultTimeout() 112 Expect(session).Should(ExitCleanly()) 113 stats := podmanTest.Podman([]string{"stats", "-a", "--no-reset", "--no-stream", "--interval=5"}) 114 stats.WaitWithDefaultTimeout() 115 Expect(stats).Should(ExitCleanly()) 116 }) 117 118 It("podman stats with json output", func() { 119 var found bool 120 session := podmanTest.RunTopContainer("") 121 session.WaitWithDefaultTimeout() 122 Expect(session).Should(ExitCleanly()) 123 for i := 0; i < 5; i++ { 124 ps := podmanTest.Podman([]string{"ps", "-q"}) 125 ps.WaitWithDefaultTimeout() 126 if len(ps.OutputToStringArray()) == 1 { 127 found = true 128 break 129 } 130 time.Sleep(time.Second) 131 } 132 Expect(found).To(BeTrue(), "container has started") 133 stats := podmanTest.Podman([]string{"stats", "--all", "--no-stream", "--format", "json"}) 134 stats.WaitWithDefaultTimeout() 135 Expect(stats).Should(ExitCleanly()) 136 Expect(stats.OutputToString()).To(BeValidJSON()) 137 }) 138 139 It("podman stats on a container with no net ns", func() { 140 session := podmanTest.Podman([]string{"run", "-d", "--net", "none", ALPINE, "top"}) 141 session.WaitWithDefaultTimeout() 142 Expect(session).Should(ExitCleanly()) 143 session = podmanTest.Podman([]string{"stats", "--no-stream", "-a"}) 144 session.WaitWithDefaultTimeout() 145 Expect(session).Should(ExitCleanly()) 146 }) 147 148 It("podman stats on a container that joined another's net ns", func() { 149 session := podmanTest.RunTopContainer("") 150 session.WaitWithDefaultTimeout() 151 Expect(session).Should(ExitCleanly()) 152 cid := session.OutputToString() 153 154 session = podmanTest.Podman([]string{"run", "-d", "--net", fmt.Sprintf("container:%s", cid), ALPINE, "top"}) 155 session.WaitWithDefaultTimeout() 156 Expect(session).Should(ExitCleanly()) 157 158 session = podmanTest.Podman([]string{"stats", "--no-stream", "-a"}) 159 session.WaitWithDefaultTimeout() 160 Expect(session).Should(ExitCleanly()) 161 }) 162 163 It("podman stats on container with forced slirp4netns", func() { 164 // This will force the slirp4netns net mode to be tested as root 165 session := podmanTest.Podman([]string{"run", "-d", "--net", "slirp4netns", ALPINE, "top"}) 166 session.WaitWithDefaultTimeout() 167 Expect(session).Should(ExitCleanly()) 168 session = podmanTest.Podman([]string{"stats", "--no-stream", "-a"}) 169 session.WaitWithDefaultTimeout() 170 Expect(session).Should(ExitCleanly()) 171 }) 172 173 It("podman reads slirp4netns network stats", func() { 174 session := podmanTest.Podman([]string{"run", "-d", "--network", "slirp4netns", ALPINE, "top"}) 175 session.WaitWithDefaultTimeout() 176 Expect(session).Should(ExitCleanly()) 177 178 cid := session.OutputToString() 179 180 stats := podmanTest.Podman([]string{"stats", "--format", "'{{.NetIO}}'", "--no-stream", cid}) 181 stats.WaitWithDefaultTimeout() 182 Expect(stats).Should(ExitCleanly()) 183 Expect(stats.OutputToString()).To(Not(ContainSubstring("-- / --"))) 184 }) 185 186 // Regression test for #8265 187 It("podman stats with custom memory limits", func() { 188 // Run three containers. One with a memory limit. Make sure 189 // that the limits are different and the limited one has a 190 // lower limit. 191 ctrNoLimit0 := "no-limit-0" 192 ctrNoLimit1 := "no-limit-1" 193 ctrWithLimit := "with-limit" 194 195 session := podmanTest.Podman([]string{"run", "-d", "--name", ctrNoLimit0, ALPINE, "top"}) 196 session.WaitWithDefaultTimeout() 197 Expect(session).Should(ExitCleanly()) 198 199 session = podmanTest.Podman([]string{"run", "-d", "--name", ctrNoLimit1, ALPINE, "top"}) 200 session.WaitWithDefaultTimeout() 201 Expect(session).Should(ExitCleanly()) 202 203 session = podmanTest.Podman([]string{"run", "-d", "--name", ctrWithLimit, "--memory", "50m", ALPINE, "top"}) 204 session.WaitWithDefaultTimeout() 205 Expect(session).Should(ExitCleanly()) 206 207 session = podmanTest.Podman([]string{"stats", "--no-stream", "--format", "{{.MemLimit}}", ctrNoLimit0, ctrNoLimit1, ctrWithLimit}) 208 session.WaitWithDefaultTimeout() 209 Expect(session).Should(ExitCleanly()) 210 211 // We have three containers. The unlimited ones need to have 212 // the same limit, the limited one a lower one. 213 limits := session.OutputToStringArray() 214 Expect(limits).To(HaveLen(3)) 215 Expect(limits[0]).To(Equal(limits[1])) 216 Expect(limits[0]).ToNot(Equal(limits[2])) 217 218 defaultLimit, err := strconv.Atoi(limits[0]) 219 Expect(err).ToNot(HaveOccurred()) 220 customLimit, err := strconv.Atoi(limits[2]) 221 Expect(err).ToNot(HaveOccurred()) 222 223 Expect(customLimit).To(BeNumerically("<", defaultLimit)) 224 }) 225 226 It("podman stats with a container that is not running", func() { 227 ctr := "created_container" 228 session := podmanTest.Podman([]string{"create", "--name", ctr, ALPINE}) 229 session.WaitWithDefaultTimeout() 230 Expect(session).Should(ExitCleanly()) 231 232 session = podmanTest.Podman([]string{"stats", "--no-stream", ctr}) 233 session.WaitWithDefaultTimeout() 234 Expect(session).Should(ExitCleanly()) 235 }) 236 237 It("podman stats show cgroup memory limit", func() { 238 ctrWithLimit := "with-limit" 239 240 session := podmanTest.Podman([]string{"run", "-d", "--name", ctrWithLimit, "--memory", "50m", ALPINE, "top"}) 241 session.WaitWithDefaultTimeout() 242 Expect(session).Should(ExitCleanly()) 243 244 session = podmanTest.Podman([]string{"stats", "--no-stream", "--format", "{{.MemLimit}}", ctrWithLimit}) 245 session.WaitWithDefaultTimeout() 246 Expect(session).Should(ExitCleanly()) 247 248 limit, err := strconv.Atoi(session.OutputToString()) 249 Expect(err).ToNot(HaveOccurred()) 250 Expect(limit).To(BeNumerically("==", 50*1024*1024)) 251 252 session = podmanTest.Podman([]string{"container", "update", ctrWithLimit, "--memory", "100m"}) 253 session.WaitWithDefaultTimeout() 254 Expect(session).Should(ExitCleanly()) 255 256 session = podmanTest.Podman([]string{"stats", "--no-stream", "--format", "{{.MemLimit}}", ctrWithLimit}) 257 session.WaitWithDefaultTimeout() 258 Expect(session).Should(ExitCleanly()) 259 260 limit, err = strconv.Atoi(session.OutputToString()) 261 Expect(err).ToNot(HaveOccurred()) 262 Expect(limit).To(BeNumerically("==", 100*1024*1024)) 263 }) 264 265 It("podman stats --all", func() { 266 runningContainersession := podmanTest.RunTopContainer("") 267 runningContainersession.WaitWithDefaultTimeout() 268 Expect(runningContainersession).Should(ExitCleanly()) 269 runningCtrID := runningContainersession.OutputToString()[0:12] 270 271 createdContainerSession, _, _ := podmanTest.CreatePod(map[string][]string{ 272 "--infra": {"true"}, 273 }) 274 275 createdContainerSession.WaitWithDefaultTimeout() 276 Expect(createdContainerSession).Should(ExitCleanly()) 277 278 sessionAll := podmanTest.Podman([]string{"stats", "--no-stream", "--format", "{{.ID}}"}) 279 sessionAll.WaitWithDefaultTimeout() 280 Expect(sessionAll).Should(ExitCleanly()) 281 Expect(sessionAll.OutputToString()).Should(Equal(runningCtrID)) 282 283 sessionAll = podmanTest.Podman([]string{"stats", "--no-stream", "--all=false", "--format", "{{.ID}}"}) 284 sessionAll.WaitWithDefaultTimeout() 285 Expect(sessionAll).Should(ExitCleanly()) 286 Expect(sessionAll.OutputToString()).Should(Equal(runningCtrID)) 287 288 sessionAll = podmanTest.Podman([]string{"stats", "--all=true", "--no-stream", "--format", "{{.ID}}"}) 289 sessionAll.WaitWithDefaultTimeout() 290 Expect(sessionAll).Should(ExitCleanly()) 291 Expect(sessionAll.OutputToStringArray()).Should(HaveLen(2)) 292 293 sessionAll = podmanTest.Podman([]string{"stats", "--all", "--no-stream", "--format", "{{.ID}}"}) 294 sessionAll.WaitWithDefaultTimeout() 295 Expect(sessionAll).Should(ExitCleanly()) 296 Expect(sessionAll.OutputToStringArray()).Should(HaveLen(2)) 297 }) 298 })