github.com/tompao/docker@v1.9.1/integration-cli/docker_cli_events_test.go (about)

     1  package main
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"net/http"
     8  	"os"
     9  	"os/exec"
    10  	"regexp"
    11  	"strconv"
    12  	"strings"
    13  	"sync"
    14  	"time"
    15  
    16  	"github.com/docker/docker/pkg/integration/checker"
    17  	"github.com/go-check/check"
    18  )
    19  
    20  func (s *DockerSuite) TestEventsTimestampFormats(c *check.C) {
    21  	testRequires(c, DaemonIsLinux)
    22  	image := "busybox"
    23  
    24  	// Start stopwatch, generate an event
    25  	time.Sleep(1 * time.Second) // so that we don't grab events from previous test occured in the same second
    26  	start := daemonTime(c)
    27  	dockerCmd(c, "tag", image, "timestamptest:1")
    28  	dockerCmd(c, "rmi", "timestamptest:1")
    29  	time.Sleep(1 * time.Second) // so that until > since
    30  	end := daemonTime(c)
    31  
    32  	// List of available time formats to --since
    33  	unixTs := func(t time.Time) string { return fmt.Sprintf("%v", t.Unix()) }
    34  	rfc3339 := func(t time.Time) string { return t.Format(time.RFC3339) }
    35  	duration := func(t time.Time) string { return time.Now().Sub(t).String() }
    36  
    37  	// --since=$start must contain only the 'untag' event
    38  	for _, f := range []func(time.Time) string{unixTs, rfc3339, duration} {
    39  		since, until := f(start), f(end)
    40  		out, _ := dockerCmd(c, "events", "--since="+since, "--until="+until)
    41  		events := strings.Split(strings.TrimSpace(out), "\n")
    42  		if len(events) != 2 {
    43  			c.Fatalf("unexpected events, was expecting only 2 events tag/untag (since=%s, until=%s) out=%s", since, until, out)
    44  		}
    45  		if !strings.Contains(out, "untag") {
    46  			c.Fatalf("expected 'untag' event not found (since=%s, until=%s) out=%s", since, until, out)
    47  		}
    48  	}
    49  
    50  }
    51  
    52  func (s *DockerSuite) TestEventsUntag(c *check.C) {
    53  	testRequires(c, DaemonIsLinux)
    54  	image := "busybox"
    55  	dockerCmd(c, "tag", image, "utest:tag1")
    56  	dockerCmd(c, "tag", image, "utest:tag2")
    57  	dockerCmd(c, "rmi", "utest:tag1")
    58  	dockerCmd(c, "rmi", "utest:tag2")
    59  	eventsCmd := exec.Command(dockerBinary, "events", "--since=1")
    60  	out, exitCode, _, err := runCommandWithOutputForDuration(eventsCmd, time.Duration(time.Millisecond*200))
    61  	if exitCode != 0 || err != nil {
    62  		c.Fatalf("Failed to get events - exit code %d: %s", exitCode, err)
    63  	}
    64  	events := strings.Split(out, "\n")
    65  	nEvents := len(events)
    66  	// The last element after the split above will be an empty string, so we
    67  	// get the two elements before the last, which are the untags we're
    68  	// looking for.
    69  	for _, v := range events[nEvents-3 : nEvents-1] {
    70  		if !strings.Contains(v, "untag") {
    71  			c.Fatalf("event should be untag, not %#v", v)
    72  		}
    73  	}
    74  }
    75  
    76  func (s *DockerSuite) TestEventsContainerFailStartDie(c *check.C) {
    77  
    78  	out, _ := dockerCmd(c, "images", "-q")
    79  	image := strings.Split(out, "\n")[0]
    80  	if _, _, err := dockerCmdWithError("run", "--name", "testeventdie", image, "blerg"); err == nil {
    81  		c.Fatalf("Container run with command blerg should have failed, but it did not")
    82  	}
    83  
    84  	out, _ = dockerCmd(c, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
    85  	events := strings.Split(out, "\n")
    86  	if len(events) <= 1 {
    87  		c.Fatalf("Missing expected event")
    88  	}
    89  
    90  	startEvent := strings.Fields(events[len(events)-3])
    91  	dieEvent := strings.Fields(events[len(events)-2])
    92  
    93  	if startEvent[len(startEvent)-1] != "start" {
    94  		c.Fatalf("event should be start, not %#v", startEvent)
    95  	}
    96  	if dieEvent[len(dieEvent)-1] != "die" {
    97  		c.Fatalf("event should be die, not %#v", dieEvent)
    98  	}
    99  
   100  }
   101  
   102  func (s *DockerSuite) TestEventsLimit(c *check.C) {
   103  	testRequires(c, DaemonIsLinux)
   104  	var waitGroup sync.WaitGroup
   105  	errChan := make(chan error, 17)
   106  
   107  	args := []string{"run", "--rm", "busybox", "true"}
   108  	for i := 0; i < 17; i++ {
   109  		waitGroup.Add(1)
   110  		go func() {
   111  			defer waitGroup.Done()
   112  			errChan <- exec.Command(dockerBinary, args...).Run()
   113  		}()
   114  	}
   115  
   116  	waitGroup.Wait()
   117  	close(errChan)
   118  
   119  	for err := range errChan {
   120  		if err != nil {
   121  			c.Fatalf("%q failed with error: %v", strings.Join(args, " "), err)
   122  		}
   123  	}
   124  
   125  	out, _ := dockerCmd(c, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
   126  	events := strings.Split(out, "\n")
   127  	nEvents := len(events) - 1
   128  	if nEvents != 64 {
   129  		c.Fatalf("events should be limited to 64, but received %d", nEvents)
   130  	}
   131  }
   132  
   133  func (s *DockerSuite) TestEventsContainerEvents(c *check.C) {
   134  	testRequires(c, DaemonIsLinux)
   135  	dockerCmd(c, "run", "--rm", "busybox", "true")
   136  	out, _ := dockerCmd(c, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
   137  	events := strings.Split(out, "\n")
   138  	events = events[:len(events)-1]
   139  	if len(events) < 5 {
   140  		c.Fatalf("Missing expected event")
   141  	}
   142  	createEvent := strings.Fields(events[len(events)-5])
   143  	attachEvent := strings.Fields(events[len(events)-4])
   144  	startEvent := strings.Fields(events[len(events)-3])
   145  	dieEvent := strings.Fields(events[len(events)-2])
   146  	destroyEvent := strings.Fields(events[len(events)-1])
   147  	if createEvent[len(createEvent)-1] != "create" {
   148  		c.Fatalf("event should be create, not %#v", createEvent)
   149  	}
   150  	if attachEvent[len(attachEvent)-1] != "attach" {
   151  		c.Fatalf("event should be attach, not %#v", attachEvent)
   152  	}
   153  	if startEvent[len(startEvent)-1] != "start" {
   154  		c.Fatalf("event should be start, not %#v", startEvent)
   155  	}
   156  	if dieEvent[len(dieEvent)-1] != "die" {
   157  		c.Fatalf("event should be die, not %#v", dieEvent)
   158  	}
   159  	if destroyEvent[len(destroyEvent)-1] != "destroy" {
   160  		c.Fatalf("event should be destroy, not %#v", destroyEvent)
   161  	}
   162  
   163  }
   164  
   165  func (s *DockerSuite) TestEventsContainerEventsSinceUnixEpoch(c *check.C) {
   166  	testRequires(c, DaemonIsLinux)
   167  	dockerCmd(c, "run", "--rm", "busybox", "true")
   168  	timeBeginning := time.Unix(0, 0).Format(time.RFC3339Nano)
   169  	timeBeginning = strings.Replace(timeBeginning, "Z", ".000000000Z", -1)
   170  	out, _ := dockerCmd(c, "events", fmt.Sprintf("--since='%s'", timeBeginning),
   171  		fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
   172  	events := strings.Split(out, "\n")
   173  	events = events[:len(events)-1]
   174  	if len(events) < 5 {
   175  		c.Fatalf("Missing expected event")
   176  	}
   177  	createEvent := strings.Fields(events[len(events)-5])
   178  	attachEvent := strings.Fields(events[len(events)-4])
   179  	startEvent := strings.Fields(events[len(events)-3])
   180  	dieEvent := strings.Fields(events[len(events)-2])
   181  	destroyEvent := strings.Fields(events[len(events)-1])
   182  	if createEvent[len(createEvent)-1] != "create" {
   183  		c.Fatalf("event should be create, not %#v", createEvent)
   184  	}
   185  	if attachEvent[len(attachEvent)-1] != "attach" {
   186  		c.Fatalf("event should be attach, not %#v", attachEvent)
   187  	}
   188  	if startEvent[len(startEvent)-1] != "start" {
   189  		c.Fatalf("event should be start, not %#v", startEvent)
   190  	}
   191  	if dieEvent[len(dieEvent)-1] != "die" {
   192  		c.Fatalf("event should be die, not %#v", dieEvent)
   193  	}
   194  	if destroyEvent[len(destroyEvent)-1] != "destroy" {
   195  		c.Fatalf("event should be destroy, not %#v", destroyEvent)
   196  	}
   197  
   198  }
   199  
   200  func (s *DockerSuite) TestEventsImageUntagDelete(c *check.C) {
   201  	testRequires(c, DaemonIsLinux)
   202  	name := "testimageevents"
   203  	_, err := buildImage(name,
   204  		`FROM scratch
   205  		MAINTAINER "docker"`,
   206  		true)
   207  	if err != nil {
   208  		c.Fatal(err)
   209  	}
   210  	if err := deleteImages(name); err != nil {
   211  		c.Fatal(err)
   212  	}
   213  	out, _ := dockerCmd(c, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
   214  	events := strings.Split(out, "\n")
   215  
   216  	events = events[:len(events)-1]
   217  	if len(events) < 2 {
   218  		c.Fatalf("Missing expected event")
   219  	}
   220  	untagEvent := strings.Fields(events[len(events)-2])
   221  	deleteEvent := strings.Fields(events[len(events)-1])
   222  	if untagEvent[len(untagEvent)-1] != "untag" {
   223  		c.Fatalf("untag should be untag, not %#v", untagEvent)
   224  	}
   225  	if deleteEvent[len(deleteEvent)-1] != "delete" {
   226  		c.Fatalf("delete should be delete, not %#v", deleteEvent)
   227  	}
   228  }
   229  
   230  func (s *DockerSuite) TestEventsImageTag(c *check.C) {
   231  	testRequires(c, DaemonIsLinux)
   232  	time.Sleep(1 * time.Second) // because API has seconds granularity
   233  	since := daemonTime(c).Unix()
   234  	image := "testimageevents:tag"
   235  	dockerCmd(c, "tag", "busybox", image)
   236  
   237  	out, _ := dockerCmd(c, "events",
   238  		fmt.Sprintf("--since=%d", since),
   239  		fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
   240  
   241  	events := strings.Split(strings.TrimSpace(out), "\n")
   242  	if len(events) != 1 {
   243  		c.Fatalf("was expecting 1 event. out=%s", out)
   244  	}
   245  	event := strings.TrimSpace(events[0])
   246  	expectedStr := image + ": tag"
   247  
   248  	if !strings.HasSuffix(event, expectedStr) {
   249  		c.Fatalf("wrong event format. expected='%s' got=%s", expectedStr, event)
   250  	}
   251  
   252  }
   253  
   254  func (s *DockerSuite) TestEventsImagePull(c *check.C) {
   255  	testRequires(c, DaemonIsLinux)
   256  	since := daemonTime(c).Unix()
   257  	testRequires(c, Network)
   258  
   259  	dockerCmd(c, "pull", "hello-world")
   260  
   261  	out, _ := dockerCmd(c, "events",
   262  		fmt.Sprintf("--since=%d", since),
   263  		fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
   264  
   265  	events := strings.Split(strings.TrimSpace(out), "\n")
   266  	event := strings.TrimSpace(events[len(events)-1])
   267  
   268  	if !strings.HasSuffix(event, "hello-world:latest: pull") {
   269  		c.Fatalf("Missing pull event - got:%q", event)
   270  	}
   271  
   272  }
   273  
   274  func (s *DockerSuite) TestEventsImageImport(c *check.C) {
   275  	testRequires(c, DaemonIsLinux)
   276  	since := daemonTime(c).Unix()
   277  
   278  	id := make(chan string)
   279  	eventImport := make(chan struct{})
   280  	eventsCmd := exec.Command(dockerBinary, "events", "--since", strconv.FormatInt(since, 10))
   281  	stdout, err := eventsCmd.StdoutPipe()
   282  	if err != nil {
   283  		c.Fatal(err)
   284  	}
   285  	if err := eventsCmd.Start(); err != nil {
   286  		c.Fatal(err)
   287  	}
   288  	defer eventsCmd.Process.Kill()
   289  
   290  	go func() {
   291  		containerID := <-id
   292  
   293  		matchImport := regexp.MustCompile(containerID + `: import$`)
   294  		scanner := bufio.NewScanner(stdout)
   295  		for scanner.Scan() {
   296  			if matchImport.MatchString(scanner.Text()) {
   297  				close(eventImport)
   298  			}
   299  		}
   300  	}()
   301  
   302  	out, _ := dockerCmd(c, "run", "-d", "busybox", "true")
   303  	cleanedContainerID := strings.TrimSpace(out)
   304  
   305  	out, _, err = runCommandPipelineWithOutput(
   306  		exec.Command(dockerBinary, "export", cleanedContainerID),
   307  		exec.Command(dockerBinary, "import", "-"),
   308  	)
   309  	if err != nil {
   310  		c.Errorf("import failed with errors: %v, output: %q", err, out)
   311  	}
   312  	newContainerID := strings.TrimSpace(out)
   313  	id <- newContainerID
   314  
   315  	select {
   316  	case <-time.After(5 * time.Second):
   317  		c.Fatal("failed to observe image import in timely fashion")
   318  	case <-eventImport:
   319  		// ignore, done
   320  	}
   321  }
   322  
   323  func (s *DockerSuite) TestEventsFilters(c *check.C) {
   324  	testRequires(c, DaemonIsLinux)
   325  	parseEvents := func(out, match string) {
   326  		events := strings.Split(out, "\n")
   327  		events = events[:len(events)-1]
   328  		for _, event := range events {
   329  			eventFields := strings.Fields(event)
   330  			eventName := eventFields[len(eventFields)-1]
   331  			if ok, err := regexp.MatchString(match, eventName); err != nil || !ok {
   332  				c.Fatalf("event should match %s, got %#v, err: %v", match, eventFields, err)
   333  			}
   334  		}
   335  	}
   336  
   337  	since := daemonTime(c).Unix()
   338  	dockerCmd(c, "run", "--rm", "busybox", "true")
   339  	dockerCmd(c, "run", "--rm", "busybox", "true")
   340  	out, _ := dockerCmd(c, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix()), "--filter", "event=die")
   341  	parseEvents(out, "die")
   342  
   343  	out, _ = dockerCmd(c, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix()), "--filter", "event=die", "--filter", "event=start")
   344  	parseEvents(out, "((die)|(start))")
   345  
   346  	// make sure we at least got 2 start events
   347  	count := strings.Count(out, "start")
   348  	if count < 2 {
   349  		c.Fatalf("should have had 2 start events but had %d, out: %s", count, out)
   350  	}
   351  
   352  }
   353  
   354  func (s *DockerSuite) TestEventsFilterImageName(c *check.C) {
   355  	testRequires(c, DaemonIsLinux)
   356  	since := daemonTime(c).Unix()
   357  
   358  	out, _ := dockerCmd(c, "run", "--name", "container_1", "-d", "busybox:latest", "true")
   359  	container1 := strings.TrimSpace(out)
   360  
   361  	out, _ = dockerCmd(c, "run", "--name", "container_2", "-d", "busybox", "true")
   362  	container2 := strings.TrimSpace(out)
   363  
   364  	name := "busybox"
   365  	out, _ = dockerCmd(c, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix()), "--filter", fmt.Sprintf("image=%s", name))
   366  	events := strings.Split(out, "\n")
   367  	events = events[:len(events)-1]
   368  	if len(events) == 0 {
   369  		c.Fatalf("Expected events but found none for the image busybox:latest")
   370  	}
   371  	count1 := 0
   372  	count2 := 0
   373  
   374  	for _, e := range events {
   375  		if strings.Contains(e, container1) {
   376  			count1++
   377  		} else if strings.Contains(e, container2) {
   378  			count2++
   379  		}
   380  	}
   381  	if count1 == 0 || count2 == 0 {
   382  		c.Fatalf("Expected events from each container but got %d from %s and %d from %s", count1, container1, count2, container2)
   383  	}
   384  
   385  }
   386  
   387  func (s *DockerSuite) TestEventsFilterLabels(c *check.C) {
   388  	testRequires(c, DaemonIsLinux)
   389  	since := daemonTime(c).Unix()
   390  	label := "io.docker.testing=foo"
   391  
   392  	out, _ := dockerCmd(c, "run", "-d", "-l", label, "busybox:latest", "true")
   393  	container1 := strings.TrimSpace(out)
   394  
   395  	out, _ = dockerCmd(c, "run", "-d", "busybox", "true")
   396  	container2 := strings.TrimSpace(out)
   397  
   398  	out, _ = dockerCmd(
   399  		c,
   400  		"events",
   401  		fmt.Sprintf("--since=%d", since),
   402  		fmt.Sprintf("--until=%d", daemonTime(c).Unix()),
   403  		"--filter", fmt.Sprintf("label=%s", label))
   404  
   405  	events := strings.Split(strings.TrimSpace(out), "\n")
   406  	c.Assert(len(events), checker.Equals, 3)
   407  
   408  	for _, e := range events {
   409  		c.Assert(e, checker.Contains, container1)
   410  		c.Assert(e, check.Not(checker.Contains), container2)
   411  	}
   412  }
   413  
   414  func (s *DockerSuite) TestEventsFilterImageLabels(c *check.C) {
   415  	testRequires(c, DaemonIsLinux)
   416  	since := daemonTime(c).Unix()
   417  	name := "labelfilterimage"
   418  	label := "io.docker.testing=image"
   419  
   420  	// Build a test image.
   421  	_, err := buildImage(name, `
   422  		FROM busybox:latest
   423  		LABEL io.docker.testing=image`, true)
   424  	if err != nil {
   425  		c.Fatalf("Couldn't create image: %q", err)
   426  	}
   427  
   428  	dockerCmd(c, "tag", name, "labelfiltertest:tag1")
   429  	dockerCmd(c, "tag", name, "labelfiltertest:tag2")
   430  	dockerCmd(c, "tag", "busybox:latest", "labelfiltertest:tag3")
   431  
   432  	out, _ := dockerCmd(
   433  		c,
   434  		"events",
   435  		fmt.Sprintf("--since=%d", since),
   436  		fmt.Sprintf("--until=%d", daemonTime(c).Unix()),
   437  		"--filter", fmt.Sprintf("label=%s", label))
   438  
   439  	events := strings.Split(strings.TrimSpace(out), "\n")
   440  	c.Assert(len(events), checker.Equals, 2, check.Commentf("Events == %s", events))
   441  	for _, e := range events {
   442  		c.Assert(e, checker.Contains, "labelfiltertest")
   443  	}
   444  }
   445  
   446  func (s *DockerSuite) TestEventsFilterContainer(c *check.C) {
   447  	testRequires(c, DaemonIsLinux)
   448  	since := fmt.Sprintf("%d", daemonTime(c).Unix())
   449  	nameID := make(map[string]string)
   450  
   451  	for _, name := range []string{"container_1", "container_2"} {
   452  		dockerCmd(c, "run", "--name", name, "busybox", "true")
   453  		id, err := inspectField(name, "Id")
   454  		if err != nil {
   455  			c.Fatal(err)
   456  		}
   457  		nameID[name] = id
   458  	}
   459  
   460  	until := fmt.Sprintf("%d", daemonTime(c).Unix())
   461  
   462  	checkEvents := func(id string, events []string) error {
   463  		if len(events) != 4 { // create, attach, start, die
   464  			return fmt.Errorf("expected 4 events, got %v", events)
   465  		}
   466  		for _, event := range events {
   467  			e := strings.Fields(event)
   468  			if len(e) < 3 {
   469  				return fmt.Errorf("got malformed event: %s", event)
   470  			}
   471  
   472  			// Check the id
   473  			parsedID := strings.TrimSuffix(e[1], ":")
   474  			if parsedID != id {
   475  				return fmt.Errorf("expected event for container id %s: %s - parsed container id: %s", id, event, parsedID)
   476  			}
   477  		}
   478  		return nil
   479  	}
   480  
   481  	for name, ID := range nameID {
   482  		// filter by names
   483  		out, _ := dockerCmd(c, "events", "--since", since, "--until", until, "--filter", "container="+name)
   484  		events := strings.Split(strings.TrimSuffix(out, "\n"), "\n")
   485  		if err := checkEvents(ID, events); err != nil {
   486  			c.Fatal(err)
   487  		}
   488  
   489  		// filter by ID's
   490  		out, _ = dockerCmd(c, "events", "--since", since, "--until", until, "--filter", "container="+ID)
   491  		events = strings.Split(strings.TrimSuffix(out, "\n"), "\n")
   492  		if err := checkEvents(ID, events); err != nil {
   493  			c.Fatal(err)
   494  		}
   495  	}
   496  }
   497  
   498  func (s *DockerSuite) TestEventsStreaming(c *check.C) {
   499  	testRequires(c, DaemonIsLinux)
   500  	start := daemonTime(c).Unix()
   501  
   502  	id := make(chan string)
   503  	eventCreate := make(chan struct{})
   504  	eventStart := make(chan struct{})
   505  	eventDie := make(chan struct{})
   506  	eventDestroy := make(chan struct{})
   507  
   508  	eventsCmd := exec.Command(dockerBinary, "events", "--since", strconv.FormatInt(start, 10))
   509  	stdout, err := eventsCmd.StdoutPipe()
   510  	if err != nil {
   511  		c.Fatal(err)
   512  	}
   513  	if err := eventsCmd.Start(); err != nil {
   514  		c.Fatalf("failed to start 'docker events': %s", err)
   515  	}
   516  	defer eventsCmd.Process.Kill()
   517  
   518  	go func() {
   519  		containerID := <-id
   520  
   521  		matchCreate := regexp.MustCompile(containerID + `: \(from busybox:latest\) create$`)
   522  		matchStart := regexp.MustCompile(containerID + `: \(from busybox:latest\) start$`)
   523  		matchDie := regexp.MustCompile(containerID + `: \(from busybox:latest\) die$`)
   524  		matchDestroy := regexp.MustCompile(containerID + `: \(from busybox:latest\) destroy$`)
   525  
   526  		scanner := bufio.NewScanner(stdout)
   527  		for scanner.Scan() {
   528  			switch {
   529  			case matchCreate.MatchString(scanner.Text()):
   530  				close(eventCreate)
   531  			case matchStart.MatchString(scanner.Text()):
   532  				close(eventStart)
   533  			case matchDie.MatchString(scanner.Text()):
   534  				close(eventDie)
   535  			case matchDestroy.MatchString(scanner.Text()):
   536  				close(eventDestroy)
   537  			}
   538  		}
   539  	}()
   540  
   541  	out, _ := dockerCmd(c, "run", "-d", "busybox:latest", "true")
   542  	cleanedContainerID := strings.TrimSpace(out)
   543  	id <- cleanedContainerID
   544  
   545  	select {
   546  	case <-time.After(5 * time.Second):
   547  		c.Fatal("failed to observe container create in timely fashion")
   548  	case <-eventCreate:
   549  		// ignore, done
   550  	}
   551  
   552  	select {
   553  	case <-time.After(5 * time.Second):
   554  		c.Fatal("failed to observe container start in timely fashion")
   555  	case <-eventStart:
   556  		// ignore, done
   557  	}
   558  
   559  	select {
   560  	case <-time.After(5 * time.Second):
   561  		c.Fatal("failed to observe container die in timely fashion")
   562  	case <-eventDie:
   563  		// ignore, done
   564  	}
   565  
   566  	dockerCmd(c, "rm", cleanedContainerID)
   567  
   568  	select {
   569  	case <-time.After(5 * time.Second):
   570  		c.Fatal("failed to observe container destroy in timely fashion")
   571  	case <-eventDestroy:
   572  		// ignore, done
   573  	}
   574  }
   575  
   576  func (s *DockerSuite) TestEventsCommit(c *check.C) {
   577  	testRequires(c, DaemonIsLinux)
   578  	since := daemonTime(c).Unix()
   579  
   580  	out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
   581  	cID := strings.TrimSpace(out)
   582  	c.Assert(waitRun(cID), check.IsNil)
   583  
   584  	dockerCmd(c, "commit", "-m", "test", cID)
   585  	dockerCmd(c, "stop", cID)
   586  
   587  	out, _ = dockerCmd(c, "events", "--since=0", "-f", "container="+cID, "--until="+strconv.Itoa(int(since)))
   588  	if !strings.Contains(out, " commit\n") {
   589  		c.Fatalf("Missing 'commit' log event\n%s", out)
   590  	}
   591  }
   592  
   593  func (s *DockerSuite) TestEventsCopy(c *check.C) {
   594  	testRequires(c, DaemonIsLinux)
   595  	since := daemonTime(c).Unix()
   596  
   597  	// Build a test image.
   598  	id, err := buildImage("cpimg", `
   599  		  FROM busybox
   600  		  RUN echo HI > /tmp/file`, true)
   601  	if err != nil {
   602  		c.Fatalf("Couldn't create image: %q", err)
   603  	}
   604  
   605  	// Create an empty test file.
   606  	tempFile, err := ioutil.TempFile("", "test-events-copy-")
   607  	if err != nil {
   608  		c.Fatal(err)
   609  	}
   610  	defer os.Remove(tempFile.Name())
   611  
   612  	if err := tempFile.Close(); err != nil {
   613  		c.Fatal(err)
   614  	}
   615  
   616  	dockerCmd(c, "create", "--name=cptest", id)
   617  
   618  	dockerCmd(c, "cp", "cptest:/tmp/file", tempFile.Name())
   619  
   620  	out, _ := dockerCmd(c, "events", "--since=0", "-f", "container=cptest", "--until="+strconv.Itoa(int(since)))
   621  	if !strings.Contains(out, " archive-path\n") {
   622  		c.Fatalf("Missing 'archive-path' log event\n%s", out)
   623  	}
   624  
   625  	dockerCmd(c, "cp", tempFile.Name(), "cptest:/tmp/filecopy")
   626  
   627  	out, _ = dockerCmd(c, "events", "--since=0", "-f", "container=cptest", "--until="+strconv.Itoa(int(since)))
   628  	if !strings.Contains(out, " extract-to-dir\n") {
   629  		c.Fatalf("Missing 'extract-to-dir' log event\n%s", out)
   630  	}
   631  }
   632  
   633  func (s *DockerSuite) TestEventsResize(c *check.C) {
   634  	testRequires(c, DaemonIsLinux)
   635  	since := daemonTime(c).Unix()
   636  
   637  	out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
   638  	cID := strings.TrimSpace(out)
   639  	c.Assert(waitRun(cID), check.IsNil)
   640  
   641  	endpoint := "/containers/" + cID + "/resize?h=80&w=24"
   642  	status, _, err := sockRequest("POST", endpoint, nil)
   643  	c.Assert(status, check.Equals, http.StatusOK)
   644  	c.Assert(err, check.IsNil)
   645  
   646  	dockerCmd(c, "stop", cID)
   647  
   648  	out, _ = dockerCmd(c, "events", "--since=0", "-f", "container="+cID, "--until="+strconv.Itoa(int(since)))
   649  	if !strings.Contains(out, " resize\n") {
   650  		c.Fatalf("Missing 'resize' log event\n%s", out)
   651  	}
   652  }
   653  
   654  func (s *DockerSuite) TestEventsAttach(c *check.C) {
   655  	testRequires(c, DaemonIsLinux)
   656  	since := daemonTime(c).Unix()
   657  
   658  	out, _ := dockerCmd(c, "run", "-di", "busybox", "/bin/cat")
   659  	cID := strings.TrimSpace(out)
   660  
   661  	cmd := exec.Command(dockerBinary, "attach", cID)
   662  	stdin, err := cmd.StdinPipe()
   663  	c.Assert(err, check.IsNil)
   664  	defer stdin.Close()
   665  	stdout, err := cmd.StdoutPipe()
   666  	c.Assert(err, check.IsNil)
   667  	defer stdout.Close()
   668  	c.Assert(cmd.Start(), check.IsNil)
   669  	defer cmd.Process.Kill()
   670  
   671  	// Make sure we're done attaching by writing/reading some stuff
   672  	if _, err := stdin.Write([]byte("hello\n")); err != nil {
   673  		c.Fatal(err)
   674  	}
   675  	out, err = bufio.NewReader(stdout).ReadString('\n')
   676  	c.Assert(err, check.IsNil)
   677  	if strings.TrimSpace(out) != "hello" {
   678  		c.Fatalf("expected 'hello', got %q", out)
   679  	}
   680  
   681  	c.Assert(stdin.Close(), check.IsNil)
   682  
   683  	dockerCmd(c, "stop", cID)
   684  
   685  	out, _ = dockerCmd(c, "events", "--since=0", "-f", "container="+cID, "--until="+strconv.Itoa(int(since)))
   686  	if !strings.Contains(out, " attach\n") {
   687  		c.Fatalf("Missing 'attach' log event\n%s", out)
   688  	}
   689  }
   690  
   691  func (s *DockerSuite) TestEventsRename(c *check.C) {
   692  	testRequires(c, DaemonIsLinux)
   693  	since := daemonTime(c).Unix()
   694  
   695  	dockerCmd(c, "run", "--name", "oldName", "busybox", "true")
   696  	dockerCmd(c, "rename", "oldName", "newName")
   697  
   698  	out, _ := dockerCmd(c, "events", "--since=0", "-f", "container=newName", "--until="+strconv.Itoa(int(since)))
   699  	if !strings.Contains(out, " rename\n") {
   700  		c.Fatalf("Missing 'rename' log event\n%s", out)
   701  	}
   702  }
   703  
   704  func (s *DockerSuite) TestEventsTop(c *check.C) {
   705  	testRequires(c, DaemonIsLinux)
   706  	since := daemonTime(c).Unix()
   707  
   708  	out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
   709  	cID := strings.TrimSpace(out)
   710  	c.Assert(waitRun(cID), check.IsNil)
   711  
   712  	dockerCmd(c, "top", cID)
   713  	dockerCmd(c, "stop", cID)
   714  
   715  	out, _ = dockerCmd(c, "events", "--since=0", "-f", "container="+cID, "--until="+strconv.Itoa(int(since)))
   716  	if !strings.Contains(out, " top\n") {
   717  		c.Fatalf("Missing 'top' log event\n%s", out)
   718  	}
   719  }
   720  
   721  // #13753
   722  func (s *DockerSuite) TestEventsDefaultEmpty(c *check.C) {
   723  	testRequires(c, DaemonIsLinux)
   724  	dockerCmd(c, "run", "busybox")
   725  	out, _ := dockerCmd(c, "events", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
   726  	c.Assert(strings.TrimSpace(out), check.Equals, "")
   727  }
   728  
   729  // #14316
   730  func (s *DockerRegistrySuite) TestEventsImageFilterPush(c *check.C) {
   731  	testRequires(c, DaemonIsLinux)
   732  	testRequires(c, Network)
   733  	since := daemonTime(c).Unix()
   734  	repoName := fmt.Sprintf("%v/dockercli/testf", privateRegistryURL)
   735  
   736  	out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
   737  	cID := strings.TrimSpace(out)
   738  	c.Assert(waitRun(cID), check.IsNil)
   739  
   740  	dockerCmd(c, "commit", cID, repoName)
   741  	dockerCmd(c, "stop", cID)
   742  	dockerCmd(c, "push", repoName)
   743  
   744  	out, _ = dockerCmd(c, "events", "--since=0", "-f", "image="+repoName, "-f", "event=push", "--until="+strconv.Itoa(int(since)))
   745  	if !strings.Contains(out, repoName+": push\n") {
   746  		c.Fatalf("Missing 'push' log event for image %s\n%s", repoName, out)
   747  	}
   748  }