github.com/rita33cool1/iot-system-gateway@v0.0.0-20200911033302-e65bde238cc5/docker-engine/integration-cli/docker_cli_events_test.go (about)

     1  package main
     2  
     3  import (
     4  	"bufio"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io"
     8  	"io/ioutil"
     9  	"os"
    10  	"os/exec"
    11  	"strings"
    12  	"time"
    13  
    14  	"github.com/docker/docker/api/types"
    15  	eventtypes "github.com/docker/docker/api/types/events"
    16  	"github.com/docker/docker/client"
    17  	eventstestutils "github.com/docker/docker/daemon/events/testutils"
    18  	"github.com/docker/docker/integration-cli/checker"
    19  	"github.com/docker/docker/integration-cli/cli"
    20  	"github.com/docker/docker/integration-cli/cli/build"
    21  	"github.com/go-check/check"
    22  	"github.com/gotestyourself/gotestyourself/icmd"
    23  	"golang.org/x/net/context"
    24  )
    25  
    26  func (s *DockerSuite) TestEventsTimestampFormats(c *check.C) {
    27  	name := "events-time-format-test"
    28  
    29  	// Start stopwatch, generate an event
    30  	start := daemonTime(c)
    31  	time.Sleep(1100 * time.Millisecond) // so that first event occur in different second from since (just for the case)
    32  	dockerCmd(c, "run", "--rm", "--name", name, "busybox", "true")
    33  	time.Sleep(1100 * time.Millisecond) // so that until > since
    34  	end := daemonTime(c)
    35  
    36  	// List of available time formats to --since
    37  	unixTs := func(t time.Time) string { return fmt.Sprintf("%v", t.Unix()) }
    38  	rfc3339 := func(t time.Time) string { return t.Format(time.RFC3339) }
    39  	duration := func(t time.Time) string { return time.Since(t).String() }
    40  
    41  	// --since=$start must contain only the 'untag' event
    42  	for _, f := range []func(time.Time) string{unixTs, rfc3339, duration} {
    43  		since, until := f(start), f(end)
    44  		out, _ := dockerCmd(c, "events", "--since="+since, "--until="+until)
    45  		events := strings.Split(out, "\n")
    46  		events = events[:len(events)-1]
    47  
    48  		nEvents := len(events)
    49  		c.Assert(nEvents, checker.GreaterOrEqualThan, 5) //Missing expected event
    50  		containerEvents := eventActionsByIDAndType(c, events, name, "container")
    51  		c.Assert(containerEvents, checker.HasLen, 5, check.Commentf("events: %v", events))
    52  
    53  		c.Assert(containerEvents[0], checker.Equals, "create", check.Commentf(out))
    54  		c.Assert(containerEvents[1], checker.Equals, "attach", check.Commentf(out))
    55  		c.Assert(containerEvents[2], checker.Equals, "start", check.Commentf(out))
    56  		c.Assert(containerEvents[3], checker.Equals, "die", check.Commentf(out))
    57  		c.Assert(containerEvents[4], checker.Equals, "destroy", check.Commentf(out))
    58  	}
    59  }
    60  
    61  func (s *DockerSuite) TestEventsUntag(c *check.C) {
    62  	image := "busybox"
    63  	dockerCmd(c, "tag", image, "utest:tag1")
    64  	dockerCmd(c, "tag", image, "utest:tag2")
    65  	dockerCmd(c, "rmi", "utest:tag1")
    66  	dockerCmd(c, "rmi", "utest:tag2")
    67  
    68  	result := icmd.RunCmd(icmd.Cmd{
    69  		Command: []string{dockerBinary, "events", "--since=1"},
    70  		Timeout: time.Millisecond * 2500,
    71  	})
    72  	result.Assert(c, icmd.Expected{Timeout: true})
    73  
    74  	events := strings.Split(result.Stdout(), "\n")
    75  	nEvents := len(events)
    76  	// The last element after the split above will be an empty string, so we
    77  	// get the two elements before the last, which are the untags we're
    78  	// looking for.
    79  	for _, v := range events[nEvents-3 : nEvents-1] {
    80  		c.Assert(v, checker.Contains, "untag", check.Commentf("event should be untag"))
    81  	}
    82  }
    83  
    84  func (s *DockerSuite) TestEventsContainerEvents(c *check.C) {
    85  	dockerCmd(c, "run", "--rm", "--name", "container-events-test", "busybox", "true")
    86  
    87  	out, _ := dockerCmd(c, "events", "--until", daemonUnixTime(c))
    88  	events := strings.Split(out, "\n")
    89  	events = events[:len(events)-1]
    90  
    91  	nEvents := len(events)
    92  	c.Assert(nEvents, checker.GreaterOrEqualThan, 5) //Missing expected event
    93  	containerEvents := eventActionsByIDAndType(c, events, "container-events-test", "container")
    94  	c.Assert(containerEvents, checker.HasLen, 5, check.Commentf("events: %v", events))
    95  
    96  	c.Assert(containerEvents[0], checker.Equals, "create", check.Commentf(out))
    97  	c.Assert(containerEvents[1], checker.Equals, "attach", check.Commentf(out))
    98  	c.Assert(containerEvents[2], checker.Equals, "start", check.Commentf(out))
    99  	c.Assert(containerEvents[3], checker.Equals, "die", check.Commentf(out))
   100  	c.Assert(containerEvents[4], checker.Equals, "destroy", check.Commentf(out))
   101  }
   102  
   103  func (s *DockerSuite) TestEventsContainerEventsAttrSort(c *check.C) {
   104  	since := daemonUnixTime(c)
   105  	dockerCmd(c, "run", "--rm", "--name", "container-events-test", "busybox", "true")
   106  
   107  	out, _ := dockerCmd(c, "events", "--filter", "container=container-events-test", "--since", since, "--until", daemonUnixTime(c))
   108  	events := strings.Split(out, "\n")
   109  
   110  	nEvents := len(events)
   111  	c.Assert(nEvents, checker.GreaterOrEqualThan, 3) //Missing expected event
   112  	matchedEvents := 0
   113  	for _, event := range events {
   114  		matches := eventstestutils.ScanMap(event)
   115  		if matches["eventType"] == "container" && matches["action"] == "create" {
   116  			matchedEvents++
   117  			c.Assert(out, checker.Contains, "(image=busybox, name=container-events-test)", check.Commentf("Event attributes not sorted"))
   118  		} else if matches["eventType"] == "container" && matches["action"] == "start" {
   119  			matchedEvents++
   120  			c.Assert(out, checker.Contains, "(image=busybox, name=container-events-test)", check.Commentf("Event attributes not sorted"))
   121  		}
   122  	}
   123  	c.Assert(matchedEvents, checker.Equals, 2, check.Commentf("missing events for container container-events-test:\n%s", out))
   124  }
   125  
   126  func (s *DockerSuite) TestEventsContainerEventsSinceUnixEpoch(c *check.C) {
   127  	dockerCmd(c, "run", "--rm", "--name", "since-epoch-test", "busybox", "true")
   128  	timeBeginning := time.Unix(0, 0).Format(time.RFC3339Nano)
   129  	timeBeginning = strings.Replace(timeBeginning, "Z", ".000000000Z", -1)
   130  	out, _ := dockerCmd(c, "events", "--since", timeBeginning, "--until", daemonUnixTime(c))
   131  	events := strings.Split(out, "\n")
   132  	events = events[:len(events)-1]
   133  
   134  	nEvents := len(events)
   135  	c.Assert(nEvents, checker.GreaterOrEqualThan, 5) //Missing expected event
   136  	containerEvents := eventActionsByIDAndType(c, events, "since-epoch-test", "container")
   137  	c.Assert(containerEvents, checker.HasLen, 5, check.Commentf("events: %v", events))
   138  
   139  	c.Assert(containerEvents[0], checker.Equals, "create", check.Commentf(out))
   140  	c.Assert(containerEvents[1], checker.Equals, "attach", check.Commentf(out))
   141  	c.Assert(containerEvents[2], checker.Equals, "start", check.Commentf(out))
   142  	c.Assert(containerEvents[3], checker.Equals, "die", check.Commentf(out))
   143  	c.Assert(containerEvents[4], checker.Equals, "destroy", check.Commentf(out))
   144  }
   145  
   146  func (s *DockerSuite) TestEventsImageTag(c *check.C) {
   147  	time.Sleep(1 * time.Second) // because API has seconds granularity
   148  	since := daemonUnixTime(c)
   149  	image := "testimageevents:tag"
   150  	dockerCmd(c, "tag", "busybox", image)
   151  
   152  	out, _ := dockerCmd(c, "events",
   153  		"--since", since, "--until", daemonUnixTime(c))
   154  
   155  	events := strings.Split(strings.TrimSpace(out), "\n")
   156  	c.Assert(events, checker.HasLen, 1, check.Commentf("was expecting 1 event. out=%s", out))
   157  	event := strings.TrimSpace(events[0])
   158  
   159  	matches := eventstestutils.ScanMap(event)
   160  	c.Assert(matchEventID(matches, image), checker.True, check.Commentf("matches: %v\nout:\n%s", matches, out))
   161  	c.Assert(matches["action"], checker.Equals, "tag")
   162  }
   163  
   164  func (s *DockerSuite) TestEventsImagePull(c *check.C) {
   165  	// TODO Windows: Enable this test once pull and reliable image names are available
   166  	testRequires(c, DaemonIsLinux)
   167  	since := daemonUnixTime(c)
   168  	testRequires(c, Network)
   169  
   170  	dockerCmd(c, "pull", "hello-world")
   171  
   172  	out, _ := dockerCmd(c, "events",
   173  		"--since", since, "--until", daemonUnixTime(c))
   174  
   175  	events := strings.Split(strings.TrimSpace(out), "\n")
   176  	event := strings.TrimSpace(events[len(events)-1])
   177  	matches := eventstestutils.ScanMap(event)
   178  	c.Assert(matches["id"], checker.Equals, "hello-world:latest")
   179  	c.Assert(matches["action"], checker.Equals, "pull")
   180  
   181  }
   182  
   183  func (s *DockerSuite) TestEventsImageImport(c *check.C) {
   184  	// TODO Windows CI. This should be portable once export/import are
   185  	// more reliable (@swernli)
   186  	testRequires(c, DaemonIsLinux)
   187  
   188  	out, _ := dockerCmd(c, "run", "-d", "busybox", "true")
   189  	cleanedContainerID := strings.TrimSpace(out)
   190  
   191  	since := daemonUnixTime(c)
   192  	out, err := RunCommandPipelineWithOutput(
   193  		exec.Command(dockerBinary, "export", cleanedContainerID),
   194  		exec.Command(dockerBinary, "import", "-"),
   195  	)
   196  	c.Assert(err, checker.IsNil, check.Commentf("import failed with output: %q", out))
   197  	imageRef := strings.TrimSpace(out)
   198  
   199  	out, _ = dockerCmd(c, "events", "--since", since, "--until", daemonUnixTime(c), "--filter", "event=import")
   200  	events := strings.Split(strings.TrimSpace(out), "\n")
   201  	c.Assert(events, checker.HasLen, 1)
   202  	matches := eventstestutils.ScanMap(events[0])
   203  	c.Assert(matches["id"], checker.Equals, imageRef, check.Commentf("matches: %v\nout:\n%s\n", matches, out))
   204  	c.Assert(matches["action"], checker.Equals, "import", check.Commentf("matches: %v\nout:\n%s\n", matches, out))
   205  }
   206  
   207  func (s *DockerSuite) TestEventsImageLoad(c *check.C) {
   208  	testRequires(c, DaemonIsLinux)
   209  	myImageName := "footest:v1"
   210  	dockerCmd(c, "tag", "busybox", myImageName)
   211  	since := daemonUnixTime(c)
   212  
   213  	out, _ := dockerCmd(c, "images", "-q", "--no-trunc", myImageName)
   214  	longImageID := strings.TrimSpace(out)
   215  	c.Assert(longImageID, checker.Not(check.Equals), "", check.Commentf("Id should not be empty"))
   216  
   217  	dockerCmd(c, "save", "-o", "saveimg.tar", myImageName)
   218  	dockerCmd(c, "rmi", myImageName)
   219  	out, _ = dockerCmd(c, "images", "-q", myImageName)
   220  	noImageID := strings.TrimSpace(out)
   221  	c.Assert(noImageID, checker.Equals, "", check.Commentf("Should not have any image"))
   222  	dockerCmd(c, "load", "-i", "saveimg.tar")
   223  
   224  	result := icmd.RunCommand("rm", "-rf", "saveimg.tar")
   225  	result.Assert(c, icmd.Success)
   226  
   227  	out, _ = dockerCmd(c, "images", "-q", "--no-trunc", myImageName)
   228  	imageID := strings.TrimSpace(out)
   229  	c.Assert(imageID, checker.Equals, longImageID, check.Commentf("Should have same image id as before"))
   230  
   231  	out, _ = dockerCmd(c, "events", "--since", since, "--until", daemonUnixTime(c), "--filter", "event=load")
   232  	events := strings.Split(strings.TrimSpace(out), "\n")
   233  	c.Assert(events, checker.HasLen, 1)
   234  	matches := eventstestutils.ScanMap(events[0])
   235  	c.Assert(matches["id"], checker.Equals, imageID, check.Commentf("matches: %v\nout:\n%s\n", matches, out))
   236  	c.Assert(matches["action"], checker.Equals, "load", check.Commentf("matches: %v\nout:\n%s\n", matches, out))
   237  
   238  	out, _ = dockerCmd(c, "events", "--since", since, "--until", daemonUnixTime(c), "--filter", "event=save")
   239  	events = strings.Split(strings.TrimSpace(out), "\n")
   240  	c.Assert(events, checker.HasLen, 1)
   241  	matches = eventstestutils.ScanMap(events[0])
   242  	c.Assert(matches["id"], checker.Equals, imageID, check.Commentf("matches: %v\nout:\n%s\n", matches, out))
   243  	c.Assert(matches["action"], checker.Equals, "save", check.Commentf("matches: %v\nout:\n%s\n", matches, out))
   244  }
   245  
   246  func (s *DockerSuite) TestEventsPluginOps(c *check.C) {
   247  	testRequires(c, DaemonIsLinux, IsAmd64, Network)
   248  
   249  	since := daemonUnixTime(c)
   250  
   251  	dockerCmd(c, "plugin", "install", pNameWithTag, "--grant-all-permissions")
   252  	dockerCmd(c, "plugin", "disable", pNameWithTag)
   253  	dockerCmd(c, "plugin", "remove", pNameWithTag)
   254  
   255  	out, _ := dockerCmd(c, "events", "--since", since, "--until", daemonUnixTime(c))
   256  	events := strings.Split(out, "\n")
   257  	events = events[:len(events)-1]
   258  
   259  	nEvents := len(events)
   260  	c.Assert(nEvents, checker.GreaterOrEqualThan, 4)
   261  
   262  	pluginEvents := eventActionsByIDAndType(c, events, pNameWithTag, "plugin")
   263  	c.Assert(pluginEvents, checker.HasLen, 4, check.Commentf("events: %v", events))
   264  
   265  	c.Assert(pluginEvents[0], checker.Equals, "pull", check.Commentf(out))
   266  	c.Assert(pluginEvents[1], checker.Equals, "enable", check.Commentf(out))
   267  	c.Assert(pluginEvents[2], checker.Equals, "disable", check.Commentf(out))
   268  	c.Assert(pluginEvents[3], checker.Equals, "remove", check.Commentf(out))
   269  }
   270  
   271  func (s *DockerSuite) TestEventsFilters(c *check.C) {
   272  	since := daemonUnixTime(c)
   273  	dockerCmd(c, "run", "--rm", "busybox", "true")
   274  	dockerCmd(c, "run", "--rm", "busybox", "true")
   275  	out, _ := dockerCmd(c, "events", "--since", since, "--until", daemonUnixTime(c), "--filter", "event=die")
   276  	parseEvents(c, out, "die")
   277  
   278  	out, _ = dockerCmd(c, "events", "--since", since, "--until", daemonUnixTime(c), "--filter", "event=die", "--filter", "event=start")
   279  	parseEvents(c, out, "die|start")
   280  
   281  	// make sure we at least got 2 start events
   282  	count := strings.Count(out, "start")
   283  	c.Assert(strings.Count(out, "start"), checker.GreaterOrEqualThan, 2, check.Commentf("should have had 2 start events but had %d, out: %s", count, out))
   284  
   285  }
   286  
   287  func (s *DockerSuite) TestEventsFilterImageName(c *check.C) {
   288  	since := daemonUnixTime(c)
   289  
   290  	out, _ := dockerCmd(c, "run", "--name", "container_1", "-d", "busybox:latest", "true")
   291  	container1 := strings.TrimSpace(out)
   292  
   293  	out, _ = dockerCmd(c, "run", "--name", "container_2", "-d", "busybox", "true")
   294  	container2 := strings.TrimSpace(out)
   295  
   296  	name := "busybox"
   297  	out, _ = dockerCmd(c, "events", "--since", since, "--until", daemonUnixTime(c), "--filter", fmt.Sprintf("image=%s", name))
   298  	events := strings.Split(out, "\n")
   299  	events = events[:len(events)-1]
   300  	c.Assert(events, checker.Not(checker.HasLen), 0) //Expected events but found none for the image busybox:latest
   301  	count1 := 0
   302  	count2 := 0
   303  
   304  	for _, e := range events {
   305  		if strings.Contains(e, container1) {
   306  			count1++
   307  		} else if strings.Contains(e, container2) {
   308  			count2++
   309  		}
   310  	}
   311  	c.Assert(count1, checker.Not(checker.Equals), 0, check.Commentf("Expected event from container but got %d from %s", count1, container1))
   312  	c.Assert(count2, checker.Not(checker.Equals), 0, check.Commentf("Expected event from container but got %d from %s", count2, container2))
   313  
   314  }
   315  
   316  func (s *DockerSuite) TestEventsFilterLabels(c *check.C) {
   317  	since := daemonUnixTime(c)
   318  	label := "io.docker.testing=foo"
   319  
   320  	out, _ := dockerCmd(c, "run", "-d", "-l", label, "busybox:latest", "true")
   321  	container1 := strings.TrimSpace(out)
   322  
   323  	out, _ = dockerCmd(c, "run", "-d", "busybox", "true")
   324  	container2 := strings.TrimSpace(out)
   325  
   326  	out, _ = dockerCmd(
   327  		c,
   328  		"events",
   329  		"--since", since,
   330  		"--until", daemonUnixTime(c),
   331  		"--filter", fmt.Sprintf("label=%s", label))
   332  
   333  	events := strings.Split(strings.TrimSpace(out), "\n")
   334  	c.Assert(len(events), checker.Equals, 3)
   335  
   336  	for _, e := range events {
   337  		c.Assert(e, checker.Contains, container1)
   338  		c.Assert(e, checker.Not(checker.Contains), container2)
   339  	}
   340  }
   341  
   342  func (s *DockerSuite) TestEventsFilterImageLabels(c *check.C) {
   343  	since := daemonUnixTime(c)
   344  	name := "labelfiltertest"
   345  	label := "io.docker.testing=image"
   346  
   347  	// Build a test image.
   348  	buildImageSuccessfully(c, name, build.WithDockerfile(fmt.Sprintf(`
   349  		FROM busybox:latest
   350  		LABEL %s`, label)))
   351  	dockerCmd(c, "tag", name, "labelfiltertest:tag1")
   352  	dockerCmd(c, "tag", name, "labelfiltertest:tag2")
   353  	dockerCmd(c, "tag", "busybox:latest", "labelfiltertest:tag3")
   354  
   355  	out, _ := dockerCmd(
   356  		c,
   357  		"events",
   358  		"--since", since,
   359  		"--until", daemonUnixTime(c),
   360  		"--filter", fmt.Sprintf("label=%s", label),
   361  		"--filter", "type=image")
   362  
   363  	events := strings.Split(strings.TrimSpace(out), "\n")
   364  
   365  	// 2 events from the "docker tag" command, another one is from "docker build"
   366  	c.Assert(events, checker.HasLen, 3, check.Commentf("Events == %s", events))
   367  	for _, e := range events {
   368  		c.Assert(e, checker.Contains, "labelfiltertest")
   369  	}
   370  }
   371  
   372  func (s *DockerSuite) TestEventsFilterContainer(c *check.C) {
   373  	since := daemonUnixTime(c)
   374  	nameID := make(map[string]string)
   375  
   376  	for _, name := range []string{"container_1", "container_2"} {
   377  		dockerCmd(c, "run", "--name", name, "busybox", "true")
   378  		id := inspectField(c, name, "Id")
   379  		nameID[name] = id
   380  	}
   381  
   382  	until := daemonUnixTime(c)
   383  
   384  	checkEvents := func(id string, events []string) error {
   385  		if len(events) != 4 { // create, attach, start, die
   386  			return fmt.Errorf("expected 4 events, got %v", events)
   387  		}
   388  		for _, event := range events {
   389  			matches := eventstestutils.ScanMap(event)
   390  			if !matchEventID(matches, id) {
   391  				return fmt.Errorf("expected event for container id %s: %s - parsed container id: %s", id, event, matches["id"])
   392  			}
   393  		}
   394  		return nil
   395  	}
   396  
   397  	for name, ID := range nameID {
   398  		// filter by names
   399  		out, _ := dockerCmd(c, "events", "--since", since, "--until", until, "--filter", "container="+name)
   400  		events := strings.Split(strings.TrimSuffix(out, "\n"), "\n")
   401  		c.Assert(checkEvents(ID, events), checker.IsNil)
   402  
   403  		// filter by ID's
   404  		out, _ = dockerCmd(c, "events", "--since", since, "--until", until, "--filter", "container="+ID)
   405  		events = strings.Split(strings.TrimSuffix(out, "\n"), "\n")
   406  		c.Assert(checkEvents(ID, events), checker.IsNil)
   407  	}
   408  }
   409  
   410  func (s *DockerSuite) TestEventsCommit(c *check.C) {
   411  	// Problematic on Windows as cannot commit a running container
   412  	testRequires(c, DaemonIsLinux)
   413  
   414  	out := runSleepingContainer(c)
   415  	cID := strings.TrimSpace(out)
   416  	cli.WaitRun(c, cID)
   417  
   418  	cli.DockerCmd(c, "commit", "-m", "test", cID)
   419  	cli.DockerCmd(c, "stop", cID)
   420  	cli.WaitExited(c, cID, 5*time.Second)
   421  
   422  	until := daemonUnixTime(c)
   423  	out = cli.DockerCmd(c, "events", "-f", "container="+cID, "--until="+until).Combined()
   424  	c.Assert(out, checker.Contains, "commit", check.Commentf("Missing 'commit' log event"))
   425  }
   426  
   427  func (s *DockerSuite) TestEventsCopy(c *check.C) {
   428  	// Build a test image.
   429  	buildImageSuccessfully(c, "cpimg", build.WithDockerfile(`
   430  		  FROM busybox
   431  		  RUN echo HI > /file`))
   432  	id := getIDByName(c, "cpimg")
   433  
   434  	// Create an empty test file.
   435  	tempFile, err := ioutil.TempFile("", "test-events-copy-")
   436  	c.Assert(err, checker.IsNil)
   437  	defer os.Remove(tempFile.Name())
   438  
   439  	c.Assert(tempFile.Close(), checker.IsNil)
   440  
   441  	dockerCmd(c, "create", "--name=cptest", id)
   442  
   443  	dockerCmd(c, "cp", "cptest:/file", tempFile.Name())
   444  
   445  	until := daemonUnixTime(c)
   446  	out, _ := dockerCmd(c, "events", "--since=0", "-f", "container=cptest", "--until="+until)
   447  	c.Assert(out, checker.Contains, "archive-path", check.Commentf("Missing 'archive-path' log event\n"))
   448  
   449  	dockerCmd(c, "cp", tempFile.Name(), "cptest:/filecopy")
   450  
   451  	until = daemonUnixTime(c)
   452  	out, _ = dockerCmd(c, "events", "-f", "container=cptest", "--until="+until)
   453  	c.Assert(out, checker.Contains, "extract-to-dir", check.Commentf("Missing 'extract-to-dir' log event"))
   454  }
   455  
   456  func (s *DockerSuite) TestEventsResize(c *check.C) {
   457  	out := runSleepingContainer(c, "-d")
   458  	cID := strings.TrimSpace(out)
   459  	c.Assert(waitRun(cID), checker.IsNil)
   460  
   461  	cli, err := client.NewEnvClient()
   462  	c.Assert(err, checker.IsNil)
   463  	defer cli.Close()
   464  
   465  	options := types.ResizeOptions{
   466  		Height: 80,
   467  		Width:  24,
   468  	}
   469  	err = cli.ContainerResize(context.Background(), cID, options)
   470  	c.Assert(err, checker.IsNil)
   471  
   472  	dockerCmd(c, "stop", cID)
   473  
   474  	until := daemonUnixTime(c)
   475  	out, _ = dockerCmd(c, "events", "-f", "container="+cID, "--until="+until)
   476  	c.Assert(out, checker.Contains, "resize", check.Commentf("Missing 'resize' log event"))
   477  }
   478  
   479  func (s *DockerSuite) TestEventsAttach(c *check.C) {
   480  	// TODO Windows CI: Figure out why this test fails intermittently (TP5).
   481  	testRequires(c, DaemonIsLinux)
   482  
   483  	out := cli.DockerCmd(c, "run", "-di", "busybox", "cat").Combined()
   484  	cID := strings.TrimSpace(out)
   485  	cli.WaitRun(c, cID)
   486  
   487  	cmd := exec.Command(dockerBinary, "attach", cID)
   488  	stdin, err := cmd.StdinPipe()
   489  	c.Assert(err, checker.IsNil)
   490  	defer stdin.Close()
   491  	stdout, err := cmd.StdoutPipe()
   492  	c.Assert(err, checker.IsNil)
   493  	defer stdout.Close()
   494  	c.Assert(cmd.Start(), checker.IsNil)
   495  	defer func() {
   496  		cmd.Process.Kill()
   497  		cmd.Wait()
   498  	}()
   499  
   500  	// Make sure we're done attaching by writing/reading some stuff
   501  	_, err = stdin.Write([]byte("hello\n"))
   502  	c.Assert(err, checker.IsNil)
   503  	out, err = bufio.NewReader(stdout).ReadString('\n')
   504  	c.Assert(err, checker.IsNil)
   505  	c.Assert(strings.TrimSpace(out), checker.Equals, "hello", check.Commentf("expected 'hello'"))
   506  
   507  	c.Assert(stdin.Close(), checker.IsNil)
   508  
   509  	cli.DockerCmd(c, "kill", cID)
   510  	cli.WaitExited(c, cID, 5*time.Second)
   511  
   512  	until := daemonUnixTime(c)
   513  	out = cli.DockerCmd(c, "events", "-f", "container="+cID, "--until="+until).Combined()
   514  	c.Assert(out, checker.Contains, "attach", check.Commentf("Missing 'attach' log event"))
   515  }
   516  
   517  func (s *DockerSuite) TestEventsRename(c *check.C) {
   518  	out, _ := dockerCmd(c, "run", "--name", "oldName", "busybox", "true")
   519  	cID := strings.TrimSpace(out)
   520  	dockerCmd(c, "rename", "oldName", "newName")
   521  
   522  	until := daemonUnixTime(c)
   523  	// filter by the container id because the name in the event will be the new name.
   524  	out, _ = dockerCmd(c, "events", "-f", "container="+cID, "--until", until)
   525  	c.Assert(out, checker.Contains, "rename", check.Commentf("Missing 'rename' log event\n"))
   526  }
   527  
   528  func (s *DockerSuite) TestEventsTop(c *check.C) {
   529  	// Problematic on Windows as Windows does not support top
   530  	testRequires(c, DaemonIsLinux)
   531  
   532  	out := runSleepingContainer(c, "-d")
   533  	cID := strings.TrimSpace(out)
   534  	c.Assert(waitRun(cID), checker.IsNil)
   535  
   536  	dockerCmd(c, "top", cID)
   537  	dockerCmd(c, "stop", cID)
   538  
   539  	until := daemonUnixTime(c)
   540  	out, _ = dockerCmd(c, "events", "-f", "container="+cID, "--until="+until)
   541  	c.Assert(out, checker.Contains, " top", check.Commentf("Missing 'top' log event"))
   542  }
   543  
   544  // #14316
   545  func (s *DockerRegistrySuite) TestEventsImageFilterPush(c *check.C) {
   546  	// Problematic to port for Windows CI during TP5 timeframe until
   547  	// supporting push
   548  	testRequires(c, DaemonIsLinux)
   549  	testRequires(c, Network)
   550  	repoName := fmt.Sprintf("%v/dockercli/testf", privateRegistryURL)
   551  
   552  	out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
   553  	cID := strings.TrimSpace(out)
   554  	c.Assert(waitRun(cID), checker.IsNil)
   555  
   556  	dockerCmd(c, "commit", cID, repoName)
   557  	dockerCmd(c, "stop", cID)
   558  	dockerCmd(c, "push", repoName)
   559  
   560  	until := daemonUnixTime(c)
   561  	out, _ = dockerCmd(c, "events", "-f", "image="+repoName, "-f", "event=push", "--until", until)
   562  	c.Assert(out, checker.Contains, repoName, check.Commentf("Missing 'push' log event for %s", repoName))
   563  }
   564  
   565  func (s *DockerSuite) TestEventsFilterType(c *check.C) {
   566  	// FIXME(vdemeester) fails on e2e run
   567  	testRequires(c, SameHostDaemon)
   568  	since := daemonUnixTime(c)
   569  	name := "labelfiltertest"
   570  	label := "io.docker.testing=image"
   571  
   572  	// Build a test image.
   573  	buildImageSuccessfully(c, name, build.WithDockerfile(fmt.Sprintf(`
   574  		FROM busybox:latest
   575  		LABEL %s`, label)))
   576  	dockerCmd(c, "tag", name, "labelfiltertest:tag1")
   577  	dockerCmd(c, "tag", name, "labelfiltertest:tag2")
   578  	dockerCmd(c, "tag", "busybox:latest", "labelfiltertest:tag3")
   579  
   580  	out, _ := dockerCmd(
   581  		c,
   582  		"events",
   583  		"--since", since,
   584  		"--until", daemonUnixTime(c),
   585  		"--filter", fmt.Sprintf("label=%s", label),
   586  		"--filter", "type=image")
   587  
   588  	events := strings.Split(strings.TrimSpace(out), "\n")
   589  
   590  	// 2 events from the "docker tag" command, another one is from "docker build"
   591  	c.Assert(events, checker.HasLen, 3, check.Commentf("Events == %s", events))
   592  	for _, e := range events {
   593  		c.Assert(e, checker.Contains, "labelfiltertest")
   594  	}
   595  
   596  	out, _ = dockerCmd(
   597  		c,
   598  		"events",
   599  		"--since", since,
   600  		"--until", daemonUnixTime(c),
   601  		"--filter", fmt.Sprintf("label=%s", label),
   602  		"--filter", "type=container")
   603  	events = strings.Split(strings.TrimSpace(out), "\n")
   604  
   605  	// Events generated by the container that builds the image
   606  	c.Assert(events, checker.HasLen, 2, check.Commentf("Events == %s", events))
   607  
   608  	out, _ = dockerCmd(
   609  		c,
   610  		"events",
   611  		"--since", since,
   612  		"--until", daemonUnixTime(c),
   613  		"--filter", "type=network")
   614  	events = strings.Split(strings.TrimSpace(out), "\n")
   615  	c.Assert(len(events), checker.GreaterOrEqualThan, 1, check.Commentf("Events == %s", events))
   616  }
   617  
   618  // #25798
   619  func (s *DockerSuite) TestEventsSpecialFiltersWithExecCreate(c *check.C) {
   620  	since := daemonUnixTime(c)
   621  	runSleepingContainer(c, "--name", "test-container", "-d")
   622  	waitRun("test-container")
   623  
   624  	dockerCmd(c, "exec", "test-container", "echo", "hello-world")
   625  
   626  	out, _ := dockerCmd(
   627  		c,
   628  		"events",
   629  		"--since", since,
   630  		"--until", daemonUnixTime(c),
   631  		"--filter",
   632  		"event='exec_create: echo hello-world'",
   633  	)
   634  
   635  	events := strings.Split(strings.TrimSpace(out), "\n")
   636  	c.Assert(len(events), checker.Equals, 1, check.Commentf(out))
   637  
   638  	out, _ = dockerCmd(
   639  		c,
   640  		"events",
   641  		"--since", since,
   642  		"--until", daemonUnixTime(c),
   643  		"--filter",
   644  		"event=exec_create",
   645  	)
   646  	c.Assert(len(events), checker.Equals, 1, check.Commentf(out))
   647  }
   648  
   649  func (s *DockerSuite) TestEventsFilterImageInContainerAction(c *check.C) {
   650  	since := daemonUnixTime(c)
   651  	dockerCmd(c, "run", "--name", "test-container", "-d", "busybox", "true")
   652  	waitRun("test-container")
   653  
   654  	out, _ := dockerCmd(c, "events", "--filter", "image=busybox", "--since", since, "--until", daemonUnixTime(c))
   655  	events := strings.Split(strings.TrimSpace(out), "\n")
   656  	c.Assert(len(events), checker.GreaterThan, 1, check.Commentf(out))
   657  }
   658  
   659  func (s *DockerSuite) TestEventsContainerRestart(c *check.C) {
   660  	dockerCmd(c, "run", "-d", "--name=testEvent", "--restart=on-failure:3", "busybox", "false")
   661  
   662  	// wait until test2 is auto removed.
   663  	waitTime := 10 * time.Second
   664  	if testEnv.OSType == "windows" {
   665  		// Windows takes longer...
   666  		waitTime = 90 * time.Second
   667  	}
   668  
   669  	err := waitInspect("testEvent", "{{ .State.Restarting }} {{ .State.Running }}", "false false", waitTime)
   670  	c.Assert(err, checker.IsNil)
   671  
   672  	var (
   673  		createCount int
   674  		startCount  int
   675  		dieCount    int
   676  	)
   677  	out, _ := dockerCmd(c, "events", "--since=0", "--until", daemonUnixTime(c), "-f", "container=testEvent")
   678  	events := strings.Split(strings.TrimSpace(out), "\n")
   679  
   680  	nEvents := len(events)
   681  	c.Assert(nEvents, checker.GreaterOrEqualThan, 1) //Missing expected event
   682  	actions := eventActionsByIDAndType(c, events, "testEvent", "container")
   683  
   684  	for _, a := range actions {
   685  		switch a {
   686  		case "create":
   687  			createCount++
   688  		case "start":
   689  			startCount++
   690  		case "die":
   691  			dieCount++
   692  		}
   693  	}
   694  	c.Assert(createCount, checker.Equals, 1, check.Commentf("testEvent should be created 1 times: %v", actions))
   695  	c.Assert(startCount, checker.Equals, 4, check.Commentf("testEvent should start 4 times: %v", actions))
   696  	c.Assert(dieCount, checker.Equals, 4, check.Commentf("testEvent should die 4 times: %v", actions))
   697  }
   698  
   699  func (s *DockerSuite) TestEventsSinceInTheFuture(c *check.C) {
   700  	dockerCmd(c, "run", "--name", "test-container", "-d", "busybox", "true")
   701  	waitRun("test-container")
   702  
   703  	since := daemonTime(c)
   704  	until := since.Add(time.Duration(-24) * time.Hour)
   705  	out, _, err := dockerCmdWithError("events", "--filter", "image=busybox", "--since", parseEventTime(since), "--until", parseEventTime(until))
   706  
   707  	c.Assert(err, checker.NotNil)
   708  	c.Assert(out, checker.Contains, "cannot be after `until`")
   709  }
   710  
   711  func (s *DockerSuite) TestEventsUntilInThePast(c *check.C) {
   712  	since := daemonUnixTime(c)
   713  
   714  	dockerCmd(c, "run", "--name", "test-container", "-d", "busybox", "true")
   715  	waitRun("test-container")
   716  
   717  	until := daemonUnixTime(c)
   718  
   719  	dockerCmd(c, "run", "--name", "test-container2", "-d", "busybox", "true")
   720  	waitRun("test-container2")
   721  
   722  	out, _ := dockerCmd(c, "events", "--filter", "image=busybox", "--since", since, "--until", until)
   723  
   724  	c.Assert(out, checker.Not(checker.Contains), "test-container2")
   725  	c.Assert(out, checker.Contains, "test-container")
   726  }
   727  
   728  func (s *DockerSuite) TestEventsFormat(c *check.C) {
   729  	since := daemonUnixTime(c)
   730  	dockerCmd(c, "run", "--rm", "busybox", "true")
   731  	dockerCmd(c, "run", "--rm", "busybox", "true")
   732  	out, _ := dockerCmd(c, "events", "--since", since, "--until", daemonUnixTime(c), "--format", "{{json .}}")
   733  	dec := json.NewDecoder(strings.NewReader(out))
   734  	// make sure we got 2 start events
   735  	startCount := 0
   736  	for {
   737  		var err error
   738  		var ev eventtypes.Message
   739  		if err = dec.Decode(&ev); err == io.EOF {
   740  			break
   741  		}
   742  		c.Assert(err, checker.IsNil)
   743  		if ev.Status == "start" {
   744  			startCount++
   745  		}
   746  	}
   747  
   748  	c.Assert(startCount, checker.Equals, 2, check.Commentf("should have had 2 start events but had %d, out: %s", startCount, out))
   749  }
   750  
   751  func (s *DockerSuite) TestEventsFormatBadFunc(c *check.C) {
   752  	// make sure it fails immediately, without receiving any event
   753  	result := dockerCmdWithResult("events", "--format", "{{badFuncString .}}")
   754  	result.Assert(c, icmd.Expected{
   755  		Error:    "exit status 64",
   756  		ExitCode: 64,
   757  		Err:      "Error parsing format: template: :1: function \"badFuncString\" not defined",
   758  	})
   759  }
   760  
   761  func (s *DockerSuite) TestEventsFormatBadField(c *check.C) {
   762  	// make sure it fails immediately, without receiving any event
   763  	result := dockerCmdWithResult("events", "--format", "{{.badFieldString}}")
   764  	result.Assert(c, icmd.Expected{
   765  		Error:    "exit status 64",
   766  		ExitCode: 64,
   767  		Err:      "Error parsing format: template: :1:2: executing \"\" at <.badFieldString>: can't evaluate field badFieldString in type *events.Message",
   768  	})
   769  }