github.com/jwhonce/docker@v0.6.7-0.20190327063223-da823cf3a5a3/integration-cli/docker_cli_events_unix_test.go (about) 1 // +build !windows 2 3 package main 4 5 import ( 6 "bufio" 7 "bytes" 8 "fmt" 9 "io/ioutil" 10 "os" 11 "os/exec" 12 "strings" 13 "time" 14 "unicode" 15 16 "github.com/docker/docker/integration-cli/checker" 17 "github.com/docker/docker/integration-cli/cli/build" 18 "github.com/go-check/check" 19 "github.com/kr/pty" 20 "golang.org/x/sys/unix" 21 ) 22 23 // #5979 24 func (s *DockerSuite) TestEventsRedirectStdout(c *check.C) { 25 since := daemonUnixTime(c) 26 dockerCmd(c, "run", "busybox", "true") 27 28 file, err := ioutil.TempFile("", "") 29 c.Assert(err, checker.IsNil, check.Commentf("could not create temp file")) 30 defer os.Remove(file.Name()) 31 32 command := fmt.Sprintf("%s events --since=%s --until=%s > %s", dockerBinary, since, daemonUnixTime(c), file.Name()) 33 _, tty, err := pty.Open() 34 c.Assert(err, checker.IsNil, check.Commentf("Could not open pty")) 35 cmd := exec.Command("sh", "-c", command) 36 cmd.Stdin = tty 37 cmd.Stdout = tty 38 cmd.Stderr = tty 39 c.Assert(cmd.Run(), checker.IsNil, check.Commentf("run err for command %q", command)) 40 41 scanner := bufio.NewScanner(file) 42 for scanner.Scan() { 43 for _, ch := range scanner.Text() { 44 c.Assert(unicode.IsControl(ch), checker.False, check.Commentf("found control character %v", []byte(string(ch)))) 45 } 46 } 47 c.Assert(scanner.Err(), checker.IsNil, check.Commentf("Scan err for command %q", command)) 48 49 } 50 51 func (s *DockerSuite) TestEventsOOMDisableFalse(c *check.C) { 52 testRequires(c, DaemonIsLinux, oomControl, memoryLimitSupport, swapMemorySupport, NotPpc64le) 53 54 errChan := make(chan error) 55 go func() { 56 defer close(errChan) 57 out, exitCode, _ := dockerCmdWithError("run", "--name", "oomFalse", "-m", "10MB", "busybox", "sh", "-c", "x=a; while true; do x=$x$x$x$x; done") 58 if expected := 137; exitCode != expected { 59 errChan <- fmt.Errorf("wrong exit code for OOM container: expected %d, got %d (output: %q)", expected, exitCode, out) 60 } 61 }() 62 select { 63 case err := <-errChan: 64 c.Assert(err, checker.IsNil) 65 case <-time.After(30 * time.Second): 66 c.Fatal("Timeout waiting for container to die on OOM") 67 } 68 69 out, _ := dockerCmd(c, "events", "--since=0", "-f", "container=oomFalse", "--until", daemonUnixTime(c)) 70 events := strings.Split(strings.TrimSuffix(out, "\n"), "\n") 71 nEvents := len(events) 72 73 c.Assert(nEvents, checker.GreaterOrEqualThan, 5) //Missing expected event 74 c.Assert(parseEventAction(c, events[nEvents-5]), checker.Equals, "create") 75 c.Assert(parseEventAction(c, events[nEvents-4]), checker.Equals, "attach") 76 c.Assert(parseEventAction(c, events[nEvents-3]), checker.Equals, "start") 77 c.Assert(parseEventAction(c, events[nEvents-2]), checker.Equals, "oom") 78 c.Assert(parseEventAction(c, events[nEvents-1]), checker.Equals, "die") 79 } 80 81 func (s *DockerSuite) TestEventsOOMDisableTrue(c *check.C) { 82 testRequires(c, DaemonIsLinux, oomControl, memoryLimitSupport, NotArm, swapMemorySupport, NotPpc64le) 83 84 errChan := make(chan error) 85 observer, err := newEventObserver(c) 86 c.Assert(err, checker.IsNil) 87 err = observer.Start() 88 c.Assert(err, checker.IsNil) 89 defer observer.Stop() 90 91 go func() { 92 defer close(errChan) 93 out, exitCode, _ := dockerCmdWithError("run", "--oom-kill-disable=true", "--name", "oomTrue", "-m", "10MB", "busybox", "sh", "-c", "x=a; while true; do x=$x$x$x$x; done") 94 if expected := 137; exitCode != expected { 95 errChan <- fmt.Errorf("wrong exit code for OOM container: expected %d, got %d (output: %q)", expected, exitCode, out) 96 } 97 }() 98 99 c.Assert(waitRun("oomTrue"), checker.IsNil) 100 defer dockerCmdWithResult("kill", "oomTrue") 101 containerID := inspectField(c, "oomTrue", "Id") 102 103 testActions := map[string]chan bool{ 104 "oom": make(chan bool), 105 } 106 107 matcher := matchEventLine(containerID, "container", testActions) 108 processor := processEventMatch(testActions) 109 go observer.Match(matcher, processor) 110 111 select { 112 case <-time.After(20 * time.Second): 113 observer.CheckEventError(c, containerID, "oom", matcher) 114 case <-testActions["oom"]: 115 // ignore, done 116 case errRun := <-errChan: 117 if errRun != nil { 118 c.Fatalf("%v", errRun) 119 } else { 120 c.Fatalf("container should be still running but it's not") 121 } 122 } 123 124 status := inspectField(c, "oomTrue", "State.Status") 125 c.Assert(strings.TrimSpace(status), checker.Equals, "running", check.Commentf("container should be still running")) 126 } 127 128 // #18453 129 func (s *DockerSuite) TestEventsContainerFilterByName(c *check.C) { 130 testRequires(c, DaemonIsLinux) 131 cOut, _ := dockerCmd(c, "run", "--name=foo", "-d", "busybox", "top") 132 c1 := strings.TrimSpace(cOut) 133 waitRun("foo") 134 cOut, _ = dockerCmd(c, "run", "--name=bar", "-d", "busybox", "top") 135 c2 := strings.TrimSpace(cOut) 136 waitRun("bar") 137 out, _ := dockerCmd(c, "events", "-f", "container=foo", "--since=0", "--until", daemonUnixTime(c)) 138 c.Assert(out, checker.Contains, c1, check.Commentf("%s", out)) 139 c.Assert(out, checker.Not(checker.Contains), c2, check.Commentf("%s", out)) 140 } 141 142 // #18453 143 func (s *DockerSuite) TestEventsContainerFilterBeforeCreate(c *check.C) { 144 testRequires(c, DaemonIsLinux) 145 buf := &bytes.Buffer{} 146 cmd := exec.Command(dockerBinary, "events", "-f", "container=foo", "--since=0") 147 cmd.Stdout = buf 148 c.Assert(cmd.Start(), check.IsNil) 149 defer cmd.Wait() 150 defer cmd.Process.Kill() 151 152 // Sleep for a second to make sure we are testing the case where events are listened before container starts. 153 time.Sleep(time.Second) 154 id, _ := dockerCmd(c, "run", "--name=foo", "-d", "busybox", "top") 155 cID := strings.TrimSpace(id) 156 for i := 0; ; i++ { 157 out := buf.String() 158 if strings.Contains(out, cID) { 159 break 160 } 161 if i > 30 { 162 c.Fatalf("Missing event of container (foo, %v), got %q", cID, out) 163 } 164 time.Sleep(500 * time.Millisecond) 165 } 166 } 167 168 func (s *DockerSuite) TestVolumeEvents(c *check.C) { 169 testRequires(c, DaemonIsLinux) 170 171 since := daemonUnixTime(c) 172 173 // Observe create/mount volume actions 174 dockerCmd(c, "volume", "create", "test-event-volume-local") 175 dockerCmd(c, "run", "--name", "test-volume-container", "--volume", "test-event-volume-local:/foo", "-d", "busybox", "true") 176 waitRun("test-volume-container") 177 178 // Observe unmount/destroy volume actions 179 dockerCmd(c, "rm", "-f", "test-volume-container") 180 dockerCmd(c, "volume", "rm", "test-event-volume-local") 181 182 until := daemonUnixTime(c) 183 out, _ := dockerCmd(c, "events", "--since", since, "--until", until) 184 events := strings.Split(strings.TrimSpace(out), "\n") 185 c.Assert(len(events), checker.GreaterThan, 4) 186 187 volumeEvents := eventActionsByIDAndType(c, events, "test-event-volume-local", "volume") 188 c.Assert(volumeEvents, checker.HasLen, 5) 189 c.Assert(volumeEvents[0], checker.Equals, "create") 190 c.Assert(volumeEvents[1], checker.Equals, "create") 191 c.Assert(volumeEvents[2], checker.Equals, "mount") 192 c.Assert(volumeEvents[3], checker.Equals, "unmount") 193 c.Assert(volumeEvents[4], checker.Equals, "destroy") 194 } 195 196 func (s *DockerSuite) TestNetworkEvents(c *check.C) { 197 testRequires(c, DaemonIsLinux) 198 199 since := daemonUnixTime(c) 200 201 // Observe create/connect network actions 202 dockerCmd(c, "network", "create", "test-event-network-local") 203 dockerCmd(c, "run", "--name", "test-network-container", "--net", "test-event-network-local", "-d", "busybox", "true") 204 waitRun("test-network-container") 205 206 // Observe disconnect/destroy network actions 207 dockerCmd(c, "rm", "-f", "test-network-container") 208 dockerCmd(c, "network", "rm", "test-event-network-local") 209 210 until := daemonUnixTime(c) 211 out, _ := dockerCmd(c, "events", "--since", since, "--until", until) 212 events := strings.Split(strings.TrimSpace(out), "\n") 213 c.Assert(len(events), checker.GreaterThan, 4) 214 215 netEvents := eventActionsByIDAndType(c, events, "test-event-network-local", "network") 216 c.Assert(netEvents, checker.HasLen, 4) 217 c.Assert(netEvents[0], checker.Equals, "create") 218 c.Assert(netEvents[1], checker.Equals, "connect") 219 c.Assert(netEvents[2], checker.Equals, "disconnect") 220 c.Assert(netEvents[3], checker.Equals, "destroy") 221 } 222 223 func (s *DockerSuite) TestEventsContainerWithMultiNetwork(c *check.C) { 224 testRequires(c, DaemonIsLinux) 225 226 // Observe create/connect network actions 227 dockerCmd(c, "network", "create", "test-event-network-local-1") 228 dockerCmd(c, "network", "create", "test-event-network-local-2") 229 dockerCmd(c, "run", "--name", "test-network-container", "--net", "test-event-network-local-1", "-td", "busybox", "sh") 230 waitRun("test-network-container") 231 dockerCmd(c, "network", "connect", "test-event-network-local-2", "test-network-container") 232 233 since := daemonUnixTime(c) 234 235 dockerCmd(c, "stop", "-t", "1", "test-network-container") 236 237 until := daemonUnixTime(c) 238 out, _ := dockerCmd(c, "events", "--since", since, "--until", until, "-f", "type=network") 239 netEvents := strings.Split(strings.TrimSpace(out), "\n") 240 241 // received two network disconnect events 242 c.Assert(len(netEvents), checker.Equals, 2) 243 c.Assert(netEvents[0], checker.Contains, "disconnect") 244 c.Assert(netEvents[1], checker.Contains, "disconnect") 245 246 //both networks appeared in the network event output 247 c.Assert(out, checker.Contains, "test-event-network-local-1") 248 c.Assert(out, checker.Contains, "test-event-network-local-2") 249 } 250 251 func (s *DockerSuite) TestEventsStreaming(c *check.C) { 252 testRequires(c, DaemonIsLinux) 253 254 observer, err := newEventObserver(c) 255 c.Assert(err, checker.IsNil) 256 err = observer.Start() 257 c.Assert(err, checker.IsNil) 258 defer observer.Stop() 259 260 out, _ := dockerCmd(c, "run", "-d", "busybox:latest", "true") 261 containerID := strings.TrimSpace(out) 262 263 testActions := map[string]chan bool{ 264 "create": make(chan bool, 1), 265 "start": make(chan bool, 1), 266 "die": make(chan bool, 1), 267 "destroy": make(chan bool, 1), 268 } 269 270 matcher := matchEventLine(containerID, "container", testActions) 271 processor := processEventMatch(testActions) 272 go observer.Match(matcher, processor) 273 274 select { 275 case <-time.After(5 * time.Second): 276 observer.CheckEventError(c, containerID, "create", matcher) 277 case <-testActions["create"]: 278 // ignore, done 279 } 280 281 select { 282 case <-time.After(5 * time.Second): 283 observer.CheckEventError(c, containerID, "start", matcher) 284 case <-testActions["start"]: 285 // ignore, done 286 } 287 288 select { 289 case <-time.After(5 * time.Second): 290 observer.CheckEventError(c, containerID, "die", matcher) 291 case <-testActions["die"]: 292 // ignore, done 293 } 294 295 dockerCmd(c, "rm", containerID) 296 297 select { 298 case <-time.After(5 * time.Second): 299 observer.CheckEventError(c, containerID, "destroy", matcher) 300 case <-testActions["destroy"]: 301 // ignore, done 302 } 303 } 304 305 func (s *DockerSuite) TestEventsImageUntagDelete(c *check.C) { 306 testRequires(c, DaemonIsLinux) 307 308 observer, err := newEventObserver(c) 309 c.Assert(err, checker.IsNil) 310 err = observer.Start() 311 c.Assert(err, checker.IsNil) 312 defer observer.Stop() 313 314 name := "testimageevents" 315 buildImageSuccessfully(c, name, build.WithDockerfile(`FROM scratch 316 MAINTAINER "docker"`)) 317 imageID := getIDByName(c, name) 318 c.Assert(deleteImages(name), checker.IsNil) 319 320 testActions := map[string]chan bool{ 321 "untag": make(chan bool, 1), 322 "delete": make(chan bool, 1), 323 } 324 325 matcher := matchEventLine(imageID, "image", testActions) 326 processor := processEventMatch(testActions) 327 go observer.Match(matcher, processor) 328 329 select { 330 case <-time.After(10 * time.Second): 331 observer.CheckEventError(c, imageID, "untag", matcher) 332 case <-testActions["untag"]: 333 // ignore, done 334 } 335 336 select { 337 case <-time.After(10 * time.Second): 338 observer.CheckEventError(c, imageID, "delete", matcher) 339 case <-testActions["delete"]: 340 // ignore, done 341 } 342 } 343 344 func (s *DockerSuite) TestEventsFilterVolumeAndNetworkType(c *check.C) { 345 testRequires(c, DaemonIsLinux) 346 347 since := daemonUnixTime(c) 348 349 dockerCmd(c, "network", "create", "test-event-network-type") 350 dockerCmd(c, "volume", "create", "test-event-volume-type") 351 352 out, _ := dockerCmd(c, "events", "--filter", "type=volume", "--filter", "type=network", "--since", since, "--until", daemonUnixTime(c)) 353 events := strings.Split(strings.TrimSpace(out), "\n") 354 c.Assert(len(events), checker.GreaterOrEqualThan, 2, check.Commentf("%s", out)) 355 356 networkActions := eventActionsByIDAndType(c, events, "test-event-network-type", "network") 357 volumeActions := eventActionsByIDAndType(c, events, "test-event-volume-type", "volume") 358 359 c.Assert(volumeActions[0], checker.Equals, "create") 360 c.Assert(networkActions[0], checker.Equals, "create") 361 } 362 363 func (s *DockerSuite) TestEventsFilterVolumeID(c *check.C) { 364 testRequires(c, DaemonIsLinux) 365 366 since := daemonUnixTime(c) 367 368 dockerCmd(c, "volume", "create", "test-event-volume-id") 369 out, _ := dockerCmd(c, "events", "--filter", "volume=test-event-volume-id", "--since", since, "--until", daemonUnixTime(c)) 370 events := strings.Split(strings.TrimSpace(out), "\n") 371 c.Assert(events, checker.HasLen, 1) 372 373 c.Assert(events[0], checker.Contains, "test-event-volume-id") 374 c.Assert(events[0], checker.Contains, "driver=local") 375 } 376 377 func (s *DockerSuite) TestEventsFilterNetworkID(c *check.C) { 378 testRequires(c, DaemonIsLinux) 379 380 since := daemonUnixTime(c) 381 382 dockerCmd(c, "network", "create", "test-event-network-local") 383 out, _ := dockerCmd(c, "events", "--filter", "network=test-event-network-local", "--since", since, "--until", daemonUnixTime(c)) 384 events := strings.Split(strings.TrimSpace(out), "\n") 385 c.Assert(events, checker.HasLen, 1) 386 387 c.Assert(events[0], checker.Contains, "test-event-network-local") 388 c.Assert(events[0], checker.Contains, "type=bridge") 389 } 390 391 func (s *DockerDaemonSuite) TestDaemonEvents(c *check.C) { 392 testRequires(c, testEnv.IsLocalDaemon, DaemonIsLinux) 393 394 // daemon config file 395 configFilePath := "test.json" 396 configFile, err := os.Create(configFilePath) 397 c.Assert(err, checker.IsNil) 398 defer os.Remove(configFilePath) 399 400 daemonConfig := `{"labels":["foo=bar"]}` 401 fmt.Fprintf(configFile, "%s", daemonConfig) 402 configFile.Close() 403 s.d.Start(c, fmt.Sprintf("--config-file=%s", configFilePath)) 404 405 // Get daemon ID 406 out, err := s.d.Cmd("info") 407 c.Assert(err, checker.IsNil) 408 daemonID := "" 409 daemonName := "" 410 for _, line := range strings.Split(out, "\n") { 411 if strings.HasPrefix(line, "ID: ") { 412 daemonID = strings.TrimPrefix(line, "ID: ") 413 } else if strings.HasPrefix(line, "Name: ") { 414 daemonName = strings.TrimPrefix(line, "Name: ") 415 } 416 } 417 c.Assert(daemonID, checker.Not(checker.Equals), "") 418 419 configFile, err = os.Create(configFilePath) 420 c.Assert(err, checker.IsNil) 421 daemonConfig = `{"max-concurrent-downloads":1,"labels":["bar=foo"], "shutdown-timeout": 10}` 422 fmt.Fprintf(configFile, "%s", daemonConfig) 423 configFile.Close() 424 425 c.Assert(s.d.Signal(unix.SIGHUP), checker.IsNil) 426 427 time.Sleep(3 * time.Second) 428 429 out, err = s.d.Cmd("events", "--since=0", "--until", daemonUnixTime(c)) 430 c.Assert(err, checker.IsNil) 431 432 // only check for values known (daemon ID/name) or explicitly set above, 433 // otherwise just check for names being present. 434 expectedSubstrings := []string{ 435 " daemon reload " + daemonID + " ", 436 "(allow-nondistributable-artifacts=[", 437 " cluster-advertise=, ", 438 " cluster-store=, ", 439 " cluster-store-opts=", 440 " debug=true, ", 441 " default-ipc-mode=", 442 " default-runtime=", 443 " default-shm-size=", 444 " insecure-registries=[", 445 " labels=[\"bar=foo\"], ", 446 " live-restore=", 447 " max-concurrent-downloads=1, ", 448 " max-concurrent-uploads=5, ", 449 " name=" + daemonName, 450 " registry-mirrors=[", 451 " runtimes=", 452 " shutdown-timeout=10)", 453 } 454 455 for _, s := range expectedSubstrings { 456 c.Assert(out, checker.Contains, s) 457 } 458 } 459 460 func (s *DockerDaemonSuite) TestDaemonEventsWithFilters(c *check.C) { 461 testRequires(c, testEnv.IsLocalDaemon, DaemonIsLinux) 462 463 // daemon config file 464 configFilePath := "test.json" 465 configFile, err := os.Create(configFilePath) 466 c.Assert(err, checker.IsNil) 467 defer os.Remove(configFilePath) 468 469 daemonConfig := `{"labels":["foo=bar"]}` 470 fmt.Fprintf(configFile, "%s", daemonConfig) 471 configFile.Close() 472 s.d.Start(c, fmt.Sprintf("--config-file=%s", configFilePath)) 473 474 // Get daemon ID 475 out, err := s.d.Cmd("info") 476 c.Assert(err, checker.IsNil) 477 daemonID := "" 478 daemonName := "" 479 for _, line := range strings.Split(out, "\n") { 480 if strings.HasPrefix(line, "ID: ") { 481 daemonID = strings.TrimPrefix(line, "ID: ") 482 } else if strings.HasPrefix(line, "Name: ") { 483 daemonName = strings.TrimPrefix(line, "Name: ") 484 } 485 } 486 c.Assert(daemonID, checker.Not(checker.Equals), "") 487 488 c.Assert(s.d.Signal(unix.SIGHUP), checker.IsNil) 489 490 time.Sleep(3 * time.Second) 491 492 out, err = s.d.Cmd("events", "--since=0", "--until", daemonUnixTime(c), "--filter", fmt.Sprintf("daemon=%s", daemonID)) 493 c.Assert(err, checker.IsNil) 494 c.Assert(out, checker.Contains, fmt.Sprintf("daemon reload %s", daemonID)) 495 496 out, err = s.d.Cmd("events", "--since=0", "--until", daemonUnixTime(c), "--filter", fmt.Sprintf("daemon=%s", daemonName)) 497 c.Assert(err, checker.IsNil) 498 c.Assert(out, checker.Contains, fmt.Sprintf("daemon reload %s", daemonID)) 499 500 out, err = s.d.Cmd("events", "--since=0", "--until", daemonUnixTime(c), "--filter", "daemon=foo") 501 c.Assert(err, checker.IsNil) 502 c.Assert(out, checker.Not(checker.Contains), fmt.Sprintf("daemon reload %s", daemonID)) 503 504 out, err = s.d.Cmd("events", "--since=0", "--until", daemonUnixTime(c), "--filter", "type=daemon") 505 c.Assert(err, checker.IsNil) 506 c.Assert(out, checker.Contains, fmt.Sprintf("daemon reload %s", daemonID)) 507 508 out, err = s.d.Cmd("events", "--since=0", "--until", daemonUnixTime(c), "--filter", "type=container") 509 c.Assert(err, checker.IsNil) 510 c.Assert(out, checker.Not(checker.Contains), fmt.Sprintf("daemon reload %s", daemonID)) 511 }