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