github.com/chenchun/docker@v1.3.2-0.20150629222414-20467faf132b/integration-cli/docker_cli_events_test.go (about)

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