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