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