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