github.com/containers/podman/v5@v5.1.0-rc1/test/e2e/events_test.go (about)

     1  package integration
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"strconv"
     7  	"sync"
     8  	"time"
     9  
    10  	"github.com/containers/podman/v5/cmd/podman/system"
    11  	. "github.com/containers/podman/v5/test/utils"
    12  	"github.com/containers/storage/pkg/stringid"
    13  	. "github.com/onsi/ginkgo/v2"
    14  	. "github.com/onsi/gomega"
    15  )
    16  
    17  var _ = Describe("Podman events", func() {
    18  
    19  	// For most, all, of these tests we do not "live" test following a log because it may make a fragile test
    20  	// system more complex.  Instead we run the "events" and then verify that the events are processed correctly.
    21  	// Perhaps a future version of this test would put events in a go func and send output back over a channel
    22  	// while events occur.
    23  
    24  	It("podman events", func() {
    25  		_, ec, _ := podmanTest.RunLsContainer("")
    26  		Expect(ec).To(Equal(0))
    27  		result := podmanTest.Podman([]string{"events", "--stream=false"})
    28  		result.WaitWithDefaultTimeout()
    29  		Expect(result).Should(ExitCleanly())
    30  	})
    31  
    32  	It("podman events with an event filter", func() {
    33  		_, ec, _ := podmanTest.RunLsContainer("")
    34  		Expect(ec).To(Equal(0))
    35  		result := podmanTest.Podman([]string{"events", "--stream=false", "--filter", "event=start"})
    36  		result.WaitWithDefaultTimeout()
    37  		Expect(result).Should(ExitCleanly())
    38  		Expect(result.OutputToStringArray()).ToNot(BeEmpty(), "Number of events")
    39  		date := time.Now().Format("2006-01-02")
    40  		Expect(result.OutputToStringArray()).To(ContainElement(HavePrefix(date)), "event log has correct timestamp")
    41  	})
    42  	It("podman events with a volume filter", func() {
    43  		_, ec, vname := podmanTest.CreateVolume(nil)
    44  		Expect(ec).To(Equal(0))
    45  
    46  		// Run two event commands - one with the full volume name and the second with the prefix
    47  		result := podmanTest.Podman([]string{"events", "--stream=false", "--filter", fmt.Sprintf("volume=%s", vname)})
    48  		resultPrefix := podmanTest.Podman([]string{"events", "--stream=false", "--filter", fmt.Sprintf("volume=%s", vname[:5])})
    49  
    50  		result.WaitWithDefaultTimeout()
    51  		Expect(result).Should(ExitCleanly())
    52  		events := result.OutputToStringArray()
    53  		Expect(events).To(HaveLen(1), "number of events")
    54  		Expect(events[0]).To(ContainSubstring(vname), "event log includes volume name")
    55  
    56  		resultPrefix.WaitWithDefaultTimeout()
    57  		Expect(resultPrefix).Should(ExitCleanly())
    58  		events = resultPrefix.OutputToStringArray()
    59  		Expect(events).To(HaveLen(1), "number of events")
    60  		Expect(events[0]).To(ContainSubstring(vname), "event log includes volume name")
    61  	})
    62  
    63  	It("podman events with an event filter and container=cid", func() {
    64  		_, ec, cid := podmanTest.RunLsContainer("")
    65  		Expect(ec).To(Equal(0))
    66  		_, ec2, cid2 := podmanTest.RunLsContainer("")
    67  		Expect(ec2).To(Equal(0))
    68  		time.Sleep(5 * time.Second)
    69  		result := podmanTest.Podman([]string{"events", "--stream=false", "--filter", "event=start", "--filter", fmt.Sprintf("container=%s", cid)})
    70  		result.WaitWithDefaultTimeout()
    71  		Expect(result).Should(ExitCleanly())
    72  		events := result.OutputToStringArray()
    73  		Expect(events).To(HaveLen(1), "number of events")
    74  		Expect(events[0]).To(ContainSubstring(cid), "event log includes CID")
    75  		Expect(events[0]).To(Not(ContainSubstring(cid2)), "event log does not include second CID")
    76  	})
    77  
    78  	It("podman events with a type and filter container=id", func() {
    79  		_, ec, cid := podmanTest.RunLsContainer("")
    80  		Expect(ec).To(Equal(0))
    81  		result := podmanTest.Podman([]string{"events", "--stream=false", "--filter", "type=pod", "--filter", fmt.Sprintf("container=%s", cid)})
    82  		result.WaitWithDefaultTimeout()
    83  		Expect(result).Should(ExitCleanly())
    84  		Expect(result.OutputToStringArray()).To(BeEmpty())
    85  	})
    86  
    87  	It("podman events with a type", func() {
    88  		setup := podmanTest.Podman([]string{"run", "-dt", "--pod", "new:foobarpod", ALPINE, "top"})
    89  		setup.WaitWithDefaultTimeout()
    90  		Expect(setup).Should(ExitCleanly())
    91  
    92  		podmanTest.StopPod("foobarpod")
    93  
    94  		result := podmanTest.Podman([]string{"events", "--stream=false", "--filter", "type=pod", "--filter", "pod=foobarpod"})
    95  		result.WaitWithDefaultTimeout()
    96  		Expect(result).Should(ExitCleanly())
    97  		events := result.OutputToStringArray()
    98  		GinkgoWriter.Println(events)
    99  		Expect(len(events)).To(BeNumerically(">=", 2), "Number of events")
   100  		Expect(events).To(ContainElement(ContainSubstring(" pod create ")))
   101  		Expect(events).To(ContainElement(ContainSubstring(" pod stop ")))
   102  		Expect(events).To(ContainElement(ContainSubstring("name=foobarpod")))
   103  	})
   104  
   105  	It("podman events --since", func() {
   106  		_, ec, _ := podmanTest.RunLsContainer("")
   107  		Expect(ec).To(Equal(0))
   108  		result := podmanTest.Podman([]string{"events", "--stream=false", "--since", "1m"})
   109  		result.WaitWithDefaultTimeout()
   110  		Expect(result).Should(ExitCleanly())
   111  	})
   112  
   113  	It("podman events --until", func() {
   114  		_, ec, _ := podmanTest.RunLsContainer("")
   115  		Expect(ec).To(Equal(0))
   116  		result := podmanTest.Podman([]string{"events", "--stream=false", "--until", "1h"})
   117  		result.WaitWithDefaultTimeout()
   118  		Expect(result).Should(ExitCleanly())
   119  	})
   120  
   121  	It("podman events format", func() {
   122  		start := time.Now()
   123  		ctrName := "testCtr"
   124  		_, ec, _ := podmanTest.RunLsContainer(ctrName)
   125  		end := time.Now()
   126  		Expect(ec).To(Equal(0))
   127  
   128  		test := podmanTest.Podman([]string{"events", "--stream=false", "--format", "json"})
   129  		test.WaitWithDefaultTimeout()
   130  		Expect(test).To(ExitCleanly())
   131  
   132  		jsonArr := test.OutputToStringArray()
   133  		Expect(test.OutputToStringArray()).ShouldNot(BeEmpty())
   134  
   135  		event := system.Event{}
   136  		err := json.Unmarshal([]byte(jsonArr[0]), &event)
   137  		Expect(err).ToNot(HaveOccurred())
   138  
   139  		test = podmanTest.Podman([]string{
   140  			"events",
   141  			"--stream=false",
   142  			"--since", strconv.FormatInt(start.Unix(), 10),
   143  			"--filter", fmt.Sprintf("container=%s", ctrName),
   144  			"--format", "{{json .}}",
   145  		})
   146  
   147  		test.WaitWithDefaultTimeout()
   148  		Expect(test).To(ExitCleanly())
   149  
   150  		jsonArr = test.OutputToStringArray()
   151  		Expect(test.OutputToStringArray()).ShouldNot(BeEmpty())
   152  
   153  		event = system.Event{}
   154  		err = json.Unmarshal([]byte(jsonArr[0]), &event)
   155  		Expect(err).ToNot(HaveOccurred())
   156  
   157  		Expect(event.Time).To(BeNumerically(">=", start.Unix()))
   158  		Expect(event.Time).To(BeNumerically("<=", end.Unix()))
   159  		Expect(event.TimeNano).To(BeNumerically(">=", start.UnixNano()))
   160  		Expect(event.TimeNano).To(BeNumerically("<=", end.UnixNano()))
   161  		Expect(time.Unix(0, event.TimeNano).Unix()).To(BeEquivalentTo(event.Time))
   162  
   163  		test = podmanTest.Podman([]string{"events", "--stream=false", "--filter=type=container", "--format", "ID: {{.ID}}"})
   164  		test.WaitWithDefaultTimeout()
   165  		Expect(test).To(ExitCleanly())
   166  		arr := test.OutputToStringArray()
   167  		Expect(len(arr)).To(BeNumerically(">", 1))
   168  		Expect(arr[0]).To(MatchRegexp("ID: [a-fA-F0-9]{64}"))
   169  	})
   170  
   171  	It("podman events --until future", func() {
   172  		name1 := stringid.GenerateRandomID()
   173  		name2 := stringid.GenerateRandomID()
   174  		name3 := stringid.GenerateRandomID()
   175  		session := podmanTest.Podman([]string{"create", "--name", name1, ALPINE})
   176  		session.WaitWithDefaultTimeout()
   177  		Expect(session).Should(ExitCleanly())
   178  
   179  		var wg sync.WaitGroup
   180  		wg.Add(1)
   181  		go func() {
   182  			defer GinkgoRecover()
   183  			defer wg.Done()
   184  
   185  			// wait 2 seconds to be sure events is running
   186  			time.Sleep(time.Second * 2)
   187  			session = podmanTest.Podman([]string{"create", "--name", name2, ALPINE})
   188  			session.WaitWithDefaultTimeout()
   189  			Expect(session).Should(ExitCleanly())
   190  			session = podmanTest.Podman([]string{"create", "--name", name3, ALPINE})
   191  			session.WaitWithDefaultTimeout()
   192  			Expect(session).Should(ExitCleanly())
   193  		}()
   194  
   195  		// unix timestamp in 10 seconds
   196  		until := time.Now().Add(time.Second * 10).Unix()
   197  		result := podmanTest.Podman([]string{"events", "--since", "30s", "--until", strconv.FormatInt(until, 10)})
   198  		result.Wait(11)
   199  		Expect(result).Should(ExitCleanly())
   200  		Expect(result.OutputToString()).To(ContainSubstring(name1))
   201  		Expect(result.OutputToString()).To(ContainSubstring(name2))
   202  		Expect(result.OutputToString()).To(ContainSubstring(name3))
   203  
   204  		// string duration in 10 seconds
   205  		untilT := time.Now().Add(time.Second * 9)
   206  		result = podmanTest.Podman([]string{"events", "--since", "30s", "--until", "10s"})
   207  		result.Wait(11)
   208  		Expect(result).Should(ExitCleanly())
   209  		tEnd := time.Now()
   210  		outDur := tEnd.Sub(untilT)
   211  		Expect(outDur.Seconds()).To(BeNumerically(">", 0), "duration")
   212  		Expect(result.OutputToString()).To(ContainSubstring(name1))
   213  		Expect(result.OutputToString()).To(ContainSubstring(name2))
   214  		Expect(result.OutputToString()).To(ContainSubstring(name3))
   215  
   216  		wg.Wait()
   217  	})
   218  
   219  	It("podman events pod creation", func() {
   220  		create := podmanTest.Podman([]string{"pod", "create", "--infra=false", "--name", "foobarpod"})
   221  		create.WaitWithDefaultTimeout()
   222  		Expect(create).Should(ExitCleanly())
   223  		id := create.OutputToString()
   224  		result := podmanTest.Podman([]string{"events", "--stream=false", "--filter", "pod=" + id})
   225  		result.WaitWithDefaultTimeout()
   226  		Expect(result).Should(ExitCleanly())
   227  		Expect(result.OutputToStringArray()).To(HaveLen(1))
   228  		Expect(result.OutputToString()).To(ContainSubstring("create"))
   229  
   230  		ctrName := "testCtr"
   231  		run := podmanTest.Podman([]string{"create", "--pod", id, "--name", ctrName, ALPINE, "top"})
   232  		run.WaitWithDefaultTimeout()
   233  		Expect(run).Should(ExitCleanly())
   234  
   235  		result2 := podmanTest.Podman([]string{"events", "--stream=false", "--filter", fmt.Sprintf("container=%s", ctrName), "--since", "30s"})
   236  		result2.WaitWithDefaultTimeout()
   237  		Expect(result2).Should(ExitCleanly())
   238  		Expect(result2.OutputToString()).To(ContainSubstring(fmt.Sprintf("pod_id=%s", id)))
   239  	})
   240  
   241  	It("podman events network connection", func() {
   242  		network := stringid.GenerateRandomID()
   243  		result := podmanTest.Podman([]string{"create", "--network", "bridge", ALPINE, "top"})
   244  		result.WaitWithDefaultTimeout()
   245  		Expect(result).Should(ExitCleanly())
   246  		ctrID := result.OutputToString()
   247  
   248  		result = podmanTest.Podman([]string{"network", "create", network})
   249  		result.WaitWithDefaultTimeout()
   250  		Expect(result).Should(ExitCleanly())
   251  
   252  		result = podmanTest.Podman([]string{"network", "connect", network, ctrID})
   253  		result.WaitWithDefaultTimeout()
   254  		Expect(result).Should(ExitCleanly())
   255  
   256  		result = podmanTest.Podman([]string{"network", "disconnect", network, ctrID})
   257  		result.WaitWithDefaultTimeout()
   258  		Expect(result).Should(ExitCleanly())
   259  
   260  		result = podmanTest.Podman([]string{"events", "--stream=false", "--since", "30s"})
   261  		result.WaitWithDefaultTimeout()
   262  		Expect(result).Should(ExitCleanly())
   263  		lines := result.OutputToStringArray()
   264  		Expect(lines).To(HaveLen(5))
   265  		Expect(lines[3]).To(ContainSubstring("network connect"))
   266  		Expect(lines[3]).To(ContainSubstring(fmt.Sprintf("(container=%s, name=%s)", ctrID, network)))
   267  		Expect(lines[4]).To(ContainSubstring("network disconnect"))
   268  		Expect(lines[4]).To(ContainSubstring(fmt.Sprintf("(container=%s, name=%s)", ctrID, network)))
   269  	})
   270  
   271  	It("podman events health_status generated", func() {
   272  		session := podmanTest.Podman([]string{"run", "--name", "test-hc", "-dt", "--health-cmd", "echo working", "busybox"})
   273  		session.WaitWithDefaultTimeout()
   274  		Expect(session).Should(ExitCleanly())
   275  
   276  		for i := 0; i < 5; i++ {
   277  			hc := podmanTest.Podman([]string{"healthcheck", "run", "test-hc"})
   278  			hc.WaitWithDefaultTimeout()
   279  			exitCode := hc.ExitCode()
   280  			if exitCode == 0 || i == 4 {
   281  				break
   282  			}
   283  			time.Sleep(1 * time.Second)
   284  		}
   285  
   286  		result := podmanTest.Podman([]string{"events", "--stream=false", "--filter", "event=health_status", "--since", "1m"})
   287  		result.WaitWithDefaultTimeout()
   288  		Expect(result).Should(ExitCleanly())
   289  		Expect(result.OutputToStringArray()).ToNot(BeEmpty(), "Number of health_status events")
   290  	})
   291  
   292  })