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