github.com/trgill/moby@v1.13.1/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, IsAmd64, Network) 280 281 since := daemonUnixTime(c) 282 283 dockerCmd(c, "plugin", "install", pNameWithTag, "--grant-all-permissions") 284 dockerCmd(c, "plugin", "disable", pNameWithTag) 285 dockerCmd(c, "plugin", "remove", pNameWithTag) 286 287 out, _ := dockerCmd(c, "events", "--since", since, "--until", daemonUnixTime(c)) 288 events := strings.Split(out, "\n") 289 events = events[:len(events)-1] 290 291 nEvents := len(events) 292 c.Assert(nEvents, checker.GreaterOrEqualThan, 4) 293 294 pluginEvents := eventActionsByIDAndType(c, events, pNameWithTag, "plugin") 295 c.Assert(pluginEvents, checker.HasLen, 4, check.Commentf("events: %v", events)) 296 297 c.Assert(pluginEvents[0], checker.Equals, "pull", check.Commentf(out)) 298 c.Assert(pluginEvents[1], checker.Equals, "enable", check.Commentf(out)) 299 c.Assert(pluginEvents[2], checker.Equals, "disable", check.Commentf(out)) 300 c.Assert(pluginEvents[3], checker.Equals, "remove", check.Commentf(out)) 301 } 302 303 func (s *DockerSuite) TestEventsFilters(c *check.C) { 304 since := daemonUnixTime(c) 305 dockerCmd(c, "run", "--rm", "busybox", "true") 306 dockerCmd(c, "run", "--rm", "busybox", "true") 307 out, _ := dockerCmd(c, "events", "--since", since, "--until", daemonUnixTime(c), "--filter", "event=die") 308 parseEvents(c, out, "die") 309 310 out, _ = dockerCmd(c, "events", "--since", since, "--until", daemonUnixTime(c), "--filter", "event=die", "--filter", "event=start") 311 parseEvents(c, out, "die|start") 312 313 // make sure we at least got 2 start events 314 count := strings.Count(out, "start") 315 c.Assert(strings.Count(out, "start"), checker.GreaterOrEqualThan, 2, check.Commentf("should have had 2 start events but had %d, out: %s", count, out)) 316 317 } 318 319 func (s *DockerSuite) TestEventsFilterImageName(c *check.C) { 320 since := daemonUnixTime(c) 321 322 out, _ := dockerCmd(c, "run", "--name", "container_1", "-d", "busybox:latest", "true") 323 container1 := strings.TrimSpace(out) 324 325 out, _ = dockerCmd(c, "run", "--name", "container_2", "-d", "busybox", "true") 326 container2 := strings.TrimSpace(out) 327 328 name := "busybox" 329 out, _ = dockerCmd(c, "events", "--since", since, "--until", daemonUnixTime(c), "--filter", fmt.Sprintf("image=%s", name)) 330 events := strings.Split(out, "\n") 331 events = events[:len(events)-1] 332 c.Assert(events, checker.Not(checker.HasLen), 0) //Expected events but found none for the image busybox:latest 333 count1 := 0 334 count2 := 0 335 336 for _, e := range events { 337 if strings.Contains(e, container1) { 338 count1++ 339 } else if strings.Contains(e, container2) { 340 count2++ 341 } 342 } 343 c.Assert(count1, checker.Not(checker.Equals), 0, check.Commentf("Expected event from container but got %d from %s", count1, container1)) 344 c.Assert(count2, checker.Not(checker.Equals), 0, check.Commentf("Expected event from container but got %d from %s", count2, container2)) 345 346 } 347 348 func (s *DockerSuite) TestEventsFilterLabels(c *check.C) { 349 since := daemonUnixTime(c) 350 label := "io.docker.testing=foo" 351 352 out, _ := dockerCmd(c, "run", "-d", "-l", label, "busybox:latest", "true") 353 container1 := strings.TrimSpace(out) 354 355 out, _ = dockerCmd(c, "run", "-d", "busybox", "true") 356 container2 := strings.TrimSpace(out) 357 358 out, _ = dockerCmd( 359 c, 360 "events", 361 "--since", since, 362 "--until", daemonUnixTime(c), 363 "--filter", fmt.Sprintf("label=%s", label)) 364 365 events := strings.Split(strings.TrimSpace(out), "\n") 366 c.Assert(len(events), checker.Equals, 3) 367 368 for _, e := range events { 369 c.Assert(e, checker.Contains, container1) 370 c.Assert(e, checker.Not(checker.Contains), container2) 371 } 372 } 373 374 func (s *DockerSuite) TestEventsFilterImageLabels(c *check.C) { 375 since := daemonUnixTime(c) 376 name := "labelfiltertest" 377 label := "io.docker.testing=image" 378 379 // Build a test image. 380 _, err := buildImage(name, fmt.Sprintf(` 381 FROM busybox:latest 382 LABEL %s`, label), true) 383 c.Assert(err, checker.IsNil, check.Commentf("Couldn't create image")) 384 385 dockerCmd(c, "tag", name, "labelfiltertest:tag1") 386 dockerCmd(c, "tag", name, "labelfiltertest:tag2") 387 dockerCmd(c, "tag", "busybox:latest", "labelfiltertest:tag3") 388 389 out, _ := dockerCmd( 390 c, 391 "events", 392 "--since", since, 393 "--until", daemonUnixTime(c), 394 "--filter", fmt.Sprintf("label=%s", label), 395 "--filter", "type=image") 396 397 events := strings.Split(strings.TrimSpace(out), "\n") 398 399 // 2 events from the "docker tag" command, another one is from "docker build" 400 c.Assert(events, checker.HasLen, 3, check.Commentf("Events == %s", events)) 401 for _, e := range events { 402 c.Assert(e, checker.Contains, "labelfiltertest") 403 } 404 } 405 406 func (s *DockerSuite) TestEventsFilterContainer(c *check.C) { 407 since := daemonUnixTime(c) 408 nameID := make(map[string]string) 409 410 for _, name := range []string{"container_1", "container_2"} { 411 dockerCmd(c, "run", "--name", name, "busybox", "true") 412 id := inspectField(c, name, "Id") 413 nameID[name] = id 414 } 415 416 until := daemonUnixTime(c) 417 418 checkEvents := func(id string, events []string) error { 419 if len(events) != 4 { // create, attach, start, die 420 return fmt.Errorf("expected 4 events, got %v", events) 421 } 422 for _, event := range events { 423 matches := eventstestutils.ScanMap(event) 424 if !matchEventID(matches, id) { 425 return fmt.Errorf("expected event for container id %s: %s - parsed container id: %s", id, event, matches["id"]) 426 } 427 } 428 return nil 429 } 430 431 for name, ID := range nameID { 432 // filter by names 433 out, _ := dockerCmd(c, "events", "--since", since, "--until", until, "--filter", "container="+name) 434 events := strings.Split(strings.TrimSuffix(out, "\n"), "\n") 435 c.Assert(checkEvents(ID, events), checker.IsNil) 436 437 // filter by ID's 438 out, _ = dockerCmd(c, "events", "--since", since, "--until", until, "--filter", "container="+ID) 439 events = strings.Split(strings.TrimSuffix(out, "\n"), "\n") 440 c.Assert(checkEvents(ID, events), checker.IsNil) 441 } 442 } 443 444 func (s *DockerSuite) TestEventsCommit(c *check.C) { 445 // Problematic on Windows as cannot commit a running container 446 testRequires(c, DaemonIsLinux) 447 448 out, _ := runSleepingContainer(c) 449 cID := strings.TrimSpace(out) 450 c.Assert(waitRun(cID), checker.IsNil) 451 452 dockerCmd(c, "commit", "-m", "test", cID) 453 dockerCmd(c, "stop", cID) 454 c.Assert(waitExited(cID, 5*time.Second), checker.IsNil) 455 456 until := daemonUnixTime(c) 457 out, _ = dockerCmd(c, "events", "-f", "container="+cID, "--until="+until) 458 c.Assert(out, checker.Contains, "commit", check.Commentf("Missing 'commit' log event")) 459 } 460 461 func (s *DockerSuite) TestEventsCopy(c *check.C) { 462 // Build a test image. 463 id, err := buildImage("cpimg", ` 464 FROM busybox 465 RUN echo HI > /file`, true) 466 c.Assert(err, checker.IsNil, check.Commentf("Couldn't create image")) 467 468 // Create an empty test file. 469 tempFile, err := ioutil.TempFile("", "test-events-copy-") 470 c.Assert(err, checker.IsNil) 471 defer os.Remove(tempFile.Name()) 472 473 c.Assert(tempFile.Close(), checker.IsNil) 474 475 dockerCmd(c, "create", "--name=cptest", id) 476 477 dockerCmd(c, "cp", "cptest:/file", tempFile.Name()) 478 479 until := daemonUnixTime(c) 480 out, _ := dockerCmd(c, "events", "--since=0", "-f", "container=cptest", "--until="+until) 481 c.Assert(out, checker.Contains, "archive-path", check.Commentf("Missing 'archive-path' log event\n")) 482 483 dockerCmd(c, "cp", tempFile.Name(), "cptest:/filecopy") 484 485 until = daemonUnixTime(c) 486 out, _ = dockerCmd(c, "events", "-f", "container=cptest", "--until="+until) 487 c.Assert(out, checker.Contains, "extract-to-dir", check.Commentf("Missing 'extract-to-dir' log event")) 488 } 489 490 func (s *DockerSuite) TestEventsResize(c *check.C) { 491 out, _ := runSleepingContainer(c, "-d") 492 cID := strings.TrimSpace(out) 493 c.Assert(waitRun(cID), checker.IsNil) 494 495 endpoint := "/containers/" + cID + "/resize?h=80&w=24" 496 status, _, err := sockRequest("POST", endpoint, nil) 497 c.Assert(status, checker.Equals, http.StatusOK) 498 c.Assert(err, checker.IsNil) 499 500 dockerCmd(c, "stop", cID) 501 502 until := daemonUnixTime(c) 503 out, _ = dockerCmd(c, "events", "-f", "container="+cID, "--until="+until) 504 c.Assert(out, checker.Contains, "resize", check.Commentf("Missing 'resize' log event")) 505 } 506 507 func (s *DockerSuite) TestEventsAttach(c *check.C) { 508 // TODO Windows CI: Figure out why this test fails intermittently (TP5). 509 testRequires(c, DaemonIsLinux) 510 511 out, _ := dockerCmd(c, "run", "-di", "busybox", "cat") 512 cID := strings.TrimSpace(out) 513 c.Assert(waitRun(cID), checker.IsNil) 514 515 cmd := exec.Command(dockerBinary, "attach", cID) 516 stdin, err := cmd.StdinPipe() 517 c.Assert(err, checker.IsNil) 518 defer stdin.Close() 519 stdout, err := cmd.StdoutPipe() 520 c.Assert(err, checker.IsNil) 521 defer stdout.Close() 522 c.Assert(cmd.Start(), checker.IsNil) 523 defer cmd.Process.Kill() 524 525 // Make sure we're done attaching by writing/reading some stuff 526 _, err = stdin.Write([]byte("hello\n")) 527 c.Assert(err, checker.IsNil) 528 out, err = bufio.NewReader(stdout).ReadString('\n') 529 c.Assert(err, checker.IsNil) 530 c.Assert(strings.TrimSpace(out), checker.Equals, "hello", check.Commentf("expected 'hello'")) 531 532 c.Assert(stdin.Close(), checker.IsNil) 533 534 dockerCmd(c, "kill", cID) 535 c.Assert(waitExited(cID, 5*time.Second), checker.IsNil) 536 537 until := daemonUnixTime(c) 538 out, _ = dockerCmd(c, "events", "-f", "container="+cID, "--until="+until) 539 c.Assert(out, checker.Contains, "attach", check.Commentf("Missing 'attach' log event")) 540 } 541 542 func (s *DockerSuite) TestEventsRename(c *check.C) { 543 out, _ := dockerCmd(c, "run", "--name", "oldName", "busybox", "true") 544 cID := strings.TrimSpace(out) 545 dockerCmd(c, "rename", "oldName", "newName") 546 547 until := daemonUnixTime(c) 548 // filter by the container id because the name in the event will be the new name. 549 out, _ = dockerCmd(c, "events", "-f", "container="+cID, "--until", until) 550 c.Assert(out, checker.Contains, "rename", check.Commentf("Missing 'rename' log event\n")) 551 } 552 553 func (s *DockerSuite) TestEventsTop(c *check.C) { 554 // Problematic on Windows as Windows does not support top 555 testRequires(c, DaemonIsLinux) 556 557 out, _ := runSleepingContainer(c, "-d") 558 cID := strings.TrimSpace(out) 559 c.Assert(waitRun(cID), checker.IsNil) 560 561 dockerCmd(c, "top", cID) 562 dockerCmd(c, "stop", cID) 563 564 until := daemonUnixTime(c) 565 out, _ = dockerCmd(c, "events", "-f", "container="+cID, "--until="+until) 566 c.Assert(out, checker.Contains, " top", check.Commentf("Missing 'top' log event")) 567 } 568 569 // #14316 570 func (s *DockerRegistrySuite) TestEventsImageFilterPush(c *check.C) { 571 // Problematic to port for Windows CI during TP5 timeframe until 572 // supporting push 573 testRequires(c, DaemonIsLinux) 574 testRequires(c, Network) 575 repoName := fmt.Sprintf("%v/dockercli/testf", privateRegistryURL) 576 577 out, _ := dockerCmd(c, "run", "-d", "busybox", "top") 578 cID := strings.TrimSpace(out) 579 c.Assert(waitRun(cID), checker.IsNil) 580 581 dockerCmd(c, "commit", cID, repoName) 582 dockerCmd(c, "stop", cID) 583 dockerCmd(c, "push", repoName) 584 585 until := daemonUnixTime(c) 586 out, _ = dockerCmd(c, "events", "-f", "image="+repoName, "-f", "event=push", "--until", until) 587 c.Assert(out, checker.Contains, repoName, check.Commentf("Missing 'push' log event for %s", repoName)) 588 } 589 590 func (s *DockerSuite) TestEventsFilterType(c *check.C) { 591 since := daemonUnixTime(c) 592 name := "labelfiltertest" 593 label := "io.docker.testing=image" 594 595 // Build a test image. 596 _, err := buildImage(name, fmt.Sprintf(` 597 FROM busybox:latest 598 LABEL %s`, label), true) 599 c.Assert(err, checker.IsNil, check.Commentf("Couldn't create image")) 600 601 dockerCmd(c, "tag", name, "labelfiltertest:tag1") 602 dockerCmd(c, "tag", name, "labelfiltertest:tag2") 603 dockerCmd(c, "tag", "busybox:latest", "labelfiltertest:tag3") 604 605 out, _ := dockerCmd( 606 c, 607 "events", 608 "--since", since, 609 "--until", daemonUnixTime(c), 610 "--filter", fmt.Sprintf("label=%s", label), 611 "--filter", "type=image") 612 613 events := strings.Split(strings.TrimSpace(out), "\n") 614 615 // 2 events from the "docker tag" command, another one is from "docker build" 616 c.Assert(events, checker.HasLen, 3, check.Commentf("Events == %s", events)) 617 for _, e := range events { 618 c.Assert(e, checker.Contains, "labelfiltertest") 619 } 620 621 out, _ = dockerCmd( 622 c, 623 "events", 624 "--since", since, 625 "--until", daemonUnixTime(c), 626 "--filter", fmt.Sprintf("label=%s", label), 627 "--filter", "type=container") 628 events = strings.Split(strings.TrimSpace(out), "\n") 629 630 // Events generated by the container that builds the image 631 c.Assert(events, checker.HasLen, 3, check.Commentf("Events == %s", events)) 632 633 out, _ = dockerCmd( 634 c, 635 "events", 636 "--since", since, 637 "--until", daemonUnixTime(c), 638 "--filter", "type=network") 639 events = strings.Split(strings.TrimSpace(out), "\n") 640 c.Assert(len(events), checker.GreaterOrEqualThan, 1, check.Commentf("Events == %s", events)) 641 } 642 643 // #25798 644 func (s *DockerSuite) TestEventsSpecialFiltersWithExecCreate(c *check.C) { 645 since := daemonUnixTime(c) 646 runSleepingContainer(c, "--name", "test-container", "-d") 647 waitRun("test-container") 648 649 dockerCmd(c, "exec", "test-container", "echo", "hello-world") 650 651 out, _ := dockerCmd( 652 c, 653 "events", 654 "--since", since, 655 "--until", daemonUnixTime(c), 656 "--filter", 657 "event='exec_create: echo hello-world'", 658 ) 659 660 events := strings.Split(strings.TrimSpace(out), "\n") 661 c.Assert(len(events), checker.Equals, 1, check.Commentf(out)) 662 663 out, _ = dockerCmd( 664 c, 665 "events", 666 "--since", since, 667 "--until", daemonUnixTime(c), 668 "--filter", 669 "event=exec_create", 670 ) 671 c.Assert(len(events), checker.Equals, 1, check.Commentf(out)) 672 } 673 674 func (s *DockerSuite) TestEventsFilterImageInContainerAction(c *check.C) { 675 since := daemonUnixTime(c) 676 dockerCmd(c, "run", "--name", "test-container", "-d", "busybox", "true") 677 waitRun("test-container") 678 679 out, _ := dockerCmd(c, "events", "--filter", "image=busybox", "--since", since, "--until", daemonUnixTime(c)) 680 events := strings.Split(strings.TrimSpace(out), "\n") 681 c.Assert(len(events), checker.GreaterThan, 1, check.Commentf(out)) 682 } 683 684 func (s *DockerSuite) TestEventsContainerRestart(c *check.C) { 685 dockerCmd(c, "run", "-d", "--name=testEvent", "--restart=on-failure:3", "busybox", "false") 686 687 // wait until test2 is auto removed. 688 waitTime := 10 * time.Second 689 if daemonPlatform == "windows" { 690 // Windows takes longer... 691 waitTime = 90 * time.Second 692 } 693 694 err := waitInspect("testEvent", "{{ .State.Restarting }} {{ .State.Running }}", "false false", waitTime) 695 c.Assert(err, checker.IsNil) 696 697 var ( 698 createCount int 699 startCount int 700 dieCount int 701 ) 702 out, _ := dockerCmd(c, "events", "--since=0", "--until", daemonUnixTime(c), "-f", "container=testEvent") 703 events := strings.Split(strings.TrimSpace(out), "\n") 704 705 nEvents := len(events) 706 c.Assert(nEvents, checker.GreaterOrEqualThan, 1) //Missing expected event 707 actions := eventActionsByIDAndType(c, events, "testEvent", "container") 708 709 for _, a := range actions { 710 switch a { 711 case "create": 712 createCount++ 713 case "start": 714 startCount++ 715 case "die": 716 dieCount++ 717 } 718 } 719 c.Assert(createCount, checker.Equals, 1, check.Commentf("testEvent should be created 1 times: %v", actions)) 720 c.Assert(startCount, checker.Equals, 4, check.Commentf("testEvent should start 4 times: %v", actions)) 721 c.Assert(dieCount, checker.Equals, 4, check.Commentf("testEvent should die 4 times: %v", actions)) 722 } 723 724 func (s *DockerSuite) TestEventsSinceInTheFuture(c *check.C) { 725 dockerCmd(c, "run", "--name", "test-container", "-d", "busybox", "true") 726 waitRun("test-container") 727 728 since := daemonTime(c) 729 until := since.Add(time.Duration(-24) * time.Hour) 730 out, _, err := dockerCmdWithError("events", "--filter", "image=busybox", "--since", parseEventTime(since), "--until", parseEventTime(until)) 731 732 c.Assert(err, checker.NotNil) 733 c.Assert(out, checker.Contains, "cannot be after `until`") 734 } 735 736 func (s *DockerSuite) TestEventsUntilInThePast(c *check.C) { 737 since := daemonUnixTime(c) 738 739 dockerCmd(c, "run", "--name", "test-container", "-d", "busybox", "true") 740 waitRun("test-container") 741 742 until := daemonUnixTime(c) 743 744 dockerCmd(c, "run", "--name", "test-container2", "-d", "busybox", "true") 745 waitRun("test-container2") 746 747 out, _ := dockerCmd(c, "events", "--filter", "image=busybox", "--since", since, "--until", until) 748 749 c.Assert(out, checker.Not(checker.Contains), "test-container2") 750 c.Assert(out, checker.Contains, "test-container") 751 } 752 753 func (s *DockerSuite) TestEventsFormat(c *check.C) { 754 since := daemonUnixTime(c) 755 dockerCmd(c, "run", "--rm", "busybox", "true") 756 dockerCmd(c, "run", "--rm", "busybox", "true") 757 out, _ := dockerCmd(c, "events", "--since", since, "--until", daemonUnixTime(c), "--format", "{{json .}}") 758 dec := json.NewDecoder(strings.NewReader(out)) 759 // make sure we got 2 start events 760 startCount := 0 761 for { 762 var err error 763 var ev eventtypes.Message 764 if err = dec.Decode(&ev); err == io.EOF { 765 break 766 } 767 c.Assert(err, checker.IsNil) 768 if ev.Status == "start" { 769 startCount++ 770 } 771 } 772 773 c.Assert(startCount, checker.Equals, 2, check.Commentf("should have had 2 start events but had %d, out: %s", startCount, out)) 774 } 775 776 func (s *DockerSuite) TestEventsFormatBadFunc(c *check.C) { 777 // make sure it fails immediately, without receiving any event 778 result := dockerCmdWithResult("events", "--format", "{{badFuncString .}}") 779 c.Assert(result, icmd.Matches, icmd.Expected{ 780 Error: "exit status 64", 781 ExitCode: 64, 782 Err: "Error parsing format: template: :1: function \"badFuncString\" not defined", 783 }) 784 } 785 786 func (s *DockerSuite) TestEventsFormatBadField(c *check.C) { 787 // make sure it fails immediately, without receiving any event 788 result := dockerCmdWithResult("events", "--format", "{{.badFieldString}}") 789 c.Assert(result, icmd.Matches, icmd.Expected{ 790 Error: "exit status 64", 791 ExitCode: 64, 792 Err: "Error parsing format: template: :1:2: executing \"\" at <.badFieldString>: can't evaluate field badFieldString in type *events.Message", 793 }) 794 }