github.com/ncdc/docker@v0.10.1-0.20160129113957-6c6729ef5b74/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 "time" 13 "unicode" 14 15 "github.com/docker/docker/pkg/integration/checker" 16 "github.com/go-check/check" 17 "github.com/kr/pty" 18 ) 19 20 // #5979 21 func (s *DockerSuite) TestEventsRedirectStdout(c *check.C) { 22 since := daemonTime(c).Unix() 23 dockerCmd(c, "run", "busybox", "true") 24 25 file, err := ioutil.TempFile("", "") 26 c.Assert(err, checker.IsNil, check.Commentf("could not create temp file")) 27 defer os.Remove(file.Name()) 28 29 command := fmt.Sprintf("%s events --since=%d --until=%d > %s", dockerBinary, since, daemonTime(c).Unix(), file.Name()) 30 _, tty, err := pty.Open() 31 c.Assert(err, checker.IsNil, check.Commentf("Could not open pty")) 32 cmd := exec.Command("sh", "-c", command) 33 cmd.Stdin = tty 34 cmd.Stdout = tty 35 cmd.Stderr = tty 36 c.Assert(cmd.Run(), checker.IsNil, check.Commentf("run err for command %q", command)) 37 38 scanner := bufio.NewScanner(file) 39 for scanner.Scan() { 40 for _, ch := range scanner.Text() { 41 c.Assert(unicode.IsControl(ch), checker.False, check.Commentf("found control character %v", []byte(string(ch)))) 42 } 43 } 44 c.Assert(scanner.Err(), checker.IsNil, check.Commentf("Scan err for command %q", command)) 45 46 } 47 48 func (s *DockerSuite) TestEventsOOMDisableFalse(c *check.C) { 49 testRequires(c, DaemonIsLinux, oomControl, memoryLimitSupport, NotGCCGO) 50 51 errChan := make(chan error) 52 go func() { 53 defer close(errChan) 54 out, exitCode, _ := dockerCmdWithError("run", "--name", "oomFalse", "-m", "10MB", "busybox", "sh", "-c", "x=a; while true; do x=$x$x$x$x; done") 55 if expected := 137; exitCode != expected { 56 errChan <- fmt.Errorf("wrong exit code for OOM container: expected %d, got %d (output: %q)", expected, exitCode, out) 57 } 58 }() 59 select { 60 case err := <-errChan: 61 c.Assert(err, checker.IsNil) 62 case <-time.After(30 * time.Second): 63 c.Fatal("Timeout waiting for container to die on OOM") 64 } 65 66 out, _ := dockerCmd(c, "events", "--since=0", "-f", "container=oomFalse", fmt.Sprintf("--until=%d", daemonTime(c).Unix())) 67 events := strings.Split(strings.TrimSuffix(out, "\n"), "\n") 68 nEvents := len(events) 69 70 c.Assert(nEvents, checker.GreaterOrEqualThan, 5) //Missing expected event 71 c.Assert(parseEventAction(c, events[nEvents-5]), checker.Equals, "create") 72 c.Assert(parseEventAction(c, events[nEvents-4]), checker.Equals, "attach") 73 c.Assert(parseEventAction(c, events[nEvents-3]), checker.Equals, "start") 74 c.Assert(parseEventAction(c, events[nEvents-2]), checker.Equals, "oom") 75 c.Assert(parseEventAction(c, events[nEvents-1]), checker.Equals, "die") 76 } 77 78 func (s *DockerSuite) TestEventsOOMDisableTrue(c *check.C) { 79 testRequires(c, DaemonIsLinux, oomControl, memoryLimitSupport, NotGCCGO, NotArm) 80 81 errChan := make(chan error) 82 observer, err := newEventObserver(c) 83 c.Assert(err, checker.IsNil) 84 err = observer.Start() 85 c.Assert(err, checker.IsNil) 86 defer observer.Stop() 87 88 go func() { 89 defer close(errChan) 90 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") 91 if expected := 137; exitCode != expected { 92 errChan <- fmt.Errorf("wrong exit code for OOM container: expected %d, got %d (output: %q)", expected, exitCode, out) 93 } 94 }() 95 96 c.Assert(waitRun("oomTrue"), checker.IsNil) 97 defer dockerCmd(c, "kill", "oomTrue") 98 containerID, err := inspectField("oomTrue", "Id") 99 c.Assert(err, checker.IsNil) 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, err := inspectField("oomTrue", "State.Status") 123 c.Assert(err, checker.IsNil) 124 c.Assert(strings.TrimSpace(status), checker.Equals, "running", check.Commentf("container should be still running")) 125 } 126 127 // #18453 128 func (s *DockerSuite) TestEventsContainerFilterByName(c *check.C) { 129 testRequires(c, DaemonIsLinux) 130 cOut, _ := dockerCmd(c, "run", "--name=foo", "-d", "busybox", "top") 131 c1 := strings.TrimSpace(cOut) 132 waitRun("foo") 133 cOut, _ = dockerCmd(c, "run", "--name=bar", "-d", "busybox", "top") 134 c2 := strings.TrimSpace(cOut) 135 waitRun("bar") 136 out, _ := dockerCmd(c, "events", "-f", "container=foo", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix())) 137 c.Assert(out, checker.Contains, c1, check.Commentf(out)) 138 c.Assert(out, checker.Not(checker.Contains), c2, check.Commentf(out)) 139 } 140 141 // #18453 142 func (s *DockerSuite) TestEventsContainerFilterBeforeCreate(c *check.C) { 143 testRequires(c, DaemonIsLinux) 144 var ( 145 out string 146 ch chan struct{} 147 ) 148 ch = make(chan struct{}) 149 150 // calculate the time it takes to create and start a container and sleep 2 seconds 151 // this is to make sure the docker event will recevie the event of container 152 since := daemonTime(c).Unix() 153 id, _ := dockerCmd(c, "run", "-d", "busybox", "top") 154 cID := strings.TrimSpace(id) 155 waitRun(cID) 156 time.Sleep(2 * time.Second) 157 duration := daemonTime(c).Unix() - since 158 159 go func() { 160 out, _ = dockerCmd(c, "events", "-f", "container=foo", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()+2*duration)) 161 close(ch) 162 }() 163 // Sleep 2 second to wait docker event to start 164 time.Sleep(2 * time.Second) 165 id, _ = dockerCmd(c, "run", "--name=foo", "-d", "busybox", "top") 166 cID = strings.TrimSpace(id) 167 waitRun(cID) 168 <-ch 169 c.Assert(out, checker.Contains, cID, check.Commentf("Missing event of container (foo)")) 170 } 171 172 func (s *DockerSuite) TestVolumeEvents(c *check.C) { 173 testRequires(c, DaemonIsLinux) 174 175 since := daemonTime(c).Unix() 176 177 // Observe create/mount volume actions 178 dockerCmd(c, "volume", "create", "--name", "test-event-volume-local") 179 dockerCmd(c, "run", "--name", "test-volume-container", "--volume", "test-event-volume-local:/foo", "-d", "busybox", "true") 180 waitRun("test-volume-container") 181 182 // Observe unmount/destroy volume actions 183 dockerCmd(c, "rm", "-f", "test-volume-container") 184 dockerCmd(c, "volume", "rm", "test-event-volume-local") 185 186 out, _ := dockerCmd(c, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix())) 187 events := strings.Split(strings.TrimSpace(out), "\n") 188 c.Assert(len(events), checker.GreaterThan, 4) 189 190 volumeEvents := eventActionsByIDAndType(c, events, "test-event-volume-local", "volume") 191 c.Assert(volumeEvents, checker.HasLen, 4) 192 c.Assert(volumeEvents[0], checker.Equals, "create") 193 c.Assert(volumeEvents[1], checker.Equals, "mount") 194 c.Assert(volumeEvents[2], checker.Equals, "unmount") 195 c.Assert(volumeEvents[3], checker.Equals, "destroy") 196 } 197 198 func (s *DockerSuite) TestNetworkEvents(c *check.C) { 199 testRequires(c, DaemonIsLinux) 200 201 since := daemonTime(c).Unix() 202 203 // Observe create/connect network actions 204 dockerCmd(c, "network", "create", "test-event-network-local") 205 dockerCmd(c, "run", "--name", "test-network-container", "--net", "test-event-network-local", "-d", "busybox", "true") 206 waitRun("test-network-container") 207 208 // Observe disconnect/destroy network actions 209 dockerCmd(c, "rm", "-f", "test-network-container") 210 dockerCmd(c, "network", "rm", "test-event-network-local") 211 212 out, _ := dockerCmd(c, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix())) 213 events := strings.Split(strings.TrimSpace(out), "\n") 214 c.Assert(len(events), checker.GreaterThan, 4) 215 216 netEvents := eventActionsByIDAndType(c, events, "test-event-network-local", "network") 217 c.Assert(netEvents, checker.HasLen, 4) 218 c.Assert(netEvents[0], checker.Equals, "create") 219 c.Assert(netEvents[1], checker.Equals, "connect") 220 c.Assert(netEvents[2], checker.Equals, "disconnect") 221 c.Assert(netEvents[3], checker.Equals, "destroy") 222 } 223 224 func (s *DockerSuite) TestEventsStreaming(c *check.C) { 225 testRequires(c, DaemonIsLinux) 226 227 observer, err := newEventObserver(c) 228 c.Assert(err, checker.IsNil) 229 err = observer.Start() 230 c.Assert(err, checker.IsNil) 231 defer observer.Stop() 232 233 out, _ := dockerCmd(c, "run", "-d", "busybox:latest", "true") 234 containerID := strings.TrimSpace(out) 235 236 testActions := map[string]chan bool{ 237 "create": make(chan bool), 238 "start": make(chan bool), 239 "die": make(chan bool), 240 "destroy": make(chan bool), 241 } 242 243 matcher := matchEventLine(containerID, "container", testActions) 244 processor := processEventMatch(testActions) 245 go observer.Match(matcher, processor) 246 247 select { 248 case <-time.After(5 * time.Second): 249 observer.CheckEventError(c, containerID, "create", matcher) 250 case <-testActions["create"]: 251 // ignore, done 252 } 253 254 select { 255 case <-time.After(5 * time.Second): 256 observer.CheckEventError(c, containerID, "start", matcher) 257 case <-testActions["start"]: 258 // ignore, done 259 } 260 261 select { 262 case <-time.After(5 * time.Second): 263 observer.CheckEventError(c, containerID, "die", matcher) 264 case <-testActions["die"]: 265 // ignore, done 266 } 267 268 dockerCmd(c, "rm", containerID) 269 270 select { 271 case <-time.After(5 * time.Second): 272 observer.CheckEventError(c, containerID, "destroy", matcher) 273 case <-testActions["destroy"]: 274 // ignore, done 275 } 276 } 277 278 func (s *DockerSuite) TestEventsImageUntagDelete(c *check.C) { 279 testRequires(c, DaemonIsLinux) 280 281 observer, err := newEventObserver(c) 282 c.Assert(err, checker.IsNil) 283 err = observer.Start() 284 c.Assert(err, checker.IsNil) 285 defer observer.Stop() 286 287 name := "testimageevents" 288 imageID, err := buildImage(name, 289 `FROM scratch 290 MAINTAINER "docker"`, 291 true) 292 c.Assert(err, checker.IsNil) 293 c.Assert(deleteImages(name), checker.IsNil) 294 295 testActions := map[string]chan bool{ 296 "untag": make(chan bool), 297 "delete": make(chan bool), 298 } 299 300 matcher := matchEventLine(imageID, "image", testActions) 301 processor := processEventMatch(testActions) 302 go observer.Match(matcher, processor) 303 304 select { 305 case <-time.After(10 * time.Second): 306 observer.CheckEventError(c, imageID, "untag", matcher) 307 case <-testActions["untag"]: 308 // ignore, done 309 } 310 311 select { 312 case <-time.After(10 * time.Second): 313 observer.CheckEventError(c, imageID, "delete", matcher) 314 case <-testActions["delete"]: 315 // ignore, done 316 } 317 } 318 319 func (s *DockerSuite) TestEventsFilterVolumeAndNetworkType(c *check.C) { 320 testRequires(c, DaemonIsLinux) 321 322 since := daemonTime(c).Unix() 323 324 dockerCmd(c, "network", "create", "test-event-network-type") 325 dockerCmd(c, "volume", "create", "--name", "test-event-volume-type") 326 327 out, _ := dockerCmd(c, "events", "--filter", "type=volume", "--filter", "type=network", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix())) 328 events := strings.Split(strings.TrimSpace(out), "\n") 329 c.Assert(len(events), checker.GreaterOrEqualThan, 2, check.Commentf(out)) 330 331 networkActions := eventActionsByIDAndType(c, events, "test-event-network-type", "network") 332 volumeActions := eventActionsByIDAndType(c, events, "test-event-volume-type", "volume") 333 334 c.Assert(volumeActions[0], checker.Equals, "create") 335 c.Assert(networkActions[0], checker.Equals, "create") 336 } 337 338 func (s *DockerSuite) TestEventsFilterVolumeID(c *check.C) { 339 testRequires(c, DaemonIsLinux) 340 341 since := daemonTime(c).Unix() 342 343 dockerCmd(c, "volume", "create", "--name", "test-event-volume-id") 344 out, _ := dockerCmd(c, "events", "--filter", "volume=test-event-volume-id", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix())) 345 events := strings.Split(strings.TrimSpace(out), "\n") 346 c.Assert(events, checker.HasLen, 1) 347 348 c.Assert(events[0], checker.Contains, "test-event-volume-id") 349 c.Assert(events[0], checker.Contains, "driver=local") 350 } 351 352 func (s *DockerSuite) TestEventsFilterNetworkID(c *check.C) { 353 testRequires(c, DaemonIsLinux) 354 355 since := daemonTime(c).Unix() 356 357 dockerCmd(c, "network", "create", "test-event-network-local") 358 out, _ := dockerCmd(c, "events", "--filter", "network=test-event-network-local", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix())) 359 events := strings.Split(strings.TrimSpace(out), "\n") 360 c.Assert(events, checker.HasLen, 1) 361 362 c.Assert(events[0], checker.Contains, "test-event-network-local") 363 c.Assert(events[0], checker.Contains, "type=bridge") 364 }