github.com/jwhonce/docker@v0.6.7-0.20190327063223-da823cf3a5a3/integration-cli/docker_cli_events_test.go (about)

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