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