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