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