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