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  })