github.com/akerouanton/docker@v1.11.0-rc3/integration-cli/docker_cli_daemon_test.go (about) 1 // +build daemon,!windows 2 3 package main 4 5 import ( 6 "bytes" 7 "encoding/json" 8 "fmt" 9 "io" 10 "io/ioutil" 11 "net" 12 "os" 13 "os/exec" 14 "path" 15 "path/filepath" 16 "regexp" 17 "strconv" 18 "strings" 19 "sync" 20 "syscall" 21 "time" 22 23 "github.com/docker/docker/pkg/integration/checker" 24 "github.com/docker/go-units" 25 "github.com/docker/libnetwork/iptables" 26 "github.com/docker/libtrust" 27 "github.com/go-check/check" 28 "github.com/kr/pty" 29 ) 30 31 func (s *DockerDaemonSuite) TestDaemonRestartWithRunningContainersPorts(c *check.C) { 32 if err := s.d.StartWithBusybox(); err != nil { 33 c.Fatalf("Could not start daemon with busybox: %v", err) 34 } 35 36 if out, err := s.d.Cmd("run", "-d", "--name", "top1", "-p", "1234:80", "--restart", "always", "busybox:latest", "top"); err != nil { 37 c.Fatalf("Could not run top1: err=%v\n%s", err, out) 38 } 39 // --restart=no by default 40 if out, err := s.d.Cmd("run", "-d", "--name", "top2", "-p", "80", "busybox:latest", "top"); err != nil { 41 c.Fatalf("Could not run top2: err=%v\n%s", err, out) 42 } 43 44 testRun := func(m map[string]bool, prefix string) { 45 var format string 46 for cont, shouldRun := range m { 47 out, err := s.d.Cmd("ps") 48 if err != nil { 49 c.Fatalf("Could not run ps: err=%v\n%q", err, out) 50 } 51 if shouldRun { 52 format = "%scontainer %q is not running" 53 } else { 54 format = "%scontainer %q is running" 55 } 56 if shouldRun != strings.Contains(out, cont) { 57 c.Fatalf(format, prefix, cont) 58 } 59 } 60 } 61 62 testRun(map[string]bool{"top1": true, "top2": true}, "") 63 64 if err := s.d.Restart(); err != nil { 65 c.Fatalf("Could not restart daemon: %v", err) 66 } 67 testRun(map[string]bool{"top1": true, "top2": false}, "After daemon restart: ") 68 } 69 70 func (s *DockerDaemonSuite) TestDaemonRestartWithVolumesRefs(c *check.C) { 71 if err := s.d.StartWithBusybox(); err != nil { 72 c.Fatal(err) 73 } 74 75 if out, err := s.d.Cmd("run", "--name", "volrestarttest1", "-v", "/foo", "busybox"); err != nil { 76 c.Fatal(err, out) 77 } 78 79 if err := s.d.Restart(); err != nil { 80 c.Fatal(err) 81 } 82 83 if _, err := s.d.Cmd("run", "-d", "--volumes-from", "volrestarttest1", "--name", "volrestarttest2", "busybox", "top"); err != nil { 84 c.Fatal(err) 85 } 86 87 if out, err := s.d.Cmd("rm", "-fv", "volrestarttest2"); err != nil { 88 c.Fatal(err, out) 89 } 90 91 out, err := s.d.Cmd("inspect", "-f", "{{json .Mounts}}", "volrestarttest1") 92 c.Assert(err, check.IsNil) 93 94 if _, err := inspectMountPointJSON(out, "/foo"); err != nil { 95 c.Fatalf("Expected volume to exist: /foo, error: %v\n", err) 96 } 97 } 98 99 // #11008 100 func (s *DockerDaemonSuite) TestDaemonRestartUnlessStopped(c *check.C) { 101 err := s.d.StartWithBusybox() 102 c.Assert(err, check.IsNil) 103 104 out, err := s.d.Cmd("run", "-d", "--name", "top1", "--restart", "always", "busybox:latest", "top") 105 c.Assert(err, check.IsNil, check.Commentf("run top1: %v", out)) 106 107 out, err = s.d.Cmd("run", "-d", "--name", "top2", "--restart", "unless-stopped", "busybox:latest", "top") 108 c.Assert(err, check.IsNil, check.Commentf("run top2: %v", out)) 109 110 testRun := func(m map[string]bool, prefix string) { 111 var format string 112 for name, shouldRun := range m { 113 out, err := s.d.Cmd("ps") 114 c.Assert(err, check.IsNil, check.Commentf("run ps: %v", out)) 115 if shouldRun { 116 format = "%scontainer %q is not running" 117 } else { 118 format = "%scontainer %q is running" 119 } 120 c.Assert(strings.Contains(out, name), check.Equals, shouldRun, check.Commentf(format, prefix, name)) 121 } 122 } 123 124 // both running 125 testRun(map[string]bool{"top1": true, "top2": true}, "") 126 127 out, err = s.d.Cmd("stop", "top1") 128 c.Assert(err, check.IsNil, check.Commentf(out)) 129 130 out, err = s.d.Cmd("stop", "top2") 131 c.Assert(err, check.IsNil, check.Commentf(out)) 132 133 // both stopped 134 testRun(map[string]bool{"top1": false, "top2": false}, "") 135 136 err = s.d.Restart() 137 c.Assert(err, check.IsNil) 138 139 // restart=always running 140 testRun(map[string]bool{"top1": true, "top2": false}, "After daemon restart: ") 141 142 out, err = s.d.Cmd("start", "top2") 143 c.Assert(err, check.IsNil, check.Commentf("start top2: %v", out)) 144 145 err = s.d.Restart() 146 c.Assert(err, check.IsNil) 147 148 // both running 149 testRun(map[string]bool{"top1": true, "top2": true}, "After second daemon restart: ") 150 151 } 152 153 func (s *DockerDaemonSuite) TestDaemonStartIptablesFalse(c *check.C) { 154 if err := s.d.Start("--iptables=false"); err != nil { 155 c.Fatalf("we should have been able to start the daemon with passing iptables=false: %v", err) 156 } 157 } 158 159 // Make sure we cannot shrink base device at daemon restart. 160 func (s *DockerDaemonSuite) TestDaemonRestartWithInvalidBasesize(c *check.C) { 161 testRequires(c, Devicemapper) 162 c.Assert(s.d.Start(), check.IsNil) 163 164 oldBasesizeBytes := s.d.getBaseDeviceSize(c) 165 var newBasesizeBytes int64 = 1073741824 //1GB in bytes 166 167 if newBasesizeBytes < oldBasesizeBytes { 168 err := s.d.Restart("--storage-opt", fmt.Sprintf("dm.basesize=%d", newBasesizeBytes)) 169 c.Assert(err, check.IsNil, check.Commentf("daemon should not have started as new base device size is less than existing base device size: %v", err)) 170 } 171 c.Assert(s.d.Stop(), check.IsNil) 172 } 173 174 // Make sure we can grow base device at daemon restart. 175 func (s *DockerDaemonSuite) TestDaemonRestartWithIncreasedBasesize(c *check.C) { 176 testRequires(c, Devicemapper) 177 c.Assert(s.d.Start(), check.IsNil) 178 179 oldBasesizeBytes := s.d.getBaseDeviceSize(c) 180 181 var newBasesizeBytes int64 = 53687091200 //50GB in bytes 182 183 if newBasesizeBytes < oldBasesizeBytes { 184 c.Skip(fmt.Sprintf("New base device size (%v) must be greater than (%s)", units.HumanSize(float64(newBasesizeBytes)), units.HumanSize(float64(oldBasesizeBytes)))) 185 } 186 187 err := s.d.Restart("--storage-opt", fmt.Sprintf("dm.basesize=%d", newBasesizeBytes)) 188 c.Assert(err, check.IsNil, check.Commentf("we should have been able to start the daemon with increased base device size: %v", err)) 189 190 basesizeAfterRestart := s.d.getBaseDeviceSize(c) 191 newBasesize, err := convertBasesize(newBasesizeBytes) 192 c.Assert(err, check.IsNil, check.Commentf("Error in converting base device size: %v", err)) 193 c.Assert(newBasesize, check.Equals, basesizeAfterRestart, check.Commentf("Basesize passed is not equal to Basesize set")) 194 c.Assert(s.d.Stop(), check.IsNil) 195 } 196 197 // Issue #8444: If docker0 bridge is modified (intentionally or unintentionally) and 198 // no longer has an IP associated, we should gracefully handle that case and associate 199 // an IP with it rather than fail daemon start 200 func (s *DockerDaemonSuite) TestDaemonStartBridgeWithoutIPAssociation(c *check.C) { 201 // rather than depending on brctl commands to verify docker0 is created and up 202 // let's start the daemon and stop it, and then make a modification to run the 203 // actual test 204 if err := s.d.Start(); err != nil { 205 c.Fatalf("Could not start daemon: %v", err) 206 } 207 if err := s.d.Stop(); err != nil { 208 c.Fatalf("Could not stop daemon: %v", err) 209 } 210 211 // now we will remove the ip from docker0 and then try starting the daemon 212 ipCmd := exec.Command("ip", "addr", "flush", "dev", "docker0") 213 stdout, stderr, _, err := runCommandWithStdoutStderr(ipCmd) 214 if err != nil { 215 c.Fatalf("failed to remove docker0 IP association: %v, stdout: %q, stderr: %q", err, stdout, stderr) 216 } 217 218 if err := s.d.Start(); err != nil { 219 warning := "**WARNING: Docker bridge network in bad state--delete docker0 bridge interface to fix" 220 c.Fatalf("Could not start daemon when docker0 has no IP address: %v\n%s", err, warning) 221 } 222 } 223 224 func (s *DockerDaemonSuite) TestDaemonIptablesClean(c *check.C) { 225 if err := s.d.StartWithBusybox(); err != nil { 226 c.Fatalf("Could not start daemon with busybox: %v", err) 227 } 228 229 if out, err := s.d.Cmd("run", "-d", "--name", "top", "-p", "80", "busybox:latest", "top"); err != nil { 230 c.Fatalf("Could not run top: %s, %v", out, err) 231 } 232 233 // get output from iptables with container running 234 ipTablesSearchString := "tcp dpt:80" 235 ipTablesCmd := exec.Command("iptables", "-nvL") 236 out, _, err := runCommandWithOutput(ipTablesCmd) 237 if err != nil { 238 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 239 } 240 241 if !strings.Contains(out, ipTablesSearchString) { 242 c.Fatalf("iptables output should have contained %q, but was %q", ipTablesSearchString, out) 243 } 244 245 if err := s.d.Stop(); err != nil { 246 c.Fatalf("Could not stop daemon: %v", err) 247 } 248 249 // get output from iptables after restart 250 ipTablesCmd = exec.Command("iptables", "-nvL") 251 out, _, err = runCommandWithOutput(ipTablesCmd) 252 if err != nil { 253 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 254 } 255 256 if strings.Contains(out, ipTablesSearchString) { 257 c.Fatalf("iptables output should not have contained %q, but was %q", ipTablesSearchString, out) 258 } 259 } 260 261 func (s *DockerDaemonSuite) TestDaemonIptablesCreate(c *check.C) { 262 if err := s.d.StartWithBusybox(); err != nil { 263 c.Fatalf("Could not start daemon with busybox: %v", err) 264 } 265 266 if out, err := s.d.Cmd("run", "-d", "--name", "top", "--restart=always", "-p", "80", "busybox:latest", "top"); err != nil { 267 c.Fatalf("Could not run top: %s, %v", out, err) 268 } 269 270 // get output from iptables with container running 271 ipTablesSearchString := "tcp dpt:80" 272 ipTablesCmd := exec.Command("iptables", "-nvL") 273 out, _, err := runCommandWithOutput(ipTablesCmd) 274 if err != nil { 275 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 276 } 277 278 if !strings.Contains(out, ipTablesSearchString) { 279 c.Fatalf("iptables output should have contained %q, but was %q", ipTablesSearchString, out) 280 } 281 282 if err := s.d.Restart(); err != nil { 283 c.Fatalf("Could not restart daemon: %v", err) 284 } 285 286 // make sure the container is not running 287 runningOut, err := s.d.Cmd("inspect", "--format='{{.State.Running}}'", "top") 288 if err != nil { 289 c.Fatalf("Could not inspect on container: %s, %v", out, err) 290 } 291 if strings.TrimSpace(runningOut) != "true" { 292 c.Fatalf("Container should have been restarted after daemon restart. Status running should have been true but was: %q", strings.TrimSpace(runningOut)) 293 } 294 295 // get output from iptables after restart 296 ipTablesCmd = exec.Command("iptables", "-nvL") 297 out, _, err = runCommandWithOutput(ipTablesCmd) 298 if err != nil { 299 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 300 } 301 302 if !strings.Contains(out, ipTablesSearchString) { 303 c.Fatalf("iptables output after restart should have contained %q, but was %q", ipTablesSearchString, out) 304 } 305 } 306 307 // TestDaemonIPv6Enabled checks that when the daemon is started with --ipv6=true that the docker0 bridge 308 // has the fe80::1 address and that a container is assigned a link-local address 309 func (s *DockerSuite) TestDaemonIPv6Enabled(c *check.C) { 310 testRequires(c, IPv6) 311 312 if err := setupV6(); err != nil { 313 c.Fatal("Could not set up host for IPv6 tests") 314 } 315 316 d := NewDaemon(c) 317 318 if err := d.StartWithBusybox("--ipv6"); err != nil { 319 c.Fatal(err) 320 } 321 defer d.Stop() 322 323 iface, err := net.InterfaceByName("docker0") 324 if err != nil { 325 c.Fatalf("Error getting docker0 interface: %v", err) 326 } 327 328 addrs, err := iface.Addrs() 329 if err != nil { 330 c.Fatalf("Error getting addresses for docker0 interface: %v", err) 331 } 332 333 var found bool 334 expected := "fe80::1/64" 335 336 for i := range addrs { 337 if addrs[i].String() == expected { 338 found = true 339 } 340 } 341 342 if !found { 343 c.Fatalf("Bridge does not have an IPv6 Address") 344 } 345 346 if out, err := d.Cmd("run", "-itd", "--name=ipv6test", "busybox:latest"); err != nil { 347 c.Fatalf("Could not run container: %s, %v", out, err) 348 } 349 350 out, err := d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.LinkLocalIPv6Address}}'", "ipv6test") 351 out = strings.Trim(out, " \r\n'") 352 353 if err != nil { 354 c.Fatalf("Error inspecting container: %s, %v", out, err) 355 } 356 357 if ip := net.ParseIP(out); ip == nil { 358 c.Fatalf("Container should have a link-local IPv6 address") 359 } 360 361 out, err = d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.GlobalIPv6Address}}'", "ipv6test") 362 out = strings.Trim(out, " \r\n'") 363 364 if err != nil { 365 c.Fatalf("Error inspecting container: %s, %v", out, err) 366 } 367 368 if ip := net.ParseIP(out); ip != nil { 369 c.Fatalf("Container should not have a global IPv6 address: %v", out) 370 } 371 372 if err := teardownV6(); err != nil { 373 c.Fatal("Could not perform teardown for IPv6 tests") 374 } 375 376 } 377 378 // TestDaemonIPv6FixedCIDR checks that when the daemon is started with --ipv6=true and a fixed CIDR 379 // that running containers are given a link-local and global IPv6 address 380 func (s *DockerDaemonSuite) TestDaemonIPv6FixedCIDR(c *check.C) { 381 // IPv6 setup is messing with local bridge address. 382 testRequires(c, SameHostDaemon) 383 err := setupV6() 384 c.Assert(err, checker.IsNil, check.Commentf("Could not set up host for IPv6 tests")) 385 386 err = s.d.StartWithBusybox("--ipv6", "--fixed-cidr-v6='2001:db8:2::/64'", "--default-gateway-v6='2001:db8:2::100'") 387 c.Assert(err, checker.IsNil, check.Commentf("Could not start daemon with busybox: %v", err)) 388 389 out, err := s.d.Cmd("run", "-itd", "--name=ipv6test", "busybox:latest") 390 c.Assert(err, checker.IsNil, check.Commentf("Could not run container: %s, %v", out, err)) 391 392 out, err = s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.GlobalIPv6Address}}'", "ipv6test") 393 out = strings.Trim(out, " \r\n'") 394 395 c.Assert(err, checker.IsNil, check.Commentf(out)) 396 397 ip := net.ParseIP(out) 398 c.Assert(ip, checker.NotNil, check.Commentf("Container should have a global IPv6 address")) 399 400 out, err = s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.IPv6Gateway}}'", "ipv6test") 401 c.Assert(err, checker.IsNil, check.Commentf(out)) 402 403 c.Assert(strings.Trim(out, " \r\n'"), checker.Equals, "2001:db8:2::100", check.Commentf("Container should have a global IPv6 gateway")) 404 405 err = teardownV6() 406 c.Assert(err, checker.IsNil, check.Commentf("Could not perform teardown for IPv6 tests")) 407 } 408 409 // TestDaemonIPv6FixedCIDRAndMac checks that when the daemon is started with ipv6 fixed CIDR 410 // the running containers are given a an IPv6 address derived from the MAC address and the ipv6 fixed CIDR 411 func (s *DockerDaemonSuite) TestDaemonIPv6FixedCIDRAndMac(c *check.C) { 412 // IPv6 setup is messing with local bridge address. 413 testRequires(c, SameHostDaemon) 414 err := setupV6() 415 c.Assert(err, checker.IsNil) 416 417 err = s.d.StartWithBusybox("--ipv6", "--fixed-cidr-v6='2001:db8:1::/64'") 418 c.Assert(err, checker.IsNil) 419 420 out, err := s.d.Cmd("run", "-itd", "--name=ipv6test", "--mac-address", "AA:BB:CC:DD:EE:FF", "busybox") 421 c.Assert(err, checker.IsNil) 422 423 out, err = s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.GlobalIPv6Address}}'", "ipv6test") 424 c.Assert(err, checker.IsNil) 425 c.Assert(strings.Trim(out, " \r\n'"), checker.Equals, "2001:db8:1::aabb:ccdd:eeff") 426 427 err = teardownV6() 428 c.Assert(err, checker.IsNil) 429 } 430 431 func (s *DockerDaemonSuite) TestDaemonLogLevelWrong(c *check.C) { 432 c.Assert(s.d.Start("--log-level=bogus"), check.NotNil, check.Commentf("Daemon shouldn't start with wrong log level")) 433 } 434 435 func (s *DockerDaemonSuite) TestDaemonLogLevelDebug(c *check.C) { 436 if err := s.d.Start("--log-level=debug"); err != nil { 437 c.Fatal(err) 438 } 439 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 440 if !strings.Contains(string(content), `level=debug`) { 441 c.Fatalf(`Missing level="debug" in log file:\n%s`, string(content)) 442 } 443 } 444 445 func (s *DockerDaemonSuite) TestDaemonLogLevelFatal(c *check.C) { 446 // we creating new daemons to create new logFile 447 if err := s.d.Start("--log-level=fatal"); err != nil { 448 c.Fatal(err) 449 } 450 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 451 if strings.Contains(string(content), `level=debug`) { 452 c.Fatalf(`Should not have level="debug" in log file:\n%s`, string(content)) 453 } 454 } 455 456 func (s *DockerDaemonSuite) TestDaemonFlagD(c *check.C) { 457 if err := s.d.Start("-D"); err != nil { 458 c.Fatal(err) 459 } 460 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 461 if !strings.Contains(string(content), `level=debug`) { 462 c.Fatalf(`Should have level="debug" in log file using -D:\n%s`, string(content)) 463 } 464 } 465 466 func (s *DockerDaemonSuite) TestDaemonFlagDebug(c *check.C) { 467 if err := s.d.Start("--debug"); err != nil { 468 c.Fatal(err) 469 } 470 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 471 if !strings.Contains(string(content), `level=debug`) { 472 c.Fatalf(`Should have level="debug" in log file using --debug:\n%s`, string(content)) 473 } 474 } 475 476 func (s *DockerDaemonSuite) TestDaemonFlagDebugLogLevelFatal(c *check.C) { 477 if err := s.d.Start("--debug", "--log-level=fatal"); err != nil { 478 c.Fatal(err) 479 } 480 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 481 if !strings.Contains(string(content), `level=debug`) { 482 c.Fatalf(`Should have level="debug" in log file when using both --debug and --log-level=fatal:\n%s`, string(content)) 483 } 484 } 485 486 func (s *DockerDaemonSuite) TestDaemonAllocatesListeningPort(c *check.C) { 487 listeningPorts := [][]string{ 488 {"0.0.0.0", "0.0.0.0", "5678"}, 489 {"127.0.0.1", "127.0.0.1", "1234"}, 490 {"localhost", "127.0.0.1", "1235"}, 491 } 492 493 cmdArgs := make([]string, 0, len(listeningPorts)*2) 494 for _, hostDirective := range listeningPorts { 495 cmdArgs = append(cmdArgs, "--host", fmt.Sprintf("tcp://%s:%s", hostDirective[0], hostDirective[2])) 496 } 497 498 if err := s.d.StartWithBusybox(cmdArgs...); err != nil { 499 c.Fatalf("Could not start daemon with busybox: %v", err) 500 } 501 502 for _, hostDirective := range listeningPorts { 503 output, err := s.d.Cmd("run", "-p", fmt.Sprintf("%s:%s:80", hostDirective[1], hostDirective[2]), "busybox", "true") 504 if err == nil { 505 c.Fatalf("Container should not start, expected port already allocated error: %q", output) 506 } else if !strings.Contains(output, "port is already allocated") { 507 c.Fatalf("Expected port is already allocated error: %q", output) 508 } 509 } 510 } 511 512 func (s *DockerDaemonSuite) TestDaemonKeyGeneration(c *check.C) { 513 // TODO: skip or update for Windows daemon 514 os.Remove("/etc/docker/key.json") 515 if err := s.d.Start(); err != nil { 516 c.Fatalf("Could not start daemon: %v", err) 517 } 518 s.d.Stop() 519 520 k, err := libtrust.LoadKeyFile("/etc/docker/key.json") 521 if err != nil { 522 c.Fatalf("Error opening key file") 523 } 524 kid := k.KeyID() 525 // Test Key ID is a valid fingerprint (e.g. QQXN:JY5W:TBXI:MK3X:GX6P:PD5D:F56N:NHCS:LVRZ:JA46:R24J:XEFF) 526 if len(kid) != 59 { 527 c.Fatalf("Bad key ID: %s", kid) 528 } 529 } 530 531 func (s *DockerDaemonSuite) TestDaemonKeyMigration(c *check.C) { 532 // TODO: skip or update for Windows daemon 533 os.Remove("/etc/docker/key.json") 534 k1, err := libtrust.GenerateECP256PrivateKey() 535 if err != nil { 536 c.Fatalf("Error generating private key: %s", err) 537 } 538 if err := os.MkdirAll(filepath.Join(os.Getenv("HOME"), ".docker"), 0755); err != nil { 539 c.Fatalf("Error creating .docker directory: %s", err) 540 } 541 if err := libtrust.SaveKey(filepath.Join(os.Getenv("HOME"), ".docker", "key.json"), k1); err != nil { 542 c.Fatalf("Error saving private key: %s", err) 543 } 544 545 if err := s.d.Start(); err != nil { 546 c.Fatalf("Could not start daemon: %v", err) 547 } 548 s.d.Stop() 549 550 k2, err := libtrust.LoadKeyFile("/etc/docker/key.json") 551 if err != nil { 552 c.Fatalf("Error opening key file") 553 } 554 if k1.KeyID() != k2.KeyID() { 555 c.Fatalf("Key not migrated") 556 } 557 } 558 559 // GH#11320 - verify that the daemon exits on failure properly 560 // Note that this explicitly tests the conflict of {-b,--bridge} and {--bip} options as the means 561 // to get a daemon init failure; no other tests for -b/--bip conflict are therefore required 562 func (s *DockerDaemonSuite) TestDaemonExitOnFailure(c *check.C) { 563 //attempt to start daemon with incorrect flags (we know -b and --bip conflict) 564 if err := s.d.Start("--bridge", "nosuchbridge", "--bip", "1.1.1.1"); err != nil { 565 //verify we got the right error 566 if !strings.Contains(err.Error(), "Daemon exited and never started") { 567 c.Fatalf("Expected daemon not to start, got %v", err) 568 } 569 // look in the log and make sure we got the message that daemon is shutting down 570 runCmd := exec.Command("grep", "Error starting daemon", s.d.LogFileName()) 571 if out, _, err := runCommandWithOutput(runCmd); err != nil { 572 c.Fatalf("Expected 'Error starting daemon' message; but doesn't exist in log: %q, err: %v", out, err) 573 } 574 } else { 575 //if we didn't get an error and the daemon is running, this is a failure 576 c.Fatal("Conflicting options should cause the daemon to error out with a failure") 577 } 578 } 579 580 func (s *DockerDaemonSuite) TestDaemonBridgeExternal(c *check.C) { 581 d := s.d 582 err := d.Start("--bridge", "nosuchbridge") 583 c.Assert(err, check.NotNil, check.Commentf("--bridge option with an invalid bridge should cause the daemon to fail")) 584 defer d.Restart() 585 586 bridgeName := "external-bridge" 587 bridgeIP := "192.169.1.1/24" 588 _, bridgeIPNet, _ := net.ParseCIDR(bridgeIP) 589 590 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 591 c.Assert(err, check.IsNil, check.Commentf(out)) 592 defer deleteInterface(c, bridgeName) 593 594 err = d.StartWithBusybox("--bridge", bridgeName) 595 c.Assert(err, check.IsNil) 596 597 ipTablesSearchString := bridgeIPNet.String() 598 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 599 out, _, err = runCommandWithOutput(ipTablesCmd) 600 c.Assert(err, check.IsNil) 601 602 c.Assert(strings.Contains(out, ipTablesSearchString), check.Equals, true, 603 check.Commentf("iptables output should have contained %q, but was %q", 604 ipTablesSearchString, out)) 605 606 _, err = d.Cmd("run", "-d", "--name", "ExtContainer", "busybox", "top") 607 c.Assert(err, check.IsNil) 608 609 containerIP := d.findContainerIP("ExtContainer") 610 ip := net.ParseIP(containerIP) 611 c.Assert(bridgeIPNet.Contains(ip), check.Equals, true, 612 check.Commentf("Container IP-Address must be in the same subnet range : %s", 613 containerIP)) 614 } 615 616 func createInterface(c *check.C, ifType string, ifName string, ipNet string) (string, error) { 617 args := []string{"link", "add", "name", ifName, "type", ifType} 618 ipLinkCmd := exec.Command("ip", args...) 619 out, _, err := runCommandWithOutput(ipLinkCmd) 620 if err != nil { 621 return out, err 622 } 623 624 ifCfgCmd := exec.Command("ifconfig", ifName, ipNet, "up") 625 out, _, err = runCommandWithOutput(ifCfgCmd) 626 return out, err 627 } 628 629 func deleteInterface(c *check.C, ifName string) { 630 ifCmd := exec.Command("ip", "link", "delete", ifName) 631 out, _, err := runCommandWithOutput(ifCmd) 632 c.Assert(err, check.IsNil, check.Commentf(out)) 633 634 flushCmd := exec.Command("iptables", "-t", "nat", "--flush") 635 out, _, err = runCommandWithOutput(flushCmd) 636 c.Assert(err, check.IsNil, check.Commentf(out)) 637 638 flushCmd = exec.Command("iptables", "--flush") 639 out, _, err = runCommandWithOutput(flushCmd) 640 c.Assert(err, check.IsNil, check.Commentf(out)) 641 } 642 643 func (s *DockerDaemonSuite) TestDaemonBridgeIP(c *check.C) { 644 // TestDaemonBridgeIP Steps 645 // 1. Delete the existing docker0 Bridge 646 // 2. Set --bip daemon configuration and start the new Docker Daemon 647 // 3. Check if the bip config has taken effect using ifconfig and iptables commands 648 // 4. Launch a Container and make sure the IP-Address is in the expected subnet 649 // 5. Delete the docker0 Bridge 650 // 6. Restart the Docker Daemon (via deferred action) 651 // This Restart takes care of bringing docker0 interface back to auto-assigned IP 652 653 defaultNetworkBridge := "docker0" 654 deleteInterface(c, defaultNetworkBridge) 655 656 d := s.d 657 658 bridgeIP := "192.169.1.1/24" 659 ip, bridgeIPNet, _ := net.ParseCIDR(bridgeIP) 660 661 err := d.StartWithBusybox("--bip", bridgeIP) 662 c.Assert(err, check.IsNil) 663 defer d.Restart() 664 665 ifconfigSearchString := ip.String() 666 ifconfigCmd := exec.Command("ifconfig", defaultNetworkBridge) 667 out, _, _, err := runCommandWithStdoutStderr(ifconfigCmd) 668 c.Assert(err, check.IsNil) 669 670 c.Assert(strings.Contains(out, ifconfigSearchString), check.Equals, true, 671 check.Commentf("ifconfig output should have contained %q, but was %q", 672 ifconfigSearchString, out)) 673 674 ipTablesSearchString := bridgeIPNet.String() 675 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 676 out, _, err = runCommandWithOutput(ipTablesCmd) 677 c.Assert(err, check.IsNil) 678 679 c.Assert(strings.Contains(out, ipTablesSearchString), check.Equals, true, 680 check.Commentf("iptables output should have contained %q, but was %q", 681 ipTablesSearchString, out)) 682 683 out, err = d.Cmd("run", "-d", "--name", "test", "busybox", "top") 684 c.Assert(err, check.IsNil) 685 686 containerIP := d.findContainerIP("test") 687 ip = net.ParseIP(containerIP) 688 c.Assert(bridgeIPNet.Contains(ip), check.Equals, true, 689 check.Commentf("Container IP-Address must be in the same subnet range : %s", 690 containerIP)) 691 deleteInterface(c, defaultNetworkBridge) 692 } 693 694 func (s *DockerDaemonSuite) TestDaemonRestartWithBridgeIPChange(c *check.C) { 695 if err := s.d.Start(); err != nil { 696 c.Fatalf("Could not start daemon: %v", err) 697 } 698 defer s.d.Restart() 699 if err := s.d.Stop(); err != nil { 700 c.Fatalf("Could not stop daemon: %v", err) 701 } 702 703 // now we will change the docker0's IP and then try starting the daemon 704 bridgeIP := "192.169.100.1/24" 705 _, bridgeIPNet, _ := net.ParseCIDR(bridgeIP) 706 707 ipCmd := exec.Command("ifconfig", "docker0", bridgeIP) 708 stdout, stderr, _, err := runCommandWithStdoutStderr(ipCmd) 709 if err != nil { 710 c.Fatalf("failed to change docker0's IP association: %v, stdout: %q, stderr: %q", err, stdout, stderr) 711 } 712 713 if err := s.d.Start("--bip", bridgeIP); err != nil { 714 c.Fatalf("Could not start daemon: %v", err) 715 } 716 717 //check if the iptables contains new bridgeIP MASQUERADE rule 718 ipTablesSearchString := bridgeIPNet.String() 719 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 720 out, _, err := runCommandWithOutput(ipTablesCmd) 721 if err != nil { 722 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 723 } 724 if !strings.Contains(out, ipTablesSearchString) { 725 c.Fatalf("iptables output should have contained new MASQUERADE rule with IP %q, but was %q", ipTablesSearchString, out) 726 } 727 } 728 729 func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr(c *check.C) { 730 d := s.d 731 732 bridgeName := "external-bridge" 733 bridgeIP := "192.169.1.1/24" 734 735 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 736 c.Assert(err, check.IsNil, check.Commentf(out)) 737 defer deleteInterface(c, bridgeName) 738 739 args := []string{"--bridge", bridgeName, "--fixed-cidr", "192.169.1.0/30"} 740 err = d.StartWithBusybox(args...) 741 c.Assert(err, check.IsNil) 742 defer d.Restart() 743 744 for i := 0; i < 4; i++ { 745 cName := "Container" + strconv.Itoa(i) 746 out, err := d.Cmd("run", "-d", "--name", cName, "busybox", "top") 747 if err != nil { 748 c.Assert(strings.Contains(out, "no available IPv4 addresses"), check.Equals, true, 749 check.Commentf("Could not run a Container : %s %s", err.Error(), out)) 750 } 751 } 752 } 753 754 func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr2(c *check.C) { 755 d := s.d 756 757 bridgeName := "external-bridge" 758 bridgeIP := "10.2.2.1/16" 759 760 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 761 c.Assert(err, check.IsNil, check.Commentf(out)) 762 defer deleteInterface(c, bridgeName) 763 764 err = d.StartWithBusybox("--bip", bridgeIP, "--fixed-cidr", "10.2.2.0/24") 765 c.Assert(err, check.IsNil) 766 defer s.d.Restart() 767 768 out, err = d.Cmd("run", "-d", "--name", "bb", "busybox", "top") 769 c.Assert(err, checker.IsNil, check.Commentf(out)) 770 defer d.Cmd("stop", "bb") 771 772 out, err = d.Cmd("exec", "bb", "/bin/sh", "-c", "ifconfig eth0 | awk '/inet addr/{print substr($2,6)}'") 773 c.Assert(out, checker.Equals, "10.2.2.0\n") 774 775 out, err = d.Cmd("run", "--rm", "busybox", "/bin/sh", "-c", "ifconfig eth0 | awk '/inet addr/{print substr($2,6)}'") 776 c.Assert(err, checker.IsNil, check.Commentf(out)) 777 c.Assert(out, checker.Equals, "10.2.2.2\n") 778 } 779 780 func (s *DockerDaemonSuite) TestDaemonBridgeFixedCIDREqualBridgeNetwork(c *check.C) { 781 d := s.d 782 783 bridgeName := "external-bridge" 784 bridgeIP := "172.27.42.1/16" 785 786 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 787 c.Assert(err, check.IsNil, check.Commentf(out)) 788 defer deleteInterface(c, bridgeName) 789 790 err = d.StartWithBusybox("--bridge", bridgeName, "--fixed-cidr", bridgeIP) 791 c.Assert(err, check.IsNil) 792 defer s.d.Restart() 793 794 out, err = d.Cmd("run", "-d", "busybox", "top") 795 c.Assert(err, check.IsNil, check.Commentf(out)) 796 cid1 := strings.TrimSpace(out) 797 defer d.Cmd("stop", cid1) 798 } 799 800 func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4Implicit(c *check.C) { 801 defaultNetworkBridge := "docker0" 802 deleteInterface(c, defaultNetworkBridge) 803 804 d := s.d 805 806 bridgeIP := "192.169.1.1" 807 bridgeIPNet := fmt.Sprintf("%s/24", bridgeIP) 808 809 err := d.StartWithBusybox("--bip", bridgeIPNet) 810 c.Assert(err, check.IsNil) 811 defer d.Restart() 812 813 expectedMessage := fmt.Sprintf("default via %s dev", bridgeIP) 814 out, err := d.Cmd("run", "busybox", "ip", "-4", "route", "list", "0/0") 815 c.Assert(strings.Contains(out, expectedMessage), check.Equals, true, 816 check.Commentf("Implicit default gateway should be bridge IP %s, but default route was '%s'", 817 bridgeIP, strings.TrimSpace(out))) 818 deleteInterface(c, defaultNetworkBridge) 819 } 820 821 func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4Explicit(c *check.C) { 822 defaultNetworkBridge := "docker0" 823 deleteInterface(c, defaultNetworkBridge) 824 825 d := s.d 826 827 bridgeIP := "192.169.1.1" 828 bridgeIPNet := fmt.Sprintf("%s/24", bridgeIP) 829 gatewayIP := "192.169.1.254" 830 831 err := d.StartWithBusybox("--bip", bridgeIPNet, "--default-gateway", gatewayIP) 832 c.Assert(err, check.IsNil) 833 defer d.Restart() 834 835 expectedMessage := fmt.Sprintf("default via %s dev", gatewayIP) 836 out, err := d.Cmd("run", "busybox", "ip", "-4", "route", "list", "0/0") 837 c.Assert(strings.Contains(out, expectedMessage), check.Equals, true, 838 check.Commentf("Explicit default gateway should be %s, but default route was '%s'", 839 gatewayIP, strings.TrimSpace(out))) 840 deleteInterface(c, defaultNetworkBridge) 841 } 842 843 func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4ExplicitOutsideContainerSubnet(c *check.C) { 844 defaultNetworkBridge := "docker0" 845 deleteInterface(c, defaultNetworkBridge) 846 847 // Program a custom default gateway outside of the container subnet, daemon should accept it and start 848 err := s.d.StartWithBusybox("--bip", "172.16.0.10/16", "--fixed-cidr", "172.16.1.0/24", "--default-gateway", "172.16.0.254") 849 c.Assert(err, check.IsNil) 850 851 deleteInterface(c, defaultNetworkBridge) 852 s.d.Restart() 853 } 854 855 func (s *DockerDaemonSuite) TestDaemonDefaultNetworkInvalidClusterConfig(c *check.C) { 856 testRequires(c, DaemonIsLinux, SameHostDaemon) 857 858 // Start daemon without docker0 bridge 859 defaultNetworkBridge := "docker0" 860 deleteInterface(c, defaultNetworkBridge) 861 862 d := NewDaemon(c) 863 discoveryBackend := "consul://consuladdr:consulport/some/path" 864 err := d.Start(fmt.Sprintf("--cluster-store=%s", discoveryBackend)) 865 c.Assert(err, checker.IsNil) 866 867 // Start daemon with docker0 bridge 868 ifconfigCmd := exec.Command("ifconfig", defaultNetworkBridge) 869 _, err = runCommand(ifconfigCmd) 870 c.Assert(err, check.IsNil) 871 872 err = d.Restart(fmt.Sprintf("--cluster-store=%s", discoveryBackend)) 873 c.Assert(err, checker.IsNil) 874 875 d.Stop() 876 } 877 878 func (s *DockerDaemonSuite) TestDaemonIP(c *check.C) { 879 d := s.d 880 881 ipStr := "192.170.1.1/24" 882 ip, _, _ := net.ParseCIDR(ipStr) 883 args := []string{"--ip", ip.String()} 884 err := d.StartWithBusybox(args...) 885 c.Assert(err, check.IsNil) 886 defer d.Restart() 887 888 out, err := d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top") 889 c.Assert(err, check.NotNil, 890 check.Commentf("Running a container must fail with an invalid --ip option")) 891 c.Assert(strings.Contains(out, "Error starting userland proxy"), check.Equals, true) 892 893 ifName := "dummy" 894 out, err = createInterface(c, "dummy", ifName, ipStr) 895 c.Assert(err, check.IsNil, check.Commentf(out)) 896 defer deleteInterface(c, ifName) 897 898 _, err = d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top") 899 c.Assert(err, check.IsNil) 900 901 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 902 out, _, err = runCommandWithOutput(ipTablesCmd) 903 c.Assert(err, check.IsNil) 904 905 regex := fmt.Sprintf("DNAT.*%s.*dpt:8000", ip.String()) 906 matched, _ := regexp.MatchString(regex, out) 907 c.Assert(matched, check.Equals, true, 908 check.Commentf("iptables output should have contained %q, but was %q", regex, out)) 909 } 910 911 func (s *DockerDaemonSuite) TestDaemonICCPing(c *check.C) { 912 testRequires(c, bridgeNfIptables) 913 d := s.d 914 915 bridgeName := "external-bridge" 916 bridgeIP := "192.169.1.1/24" 917 918 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 919 c.Assert(err, check.IsNil, check.Commentf(out)) 920 defer deleteInterface(c, bridgeName) 921 922 args := []string{"--bridge", bridgeName, "--icc=false"} 923 err = d.StartWithBusybox(args...) 924 c.Assert(err, check.IsNil) 925 defer d.Restart() 926 927 ipTablesCmd := exec.Command("iptables", "-nvL", "FORWARD") 928 out, _, err = runCommandWithOutput(ipTablesCmd) 929 c.Assert(err, check.IsNil) 930 931 regex := fmt.Sprintf("DROP.*all.*%s.*%s", bridgeName, bridgeName) 932 matched, _ := regexp.MatchString(regex, out) 933 c.Assert(matched, check.Equals, true, 934 check.Commentf("iptables output should have contained %q, but was %q", regex, out)) 935 936 // Pinging another container must fail with --icc=false 937 pingContainers(c, d, true) 938 939 ipStr := "192.171.1.1/24" 940 ip, _, _ := net.ParseCIDR(ipStr) 941 ifName := "icc-dummy" 942 943 createInterface(c, "dummy", ifName, ipStr) 944 945 // But, Pinging external or a Host interface must succeed 946 pingCmd := fmt.Sprintf("ping -c 1 %s -W 1", ip.String()) 947 runArgs := []string{"--rm", "busybox", "sh", "-c", pingCmd} 948 _, err = d.Cmd("run", runArgs...) 949 c.Assert(err, check.IsNil) 950 } 951 952 func (s *DockerDaemonSuite) TestDaemonICCLinkExpose(c *check.C) { 953 d := s.d 954 955 bridgeName := "external-bridge" 956 bridgeIP := "192.169.1.1/24" 957 958 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 959 c.Assert(err, check.IsNil, check.Commentf(out)) 960 defer deleteInterface(c, bridgeName) 961 962 args := []string{"--bridge", bridgeName, "--icc=false"} 963 err = d.StartWithBusybox(args...) 964 c.Assert(err, check.IsNil) 965 defer d.Restart() 966 967 ipTablesCmd := exec.Command("iptables", "-nvL", "FORWARD") 968 out, _, err = runCommandWithOutput(ipTablesCmd) 969 c.Assert(err, check.IsNil) 970 971 regex := fmt.Sprintf("DROP.*all.*%s.*%s", bridgeName, bridgeName) 972 matched, _ := regexp.MatchString(regex, out) 973 c.Assert(matched, check.Equals, true, 974 check.Commentf("iptables output should have contained %q, but was %q", regex, out)) 975 976 out, err = d.Cmd("run", "-d", "--expose", "4567", "--name", "icc1", "busybox", "nc", "-l", "-p", "4567") 977 c.Assert(err, check.IsNil, check.Commentf(out)) 978 979 out, err = d.Cmd("run", "--link", "icc1:icc1", "busybox", "nc", "icc1", "4567") 980 c.Assert(err, check.IsNil, check.Commentf(out)) 981 } 982 983 func (s *DockerDaemonSuite) TestDaemonLinksIpTablesRulesWhenLinkAndUnlink(c *check.C) { 984 bridgeName := "external-bridge" 985 bridgeIP := "192.169.1.1/24" 986 987 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 988 c.Assert(err, check.IsNil, check.Commentf(out)) 989 defer deleteInterface(c, bridgeName) 990 991 err = s.d.StartWithBusybox("--bridge", bridgeName, "--icc=false") 992 c.Assert(err, check.IsNil) 993 defer s.d.Restart() 994 995 _, err = s.d.Cmd("run", "-d", "--name", "child", "--publish", "8080:80", "busybox", "top") 996 c.Assert(err, check.IsNil) 997 _, err = s.d.Cmd("run", "-d", "--name", "parent", "--link", "child:http", "busybox", "top") 998 c.Assert(err, check.IsNil) 999 1000 childIP := s.d.findContainerIP("child") 1001 parentIP := s.d.findContainerIP("parent") 1002 1003 sourceRule := []string{"-i", bridgeName, "-o", bridgeName, "-p", "tcp", "-s", childIP, "--sport", "80", "-d", parentIP, "-j", "ACCEPT"} 1004 destinationRule := []string{"-i", bridgeName, "-o", bridgeName, "-p", "tcp", "-s", parentIP, "--dport", "80", "-d", childIP, "-j", "ACCEPT"} 1005 if !iptables.Exists("filter", "DOCKER", sourceRule...) || !iptables.Exists("filter", "DOCKER", destinationRule...) { 1006 c.Fatal("Iptables rules not found") 1007 } 1008 1009 s.d.Cmd("rm", "--link", "parent/http") 1010 if iptables.Exists("filter", "DOCKER", sourceRule...) || iptables.Exists("filter", "DOCKER", destinationRule...) { 1011 c.Fatal("Iptables rules should be removed when unlink") 1012 } 1013 1014 s.d.Cmd("kill", "child") 1015 s.d.Cmd("kill", "parent") 1016 } 1017 1018 func (s *DockerDaemonSuite) TestDaemonUlimitDefaults(c *check.C) { 1019 testRequires(c, DaemonIsLinux) 1020 1021 if err := s.d.StartWithBusybox("--default-ulimit", "nofile=42:42", "--default-ulimit", "nproc=1024:1024"); err != nil { 1022 c.Fatal(err) 1023 } 1024 1025 out, err := s.d.Cmd("run", "--ulimit", "nproc=2048", "--name=test", "busybox", "/bin/sh", "-c", "echo $(ulimit -n); echo $(ulimit -p)") 1026 if err != nil { 1027 c.Fatal(out, err) 1028 } 1029 1030 outArr := strings.Split(out, "\n") 1031 if len(outArr) < 2 { 1032 c.Fatalf("got unexpected output: %s", out) 1033 } 1034 nofile := strings.TrimSpace(outArr[0]) 1035 nproc := strings.TrimSpace(outArr[1]) 1036 1037 if nofile != "42" { 1038 c.Fatalf("expected `ulimit -n` to be `42`, got: %s", nofile) 1039 } 1040 if nproc != "2048" { 1041 c.Fatalf("exepcted `ulimit -p` to be 2048, got: %s", nproc) 1042 } 1043 1044 // Now restart daemon with a new default 1045 if err := s.d.Restart("--default-ulimit", "nofile=43"); err != nil { 1046 c.Fatal(err) 1047 } 1048 1049 out, err = s.d.Cmd("start", "-a", "test") 1050 if err != nil { 1051 c.Fatal(err) 1052 } 1053 1054 outArr = strings.Split(out, "\n") 1055 if len(outArr) < 2 { 1056 c.Fatalf("got unexpected output: %s", out) 1057 } 1058 nofile = strings.TrimSpace(outArr[0]) 1059 nproc = strings.TrimSpace(outArr[1]) 1060 1061 if nofile != "43" { 1062 c.Fatalf("expected `ulimit -n` to be `43`, got: %s", nofile) 1063 } 1064 if nproc != "2048" { 1065 c.Fatalf("exepcted `ulimit -p` to be 2048, got: %s", nproc) 1066 } 1067 } 1068 1069 // #11315 1070 func (s *DockerDaemonSuite) TestDaemonRestartRenameContainer(c *check.C) { 1071 if err := s.d.StartWithBusybox(); err != nil { 1072 c.Fatal(err) 1073 } 1074 1075 if out, err := s.d.Cmd("run", "--name=test", "busybox"); err != nil { 1076 c.Fatal(err, out) 1077 } 1078 1079 if out, err := s.d.Cmd("rename", "test", "test2"); err != nil { 1080 c.Fatal(err, out) 1081 } 1082 1083 if err := s.d.Restart(); err != nil { 1084 c.Fatal(err) 1085 } 1086 1087 if out, err := s.d.Cmd("start", "test2"); err != nil { 1088 c.Fatal(err, out) 1089 } 1090 } 1091 1092 func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefault(c *check.C) { 1093 if err := s.d.StartWithBusybox(); err != nil { 1094 c.Fatal(err) 1095 } 1096 1097 out, err := s.d.Cmd("run", "--name=test", "busybox", "echo", "testline") 1098 c.Assert(err, check.IsNil, check.Commentf(out)) 1099 id, err := s.d.getIDByName("test") 1100 c.Assert(err, check.IsNil) 1101 1102 logPath := filepath.Join(s.d.root, "containers", id, id+"-json.log") 1103 1104 if _, err := os.Stat(logPath); err != nil { 1105 c.Fatal(err) 1106 } 1107 f, err := os.Open(logPath) 1108 if err != nil { 1109 c.Fatal(err) 1110 } 1111 var res struct { 1112 Log string `json:"log"` 1113 Stream string `json:"stream"` 1114 Time time.Time `json:"time"` 1115 } 1116 if err := json.NewDecoder(f).Decode(&res); err != nil { 1117 c.Fatal(err) 1118 } 1119 if res.Log != "testline\n" { 1120 c.Fatalf("Unexpected log line: %q, expected: %q", res.Log, "testline\n") 1121 } 1122 if res.Stream != "stdout" { 1123 c.Fatalf("Unexpected stream: %q, expected: %q", res.Stream, "stdout") 1124 } 1125 if !time.Now().After(res.Time) { 1126 c.Fatalf("Log time %v in future", res.Time) 1127 } 1128 } 1129 1130 func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefaultOverride(c *check.C) { 1131 if err := s.d.StartWithBusybox(); err != nil { 1132 c.Fatal(err) 1133 } 1134 1135 out, err := s.d.Cmd("run", "--name=test", "--log-driver=none", "busybox", "echo", "testline") 1136 if err != nil { 1137 c.Fatal(out, err) 1138 } 1139 id, err := s.d.getIDByName("test") 1140 c.Assert(err, check.IsNil) 1141 1142 logPath := filepath.Join(s.d.root, "containers", id, id+"-json.log") 1143 1144 if _, err := os.Stat(logPath); err == nil || !os.IsNotExist(err) { 1145 c.Fatalf("%s shouldn't exits, error on Stat: %s", logPath, err) 1146 } 1147 } 1148 1149 func (s *DockerDaemonSuite) TestDaemonLoggingDriverNone(c *check.C) { 1150 if err := s.d.StartWithBusybox("--log-driver=none"); err != nil { 1151 c.Fatal(err) 1152 } 1153 1154 out, err := s.d.Cmd("run", "--name=test", "busybox", "echo", "testline") 1155 if err != nil { 1156 c.Fatal(out, err) 1157 } 1158 id, err := s.d.getIDByName("test") 1159 c.Assert(err, check.IsNil) 1160 1161 logPath := filepath.Join(s.d.folder, "graph", "containers", id, id+"-json.log") 1162 1163 if _, err := os.Stat(logPath); err == nil || !os.IsNotExist(err) { 1164 c.Fatalf("%s shouldn't exits, error on Stat: %s", logPath, err) 1165 } 1166 } 1167 1168 func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneOverride(c *check.C) { 1169 if err := s.d.StartWithBusybox("--log-driver=none"); err != nil { 1170 c.Fatal(err) 1171 } 1172 1173 out, err := s.d.Cmd("run", "--name=test", "--log-driver=json-file", "busybox", "echo", "testline") 1174 if err != nil { 1175 c.Fatal(out, err) 1176 } 1177 id, err := s.d.getIDByName("test") 1178 c.Assert(err, check.IsNil) 1179 1180 logPath := filepath.Join(s.d.root, "containers", id, id+"-json.log") 1181 1182 if _, err := os.Stat(logPath); err != nil { 1183 c.Fatal(err) 1184 } 1185 f, err := os.Open(logPath) 1186 if err != nil { 1187 c.Fatal(err) 1188 } 1189 var res struct { 1190 Log string `json:"log"` 1191 Stream string `json:"stream"` 1192 Time time.Time `json:"time"` 1193 } 1194 if err := json.NewDecoder(f).Decode(&res); err != nil { 1195 c.Fatal(err) 1196 } 1197 if res.Log != "testline\n" { 1198 c.Fatalf("Unexpected log line: %q, expected: %q", res.Log, "testline\n") 1199 } 1200 if res.Stream != "stdout" { 1201 c.Fatalf("Unexpected stream: %q, expected: %q", res.Stream, "stdout") 1202 } 1203 if !time.Now().After(res.Time) { 1204 c.Fatalf("Log time %v in future", res.Time) 1205 } 1206 } 1207 1208 func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneLogsError(c *check.C) { 1209 c.Assert(s.d.StartWithBusybox("--log-driver=none"), checker.IsNil) 1210 1211 out, err := s.d.Cmd("run", "--name=test", "busybox", "echo", "testline") 1212 c.Assert(err, checker.IsNil, check.Commentf(out)) 1213 1214 out, err = s.d.Cmd("logs", "test") 1215 c.Assert(err, check.NotNil, check.Commentf("Logs should fail with 'none' driver")) 1216 expected := `"logs" command is supported only for "json-file" and "journald" logging drivers (got: none)` 1217 c.Assert(out, checker.Contains, expected) 1218 } 1219 1220 func (s *DockerDaemonSuite) TestDaemonDots(c *check.C) { 1221 if err := s.d.StartWithBusybox(); err != nil { 1222 c.Fatal(err) 1223 } 1224 1225 // Now create 4 containers 1226 if _, err := s.d.Cmd("create", "busybox"); err != nil { 1227 c.Fatalf("Error creating container: %q", err) 1228 } 1229 if _, err := s.d.Cmd("create", "busybox"); err != nil { 1230 c.Fatalf("Error creating container: %q", err) 1231 } 1232 if _, err := s.d.Cmd("create", "busybox"); err != nil { 1233 c.Fatalf("Error creating container: %q", err) 1234 } 1235 if _, err := s.d.Cmd("create", "busybox"); err != nil { 1236 c.Fatalf("Error creating container: %q", err) 1237 } 1238 1239 s.d.Stop() 1240 1241 s.d.Start("--log-level=debug") 1242 s.d.Stop() 1243 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 1244 if strings.Contains(string(content), "....") { 1245 c.Fatalf("Debug level should not have ....\n%s", string(content)) 1246 } 1247 1248 s.d.Start("--log-level=error") 1249 s.d.Stop() 1250 content, _ = ioutil.ReadFile(s.d.logFile.Name()) 1251 if strings.Contains(string(content), "....") { 1252 c.Fatalf("Error level should not have ....\n%s", string(content)) 1253 } 1254 1255 s.d.Start("--log-level=info") 1256 s.d.Stop() 1257 content, _ = ioutil.ReadFile(s.d.logFile.Name()) 1258 if !strings.Contains(string(content), "....") { 1259 c.Fatalf("Info level should have ....\n%s", string(content)) 1260 } 1261 } 1262 1263 func (s *DockerDaemonSuite) TestDaemonUnixSockCleanedUp(c *check.C) { 1264 dir, err := ioutil.TempDir("", "socket-cleanup-test") 1265 if err != nil { 1266 c.Fatal(err) 1267 } 1268 defer os.RemoveAll(dir) 1269 1270 sockPath := filepath.Join(dir, "docker.sock") 1271 if err := s.d.Start("--host", "unix://"+sockPath); err != nil { 1272 c.Fatal(err) 1273 } 1274 1275 if _, err := os.Stat(sockPath); err != nil { 1276 c.Fatal("socket does not exist") 1277 } 1278 1279 if err := s.d.Stop(); err != nil { 1280 c.Fatal(err) 1281 } 1282 1283 if _, err := os.Stat(sockPath); err == nil || !os.IsNotExist(err) { 1284 c.Fatal("unix socket is not cleaned up") 1285 } 1286 } 1287 1288 func (s *DockerDaemonSuite) TestDaemonWithWrongkey(c *check.C) { 1289 type Config struct { 1290 Crv string `json:"crv"` 1291 D string `json:"d"` 1292 Kid string `json:"kid"` 1293 Kty string `json:"kty"` 1294 X string `json:"x"` 1295 Y string `json:"y"` 1296 } 1297 1298 os.Remove("/etc/docker/key.json") 1299 if err := s.d.Start(); err != nil { 1300 c.Fatalf("Failed to start daemon: %v", err) 1301 } 1302 1303 if err := s.d.Stop(); err != nil { 1304 c.Fatalf("Could not stop daemon: %v", err) 1305 } 1306 1307 config := &Config{} 1308 bytes, err := ioutil.ReadFile("/etc/docker/key.json") 1309 if err != nil { 1310 c.Fatalf("Error reading key.json file: %s", err) 1311 } 1312 1313 // byte[] to Data-Struct 1314 if err := json.Unmarshal(bytes, &config); err != nil { 1315 c.Fatalf("Error Unmarshal: %s", err) 1316 } 1317 1318 //replace config.Kid with the fake value 1319 config.Kid = "VSAJ:FUYR:X3H2:B2VZ:KZ6U:CJD5:K7BX:ZXHY:UZXT:P4FT:MJWG:HRJ4" 1320 1321 // NEW Data-Struct to byte[] 1322 newBytes, err := json.Marshal(&config) 1323 if err != nil { 1324 c.Fatalf("Error Marshal: %s", err) 1325 } 1326 1327 // write back 1328 if err := ioutil.WriteFile("/etc/docker/key.json", newBytes, 0400); err != nil { 1329 c.Fatalf("Error ioutil.WriteFile: %s", err) 1330 } 1331 1332 defer os.Remove("/etc/docker/key.json") 1333 1334 if err := s.d.Start(); err == nil { 1335 c.Fatalf("It should not be successful to start daemon with wrong key: %v", err) 1336 } 1337 1338 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 1339 1340 if !strings.Contains(string(content), "Public Key ID does not match") { 1341 c.Fatal("Missing KeyID message from daemon logs") 1342 } 1343 } 1344 1345 func (s *DockerDaemonSuite) TestDaemonRestartKillWait(c *check.C) { 1346 if err := s.d.StartWithBusybox(); err != nil { 1347 c.Fatalf("Could not start daemon with busybox: %v", err) 1348 } 1349 1350 out, err := s.d.Cmd("run", "-id", "busybox", "/bin/cat") 1351 if err != nil { 1352 c.Fatalf("Could not run /bin/cat: err=%v\n%s", err, out) 1353 } 1354 containerID := strings.TrimSpace(out) 1355 1356 if out, err := s.d.Cmd("kill", containerID); err != nil { 1357 c.Fatalf("Could not kill %s: err=%v\n%s", containerID, err, out) 1358 } 1359 1360 if err := s.d.Restart(); err != nil { 1361 c.Fatalf("Could not restart daemon: %v", err) 1362 } 1363 1364 errchan := make(chan error) 1365 go func() { 1366 if out, err := s.d.Cmd("wait", containerID); err != nil { 1367 errchan <- fmt.Errorf("%v:\n%s", err, out) 1368 } 1369 close(errchan) 1370 }() 1371 1372 select { 1373 case <-time.After(5 * time.Second): 1374 c.Fatal("Waiting on a stopped (killed) container timed out") 1375 case err := <-errchan: 1376 if err != nil { 1377 c.Fatal(err) 1378 } 1379 } 1380 } 1381 1382 // TestHttpsInfo connects via two-way authenticated HTTPS to the info endpoint 1383 func (s *DockerDaemonSuite) TestHttpsInfo(c *check.C) { 1384 const ( 1385 testDaemonHTTPSAddr = "tcp://localhost:4271" 1386 ) 1387 1388 if err := s.d.Start("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-cert.pem", 1389 "--tlskey", "fixtures/https/server-key.pem", "-H", testDaemonHTTPSAddr); err != nil { 1390 c.Fatalf("Could not start daemon with busybox: %v", err) 1391 } 1392 1393 daemonArgs := []string{"--host", testDaemonHTTPSAddr, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/client-cert.pem", "--tlskey", "fixtures/https/client-key.pem"} 1394 out, err := s.d.CmdWithArgs(daemonArgs, "info") 1395 if err != nil { 1396 c.Fatalf("Error Occurred: %s and output: %s", err, out) 1397 } 1398 } 1399 1400 // TestHttpsRun connects via two-way authenticated HTTPS to the create, attach, start, and wait endpoints. 1401 // https://github.com/docker/docker/issues/19280 1402 func (s *DockerDaemonSuite) TestHttpsRun(c *check.C) { 1403 const ( 1404 testDaemonHTTPSAddr = "tcp://localhost:4271" 1405 ) 1406 1407 if err := s.d.StartWithBusybox("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-cert.pem", 1408 "--tlskey", "fixtures/https/server-key.pem", "-H", testDaemonHTTPSAddr); err != nil { 1409 c.Fatalf("Could not start daemon with busybox: %v", err) 1410 } 1411 1412 daemonArgs := []string{"--host", testDaemonHTTPSAddr, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/client-cert.pem", "--tlskey", "fixtures/https/client-key.pem"} 1413 out, err := s.d.CmdWithArgs(daemonArgs, "run", "busybox", "echo", "TLS response") 1414 if err != nil { 1415 c.Fatalf("Error Occurred: %s and output: %s", err, out) 1416 } 1417 1418 if !strings.Contains(out, "TLS response") { 1419 c.Fatalf("expected output to include `TLS response`, got %v", out) 1420 } 1421 } 1422 1423 // TestTlsVerify verifies that --tlsverify=false turns on tls 1424 func (s *DockerDaemonSuite) TestTlsVerify(c *check.C) { 1425 out, err := exec.Command(dockerBinary, "daemon", "--tlsverify=false").CombinedOutput() 1426 if err == nil || !strings.Contains(string(out), "Could not load X509 key pair") { 1427 c.Fatalf("Daemon should not have started due to missing certs: %v\n%s", err, string(out)) 1428 } 1429 } 1430 1431 // TestHttpsInfoRogueCert connects via two-way authenticated HTTPS to the info endpoint 1432 // by using a rogue client certificate and checks that it fails with the expected error. 1433 func (s *DockerDaemonSuite) TestHttpsInfoRogueCert(c *check.C) { 1434 const ( 1435 errBadCertificate = "remote error: bad certificate" 1436 testDaemonHTTPSAddr = "tcp://localhost:4271" 1437 ) 1438 1439 if err := s.d.Start("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-cert.pem", 1440 "--tlskey", "fixtures/https/server-key.pem", "-H", testDaemonHTTPSAddr); err != nil { 1441 c.Fatalf("Could not start daemon with busybox: %v", err) 1442 } 1443 1444 daemonArgs := []string{"--host", testDaemonHTTPSAddr, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/client-rogue-cert.pem", "--tlskey", "fixtures/https/client-rogue-key.pem"} 1445 out, err := s.d.CmdWithArgs(daemonArgs, "info") 1446 if err == nil || !strings.Contains(out, errBadCertificate) { 1447 c.Fatalf("Expected err: %s, got instead: %s and output: %s", errBadCertificate, err, out) 1448 } 1449 } 1450 1451 // TestHttpsInfoRogueServerCert connects via two-way authenticated HTTPS to the info endpoint 1452 // which provides a rogue server certificate and checks that it fails with the expected error 1453 func (s *DockerDaemonSuite) TestHttpsInfoRogueServerCert(c *check.C) { 1454 const ( 1455 errCaUnknown = "x509: certificate signed by unknown authority" 1456 testDaemonRogueHTTPSAddr = "tcp://localhost:4272" 1457 ) 1458 if err := s.d.Start("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-rogue-cert.pem", 1459 "--tlskey", "fixtures/https/server-rogue-key.pem", "-H", testDaemonRogueHTTPSAddr); err != nil { 1460 c.Fatalf("Could not start daemon with busybox: %v", err) 1461 } 1462 1463 daemonArgs := []string{"--host", testDaemonRogueHTTPSAddr, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/client-rogue-cert.pem", "--tlskey", "fixtures/https/client-rogue-key.pem"} 1464 out, err := s.d.CmdWithArgs(daemonArgs, "info") 1465 if err == nil || !strings.Contains(out, errCaUnknown) { 1466 c.Fatalf("Expected err: %s, got instead: %s and output: %s", errCaUnknown, err, out) 1467 } 1468 } 1469 1470 func pingContainers(c *check.C, d *Daemon, expectFailure bool) { 1471 var dargs []string 1472 if d != nil { 1473 dargs = []string{"--host", d.sock()} 1474 } 1475 1476 args := append(dargs, "run", "-d", "--name", "container1", "busybox", "top") 1477 dockerCmd(c, args...) 1478 1479 args = append(dargs, "run", "--rm", "--link", "container1:alias1", "busybox", "sh", "-c") 1480 pingCmd := "ping -c 1 %s -W 1" 1481 args = append(args, fmt.Sprintf(pingCmd, "alias1")) 1482 _, _, err := dockerCmdWithError(args...) 1483 1484 if expectFailure { 1485 c.Assert(err, check.NotNil) 1486 } else { 1487 c.Assert(err, check.IsNil) 1488 } 1489 1490 args = append(dargs, "rm", "-f", "container1") 1491 dockerCmd(c, args...) 1492 } 1493 1494 func (s *DockerDaemonSuite) TestDaemonRestartWithSocketAsVolume(c *check.C) { 1495 c.Assert(s.d.StartWithBusybox(), check.IsNil) 1496 1497 socket := filepath.Join(s.d.folder, "docker.sock") 1498 1499 out, err := s.d.Cmd("run", "--restart=always", "-v", socket+":/sock", "busybox") 1500 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1501 c.Assert(s.d.Restart(), check.IsNil) 1502 } 1503 1504 // os.Kill should kill daemon ungracefully, leaving behind container mounts. 1505 // A subsequent daemon restart shoud clean up said mounts. 1506 func (s *DockerDaemonSuite) TestCleanupMountsAfterDaemonAndContainerKill(c *check.C) { 1507 c.Assert(s.d.StartWithBusybox(), check.IsNil) 1508 1509 out, err := s.d.Cmd("run", "-d", "busybox", "top") 1510 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1511 id := strings.TrimSpace(out) 1512 c.Assert(s.d.cmd.Process.Signal(os.Kill), check.IsNil) 1513 mountOut, err := ioutil.ReadFile("/proc/self/mountinfo") 1514 c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut)) 1515 1516 // container mounts should exist even after daemon has crashed. 1517 comment := check.Commentf("%s should stay mounted from older daemon start:\nDaemon root repository %s\n%s", id, s.d.folder, mountOut) 1518 c.Assert(strings.Contains(string(mountOut), id), check.Equals, true, comment) 1519 1520 // kill the container 1521 runCmd := exec.Command(ctrBinary, "--address", "/var/run/docker/libcontainerd/docker-containerd.sock", "containers", "kill", id) 1522 if out, ec, err := runCommandWithOutput(runCmd); err != nil { 1523 c.Fatalf("Failed to run ctr, ExitCode: %d, err: %v output: %s id: %s\n", ec, err, out, id) 1524 } 1525 1526 // restart daemon. 1527 if err := s.d.Restart(); err != nil { 1528 c.Fatal(err) 1529 } 1530 1531 // Now, container mounts should be gone. 1532 mountOut, err = ioutil.ReadFile("/proc/self/mountinfo") 1533 c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut)) 1534 comment = check.Commentf("%s is still mounted from older daemon start:\nDaemon root repository %s\n%s", id, s.d.folder, mountOut) 1535 c.Assert(strings.Contains(string(mountOut), id), check.Equals, false, comment) 1536 } 1537 1538 // os.Interrupt should perform a graceful daemon shutdown and hence cleanup mounts. 1539 func (s *DockerDaemonSuite) TestCleanupMountsAfterGracefulShutdown(c *check.C) { 1540 c.Assert(s.d.StartWithBusybox(), check.IsNil) 1541 1542 out, err := s.d.Cmd("run", "-d", "busybox", "top") 1543 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1544 id := strings.TrimSpace(out) 1545 1546 // Send SIGINT and daemon should clean up 1547 c.Assert(s.d.cmd.Process.Signal(os.Interrupt), check.IsNil) 1548 1549 // Wait a bit for the daemon to handle cleanups. 1550 time.Sleep(3 * time.Second) 1551 1552 mountOut, err := ioutil.ReadFile("/proc/self/mountinfo") 1553 c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut)) 1554 1555 comment := check.Commentf("%s is still mounted from older daemon start:\nDaemon root repository %s\n%s", id, s.d.folder, mountOut) 1556 c.Assert(strings.Contains(string(mountOut), id), check.Equals, false, comment) 1557 } 1558 1559 func (s *DockerDaemonSuite) TestRunContainerWithBridgeNone(c *check.C) { 1560 testRequires(c, DaemonIsLinux, NotUserNamespace) 1561 c.Assert(s.d.StartWithBusybox("-b", "none"), check.IsNil) 1562 1563 out, err := s.d.Cmd("run", "--rm", "busybox", "ip", "l") 1564 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1565 c.Assert(strings.Contains(out, "eth0"), check.Equals, false, 1566 check.Commentf("There shouldn't be eth0 in container in default(bridge) mode when bridge network is disabled: %s", out)) 1567 1568 out, err = s.d.Cmd("run", "--rm", "--net=bridge", "busybox", "ip", "l") 1569 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1570 c.Assert(strings.Contains(out, "eth0"), check.Equals, false, 1571 check.Commentf("There shouldn't be eth0 in container in bridge mode when bridge network is disabled: %s", out)) 1572 // the extra grep and awk clean up the output of `ip` to only list the number and name of 1573 // interfaces, allowing for different versions of ip (e.g. inside and outside the container) to 1574 // be used while still verifying that the interface list is the exact same 1575 cmd := exec.Command("sh", "-c", "ip l | grep -E '^[0-9]+:' | awk -F: ' { print $1\":\"$2 } '") 1576 stdout := bytes.NewBuffer(nil) 1577 cmd.Stdout = stdout 1578 if err := cmd.Run(); err != nil { 1579 c.Fatal("Failed to get host network interface") 1580 } 1581 out, err = s.d.Cmd("run", "--rm", "--net=host", "busybox", "sh", "-c", "ip l | grep -E '^[0-9]+:' | awk -F: ' { print $1\":\"$2 } '") 1582 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1583 c.Assert(out, check.Equals, fmt.Sprintf("%s", stdout), 1584 check.Commentf("The network interfaces in container should be the same with host when --net=host when bridge network is disabled: %s", out)) 1585 } 1586 1587 func (s *DockerDaemonSuite) TestDaemonRestartWithContainerRunning(t *check.C) { 1588 if err := s.d.StartWithBusybox(); err != nil { 1589 t.Fatal(err) 1590 } 1591 if out, err := s.d.Cmd("run", "-d", "--name", "test", "busybox", "top"); err != nil { 1592 t.Fatal(out, err) 1593 } 1594 1595 if err := s.d.Restart(); err != nil { 1596 t.Fatal(err) 1597 } 1598 // Container 'test' should be removed without error 1599 if out, err := s.d.Cmd("rm", "test"); err != nil { 1600 t.Fatal(out, err) 1601 } 1602 } 1603 1604 func (s *DockerDaemonSuite) TestDaemonRestartCleanupNetns(c *check.C) { 1605 if err := s.d.StartWithBusybox(); err != nil { 1606 c.Fatal(err) 1607 } 1608 out, err := s.d.Cmd("run", "--name", "netns", "-d", "busybox", "top") 1609 if err != nil { 1610 c.Fatal(out, err) 1611 } 1612 1613 // Get sandbox key via inspect 1614 out, err = s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.SandboxKey}}'", "netns") 1615 if err != nil { 1616 c.Fatalf("Error inspecting container: %s, %v", out, err) 1617 } 1618 fileName := strings.Trim(out, " \r\n'") 1619 1620 if out, err := s.d.Cmd("stop", "netns"); err != nil { 1621 c.Fatal(out, err) 1622 } 1623 1624 // Test if the file still exists 1625 out, _, err = runCommandWithOutput(exec.Command("stat", "-c", "%n", fileName)) 1626 out = strings.TrimSpace(out) 1627 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1628 c.Assert(out, check.Equals, fileName, check.Commentf("Output: %s", out)) 1629 1630 // Remove the container and restart the daemon 1631 if out, err := s.d.Cmd("rm", "netns"); err != nil { 1632 c.Fatal(out, err) 1633 } 1634 1635 if err := s.d.Restart(); err != nil { 1636 c.Fatal(err) 1637 } 1638 1639 // Test again and see now the netns file does not exist 1640 out, _, err = runCommandWithOutput(exec.Command("stat", "-c", "%n", fileName)) 1641 out = strings.TrimSpace(out) 1642 c.Assert(err, check.Not(check.IsNil), check.Commentf("Output: %s", out)) 1643 } 1644 1645 // tests regression detailed in #13964 where DOCKER_TLS_VERIFY env is ignored 1646 func (s *DockerDaemonSuite) TestDaemonNoTlsCliTlsVerifyWithEnv(c *check.C) { 1647 host := "tcp://localhost:4271" 1648 c.Assert(s.d.Start("-H", host), check.IsNil) 1649 cmd := exec.Command(dockerBinary, "-H", host, "info") 1650 cmd.Env = []string{"DOCKER_TLS_VERIFY=1", "DOCKER_CERT_PATH=fixtures/https"} 1651 out, _, err := runCommandWithOutput(cmd) 1652 c.Assert(err, check.Not(check.IsNil), check.Commentf("%s", out)) 1653 c.Assert(strings.Contains(out, "error occurred trying to connect"), check.Equals, true) 1654 1655 } 1656 1657 func setupV6() error { 1658 // Hack to get the right IPv6 address on docker0, which has already been created 1659 return exec.Command("ip", "addr", "add", "fe80::1/64", "dev", "docker0").Run() 1660 } 1661 1662 func teardownV6() error { 1663 return exec.Command("ip", "addr", "del", "fe80::1/64", "dev", "docker0").Run() 1664 } 1665 1666 func (s *DockerDaemonSuite) TestDaemonRestartWithContainerWithRestartPolicyAlways(c *check.C) { 1667 c.Assert(s.d.StartWithBusybox(), check.IsNil) 1668 1669 out, err := s.d.Cmd("run", "-d", "--restart", "always", "busybox", "top") 1670 c.Assert(err, check.IsNil) 1671 id := strings.TrimSpace(out) 1672 1673 _, err = s.d.Cmd("stop", id) 1674 c.Assert(err, check.IsNil) 1675 _, err = s.d.Cmd("wait", id) 1676 c.Assert(err, check.IsNil) 1677 1678 out, err = s.d.Cmd("ps", "-q") 1679 c.Assert(err, check.IsNil) 1680 c.Assert(out, check.Equals, "") 1681 1682 c.Assert(s.d.Restart(), check.IsNil) 1683 1684 out, err = s.d.Cmd("ps", "-q") 1685 c.Assert(err, check.IsNil) 1686 c.Assert(strings.TrimSpace(out), check.Equals, id[:12]) 1687 } 1688 1689 func (s *DockerDaemonSuite) TestDaemonWideLogConfig(c *check.C) { 1690 if err := s.d.StartWithBusybox("--log-driver=json-file", "--log-opt=max-size=1k"); err != nil { 1691 c.Fatal(err) 1692 } 1693 out, err := s.d.Cmd("run", "-d", "--name=logtest", "busybox", "top") 1694 c.Assert(err, check.IsNil, check.Commentf("Output: %s, err: %v", out, err)) 1695 out, err = s.d.Cmd("inspect", "-f", "{{ .HostConfig.LogConfig.Config }}", "logtest") 1696 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1697 cfg := strings.TrimSpace(out) 1698 if cfg != "map[max-size:1k]" { 1699 c.Fatalf("Unexpected log-opt: %s, expected map[max-size:1k]", cfg) 1700 } 1701 } 1702 1703 func (s *DockerDaemonSuite) TestDaemonRestartWithPausedContainer(c *check.C) { 1704 if err := s.d.StartWithBusybox(); err != nil { 1705 c.Fatal(err) 1706 } 1707 if out, err := s.d.Cmd("run", "-i", "-d", "--name", "test", "busybox", "top"); err != nil { 1708 c.Fatal(err, out) 1709 } 1710 if out, err := s.d.Cmd("pause", "test"); err != nil { 1711 c.Fatal(err, out) 1712 } 1713 if err := s.d.Restart(); err != nil { 1714 c.Fatal(err) 1715 } 1716 1717 errchan := make(chan error) 1718 go func() { 1719 out, err := s.d.Cmd("start", "test") 1720 if err != nil { 1721 errchan <- fmt.Errorf("%v:\n%s", err, out) 1722 } 1723 name := strings.TrimSpace(out) 1724 if name != "test" { 1725 errchan <- fmt.Errorf("Paused container start error on docker daemon restart, expected 'test' but got '%s'", name) 1726 } 1727 close(errchan) 1728 }() 1729 1730 select { 1731 case <-time.After(5 * time.Second): 1732 c.Fatal("Waiting on start a container timed out") 1733 case err := <-errchan: 1734 if err != nil { 1735 c.Fatal(err) 1736 } 1737 } 1738 } 1739 1740 func (s *DockerDaemonSuite) TestDaemonRestartRmVolumeInUse(c *check.C) { 1741 c.Assert(s.d.StartWithBusybox(), check.IsNil) 1742 1743 out, err := s.d.Cmd("create", "-v", "test:/foo", "busybox") 1744 c.Assert(err, check.IsNil, check.Commentf(out)) 1745 1746 c.Assert(s.d.Restart(), check.IsNil) 1747 1748 out, err = s.d.Cmd("volume", "rm", "test") 1749 c.Assert(err, check.NotNil, check.Commentf("should not be able to remove in use volume after daemon restart")) 1750 c.Assert(out, checker.Contains, "in use") 1751 } 1752 1753 func (s *DockerDaemonSuite) TestDaemonRestartLocalVolumes(c *check.C) { 1754 c.Assert(s.d.Start(), check.IsNil) 1755 1756 _, err := s.d.Cmd("volume", "create", "--name", "test") 1757 c.Assert(err, check.IsNil) 1758 c.Assert(s.d.Restart(), check.IsNil) 1759 1760 _, err = s.d.Cmd("volume", "inspect", "test") 1761 c.Assert(err, check.IsNil) 1762 } 1763 1764 func (s *DockerDaemonSuite) TestDaemonCorruptedLogDriverAddress(c *check.C) { 1765 c.Assert(s.d.Start("--log-driver=syslog", "--log-opt", "syslog-address=corrupted:42"), check.NotNil) 1766 expected := "Failed to set log opts: syslog-address should be in form proto://address" 1767 runCmd := exec.Command("grep", expected, s.d.LogFileName()) 1768 if out, _, err := runCommandWithOutput(runCmd); err != nil { 1769 c.Fatalf("Expected %q message; but doesn't exist in log: %q, err: %v", expected, out, err) 1770 } 1771 } 1772 1773 func (s *DockerDaemonSuite) TestDaemonCorruptedFluentdAddress(c *check.C) { 1774 c.Assert(s.d.Start("--log-driver=fluentd", "--log-opt", "fluentd-address=corrupted:c"), check.NotNil) 1775 expected := "Failed to set log opts: invalid fluentd-address corrupted:c: " 1776 runCmd := exec.Command("grep", expected, s.d.LogFileName()) 1777 if out, _, err := runCommandWithOutput(runCmd); err != nil { 1778 c.Fatalf("Expected %q message; but doesn't exist in log: %q, err: %v", expected, out, err) 1779 } 1780 } 1781 1782 func (s *DockerDaemonSuite) TestDaemonStartWithoutHost(c *check.C) { 1783 s.d.useDefaultHost = true 1784 defer func() { 1785 s.d.useDefaultHost = false 1786 }() 1787 c.Assert(s.d.Start(), check.IsNil) 1788 } 1789 1790 func (s *DockerDaemonSuite) TestDaemonStartWithDefalutTlsHost(c *check.C) { 1791 s.d.useDefaultTLSHost = true 1792 defer func() { 1793 s.d.useDefaultTLSHost = false 1794 }() 1795 if err := s.d.Start( 1796 "--tlsverify", 1797 "--tlscacert", "fixtures/https/ca.pem", 1798 "--tlscert", "fixtures/https/server-cert.pem", 1799 "--tlskey", "fixtures/https/server-key.pem"); err != nil { 1800 c.Fatalf("Could not start daemon: %v", err) 1801 } 1802 1803 // The client with --tlsverify should also use default host localhost:2376 1804 tmpHost := os.Getenv("DOCKER_HOST") 1805 defer func() { 1806 os.Setenv("DOCKER_HOST", tmpHost) 1807 }() 1808 1809 os.Setenv("DOCKER_HOST", "") 1810 1811 out, _ := dockerCmd( 1812 c, 1813 "--tlsverify", 1814 "--tlscacert", "fixtures/https/ca.pem", 1815 "--tlscert", "fixtures/https/client-cert.pem", 1816 "--tlskey", "fixtures/https/client-key.pem", 1817 "version", 1818 ) 1819 if !strings.Contains(out, "Server") { 1820 c.Fatalf("docker version should return information of server side") 1821 } 1822 } 1823 1824 func (s *DockerDaemonSuite) TestBridgeIPIsExcludedFromAllocatorPool(c *check.C) { 1825 defaultNetworkBridge := "docker0" 1826 deleteInterface(c, defaultNetworkBridge) 1827 1828 bridgeIP := "192.169.1.1" 1829 bridgeRange := bridgeIP + "/30" 1830 1831 err := s.d.StartWithBusybox("--bip", bridgeRange) 1832 c.Assert(err, check.IsNil) 1833 defer s.d.Restart() 1834 1835 var cont int 1836 for { 1837 contName := fmt.Sprintf("container%d", cont) 1838 _, err = s.d.Cmd("run", "--name", contName, "-d", "busybox", "/bin/sleep", "2") 1839 if err != nil { 1840 // pool exhausted 1841 break 1842 } 1843 ip, err := s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.IPAddress}}'", contName) 1844 c.Assert(err, check.IsNil) 1845 1846 c.Assert(ip, check.Not(check.Equals), bridgeIP) 1847 cont++ 1848 } 1849 } 1850 1851 // Test daemon for no space left on device error 1852 func (s *DockerDaemonSuite) TestDaemonNoSpaceleftOnDeviceError(c *check.C) { 1853 testRequires(c, SameHostDaemon, DaemonIsLinux, Network) 1854 1855 // create a 2MiB image and mount it as graph root 1856 cmd := exec.Command("dd", "of=/tmp/testfs.img", "bs=1M", "seek=2", "count=0") 1857 if err := cmd.Run(); err != nil { 1858 c.Fatalf("dd failed: %v", err) 1859 } 1860 cmd = exec.Command("mkfs.ext4", "-F", "/tmp/testfs.img") 1861 if err := cmd.Run(); err != nil { 1862 c.Fatalf("mkfs.ext4 failed: %v", err) 1863 } 1864 cmd = exec.Command("mkdir", "-p", "/tmp/testfs-mount") 1865 if err := cmd.Run(); err != nil { 1866 c.Fatalf("mkdir failed: %v", err) 1867 } 1868 cmd = exec.Command("mount", "-t", "ext4", "-no", "loop,rw", "/tmp/testfs.img", "/tmp/testfs-mount") 1869 if err := cmd.Run(); err != nil { 1870 c.Fatalf("mount failed: %v", err) 1871 } 1872 err := s.d.Start("--graph", "/tmp/testfs-mount") 1873 c.Assert(err, check.IsNil) 1874 1875 // pull a repository large enough to fill the mount point 1876 out, err := s.d.Cmd("pull", "registry:2") 1877 c.Assert(out, checker.Contains, "no space left on device") 1878 } 1879 1880 // Test daemon restart with container links + auto restart 1881 func (s *DockerDaemonSuite) TestDaemonRestartContainerLinksRestart(c *check.C) { 1882 d := NewDaemon(c) 1883 defer d.Stop() 1884 err := d.StartWithBusybox() 1885 c.Assert(err, checker.IsNil) 1886 1887 parent1Args := []string{} 1888 parent2Args := []string{} 1889 wg := sync.WaitGroup{} 1890 maxChildren := 10 1891 chErr := make(chan error, maxChildren) 1892 1893 for i := 0; i < maxChildren; i++ { 1894 wg.Add(1) 1895 name := fmt.Sprintf("test%d", i) 1896 1897 if i < maxChildren/2 { 1898 parent1Args = append(parent1Args, []string{"--link", name}...) 1899 } else { 1900 parent2Args = append(parent2Args, []string{"--link", name}...) 1901 } 1902 1903 go func() { 1904 _, err = d.Cmd("run", "-d", "--name", name, "--restart=always", "busybox", "top") 1905 chErr <- err 1906 wg.Done() 1907 }() 1908 } 1909 1910 wg.Wait() 1911 close(chErr) 1912 for err := range chErr { 1913 c.Assert(err, check.IsNil) 1914 } 1915 1916 parent1Args = append([]string{"run", "-d"}, parent1Args...) 1917 parent1Args = append(parent1Args, []string{"--name=parent1", "--restart=always", "busybox", "top"}...) 1918 parent2Args = append([]string{"run", "-d"}, parent2Args...) 1919 parent2Args = append(parent2Args, []string{"--name=parent2", "--restart=always", "busybox", "top"}...) 1920 1921 _, err = d.Cmd(parent1Args[0], parent1Args[1:]...) 1922 c.Assert(err, check.IsNil) 1923 _, err = d.Cmd(parent2Args[0], parent2Args[1:]...) 1924 c.Assert(err, check.IsNil) 1925 1926 err = d.Stop() 1927 c.Assert(err, check.IsNil) 1928 // clear the log file -- we don't need any of it but may for the next part 1929 // can ignore the error here, this is just a cleanup 1930 os.Truncate(d.LogFileName(), 0) 1931 err = d.Start() 1932 c.Assert(err, check.IsNil) 1933 1934 for _, num := range []string{"1", "2"} { 1935 out, err := d.Cmd("inspect", "-f", "{{ .State.Running }}", "parent"+num) 1936 c.Assert(err, check.IsNil) 1937 if strings.TrimSpace(out) != "true" { 1938 log, _ := ioutil.ReadFile(d.LogFileName()) 1939 c.Fatalf("parent container is not running\n%s", string(log)) 1940 } 1941 } 1942 } 1943 1944 func (s *DockerDaemonSuite) TestDaemonCgroupParent(c *check.C) { 1945 testRequires(c, DaemonIsLinux) 1946 1947 cgroupParent := "test" 1948 name := "cgroup-test" 1949 1950 err := s.d.StartWithBusybox("--cgroup-parent", cgroupParent) 1951 c.Assert(err, check.IsNil) 1952 defer s.d.Restart() 1953 1954 out, err := s.d.Cmd("run", "--name", name, "busybox", "cat", "/proc/self/cgroup") 1955 c.Assert(err, checker.IsNil) 1956 cgroupPaths := parseCgroupPaths(string(out)) 1957 c.Assert(len(cgroupPaths), checker.Not(checker.Equals), 0, check.Commentf("unexpected output - %q", string(out))) 1958 out, err = s.d.Cmd("inspect", "-f", "{{.Id}}", name) 1959 c.Assert(err, checker.IsNil) 1960 id := strings.TrimSpace(string(out)) 1961 expectedCgroup := path.Join(cgroupParent, id) 1962 found := false 1963 for _, path := range cgroupPaths { 1964 if strings.HasSuffix(path, expectedCgroup) { 1965 found = true 1966 break 1967 } 1968 } 1969 c.Assert(found, checker.True, check.Commentf("Cgroup path for container (%s) doesn't found in cgroups file: %s", expectedCgroup, cgroupPaths)) 1970 } 1971 1972 func (s *DockerDaemonSuite) TestDaemonRestartWithLinks(c *check.C) { 1973 testRequires(c, DaemonIsLinux) // Windows does not support links 1974 err := s.d.StartWithBusybox() 1975 c.Assert(err, check.IsNil) 1976 1977 out, err := s.d.Cmd("run", "-d", "--name=test", "busybox", "top") 1978 c.Assert(err, check.IsNil, check.Commentf(out)) 1979 1980 out, err = s.d.Cmd("run", "--name=test2", "--link", "test:abc", "busybox", "sh", "-c", "ping -c 1 -w 1 abc") 1981 c.Assert(err, check.IsNil, check.Commentf(out)) 1982 1983 c.Assert(s.d.Restart(), check.IsNil) 1984 1985 // should fail since test is not running yet 1986 out, err = s.d.Cmd("start", "test2") 1987 c.Assert(err, check.NotNil, check.Commentf(out)) 1988 1989 out, err = s.d.Cmd("start", "test") 1990 c.Assert(err, check.IsNil, check.Commentf(out)) 1991 out, err = s.d.Cmd("start", "-a", "test2") 1992 c.Assert(err, check.IsNil, check.Commentf(out)) 1993 c.Assert(strings.Contains(out, "1 packets transmitted, 1 packets received"), check.Equals, true, check.Commentf(out)) 1994 } 1995 1996 func (s *DockerDaemonSuite) TestDaemonRestartWithNames(c *check.C) { 1997 testRequires(c, DaemonIsLinux) // Windows does not support links 1998 err := s.d.StartWithBusybox() 1999 c.Assert(err, check.IsNil) 2000 2001 out, err := s.d.Cmd("create", "--name=test", "busybox") 2002 c.Assert(err, check.IsNil, check.Commentf(out)) 2003 2004 out, err = s.d.Cmd("run", "-d", "--name=test2", "busybox", "top") 2005 c.Assert(err, check.IsNil, check.Commentf(out)) 2006 test2ID := strings.TrimSpace(out) 2007 2008 out, err = s.d.Cmd("run", "-d", "--name=test3", "--link", "test2:abc", "busybox", "top") 2009 test3ID := strings.TrimSpace(out) 2010 2011 c.Assert(s.d.Restart(), check.IsNil) 2012 2013 out, err = s.d.Cmd("create", "--name=test", "busybox") 2014 c.Assert(err, check.NotNil, check.Commentf("expected error trying to create container with duplicate name")) 2015 // this one is no longer needed, removing simplifies the remainder of the test 2016 out, err = s.d.Cmd("rm", "-f", "test") 2017 c.Assert(err, check.IsNil, check.Commentf(out)) 2018 2019 out, err = s.d.Cmd("ps", "-a", "--no-trunc") 2020 c.Assert(err, check.IsNil, check.Commentf(out)) 2021 2022 lines := strings.Split(strings.TrimSpace(out), "\n")[1:] 2023 2024 test2validated := false 2025 test3validated := false 2026 for _, line := range lines { 2027 fields := strings.Fields(line) 2028 names := fields[len(fields)-1] 2029 switch fields[0] { 2030 case test2ID: 2031 c.Assert(names, check.Equals, "test2,test3/abc") 2032 test2validated = true 2033 case test3ID: 2034 c.Assert(names, check.Equals, "test3") 2035 test3validated = true 2036 } 2037 } 2038 2039 c.Assert(test2validated, check.Equals, true) 2040 c.Assert(test3validated, check.Equals, true) 2041 } 2042 2043 // TestRunLinksChanged checks that creating a new container with the same name does not update links 2044 // this ensures that the old, pre gh#16032 functionality continues on 2045 func (s *DockerDaemonSuite) TestRunLinksChanged(c *check.C) { 2046 testRequires(c, DaemonIsLinux) // Windows does not support links 2047 err := s.d.StartWithBusybox() 2048 c.Assert(err, check.IsNil) 2049 2050 out, err := s.d.Cmd("run", "-d", "--name=test", "busybox", "top") 2051 c.Assert(err, check.IsNil, check.Commentf(out)) 2052 2053 out, err = s.d.Cmd("run", "--name=test2", "--link=test:abc", "busybox", "sh", "-c", "ping -c 1 abc") 2054 c.Assert(err, check.IsNil, check.Commentf(out)) 2055 c.Assert(out, checker.Contains, "1 packets transmitted, 1 packets received") 2056 2057 out, err = s.d.Cmd("rm", "-f", "test") 2058 c.Assert(err, check.IsNil, check.Commentf(out)) 2059 2060 out, err = s.d.Cmd("run", "-d", "--name=test", "busybox", "top") 2061 c.Assert(err, check.IsNil, check.Commentf(out)) 2062 out, err = s.d.Cmd("start", "-a", "test2") 2063 c.Assert(err, check.NotNil, check.Commentf(out)) 2064 c.Assert(out, check.Not(checker.Contains), "1 packets transmitted, 1 packets received") 2065 2066 err = s.d.Restart() 2067 c.Assert(err, check.IsNil) 2068 out, err = s.d.Cmd("start", "-a", "test2") 2069 c.Assert(err, check.NotNil, check.Commentf(out)) 2070 c.Assert(out, check.Not(checker.Contains), "1 packets transmitted, 1 packets received") 2071 } 2072 2073 func (s *DockerDaemonSuite) TestDaemonStartWithoutColors(c *check.C) { 2074 testRequires(c, DaemonIsLinux, NotPpc64le) 2075 newD := NewDaemon(c) 2076 2077 infoLog := "\x1b[34mINFO\x1b" 2078 2079 p, tty, err := pty.Open() 2080 c.Assert(err, checker.IsNil) 2081 defer func() { 2082 tty.Close() 2083 p.Close() 2084 }() 2085 2086 b := bytes.NewBuffer(nil) 2087 go io.Copy(b, p) 2088 2089 // Enable coloring explicitly 2090 newD.StartWithLogFile(tty, "--raw-logs=false") 2091 newD.Stop() 2092 c.Assert(b.String(), checker.Contains, infoLog) 2093 2094 b.Reset() 2095 2096 // Disable coloring explicitly 2097 newD.StartWithLogFile(tty, "--raw-logs=true") 2098 newD.Stop() 2099 c.Assert(b.String(), check.Not(checker.Contains), infoLog) 2100 } 2101 2102 func (s *DockerDaemonSuite) TestDaemonDebugLog(c *check.C) { 2103 testRequires(c, DaemonIsLinux, NotPpc64le) 2104 newD := NewDaemon(c) 2105 2106 debugLog := "\x1b[37mDEBU\x1b" 2107 2108 p, tty, err := pty.Open() 2109 c.Assert(err, checker.IsNil) 2110 defer func() { 2111 tty.Close() 2112 p.Close() 2113 }() 2114 2115 b := bytes.NewBuffer(nil) 2116 go io.Copy(b, p) 2117 2118 newD.StartWithLogFile(tty, "--debug") 2119 newD.Stop() 2120 c.Assert(b.String(), checker.Contains, debugLog) 2121 } 2122 2123 func (s *DockerSuite) TestDaemonDiscoveryBackendConfigReload(c *check.C) { 2124 testRequires(c, SameHostDaemon, DaemonIsLinux) 2125 2126 // daemon config file 2127 daemonConfig := `{ "debug" : false }` 2128 configFilePath := "test.json" 2129 2130 configFile, err := os.Create(configFilePath) 2131 c.Assert(err, checker.IsNil) 2132 fmt.Fprintf(configFile, "%s", daemonConfig) 2133 2134 d := NewDaemon(c) 2135 err = d.Start(fmt.Sprintf("--config-file=%s", configFilePath)) 2136 c.Assert(err, checker.IsNil) 2137 defer d.Stop() 2138 2139 // daemon config file 2140 daemonConfig = `{ 2141 "cluster-store": "consul://consuladdr:consulport/some/path", 2142 "cluster-advertise": "192.168.56.100:0", 2143 "debug" : false 2144 }` 2145 2146 configFile.Close() 2147 os.Remove(configFilePath) 2148 2149 configFile, err = os.Create(configFilePath) 2150 c.Assert(err, checker.IsNil) 2151 defer os.Remove(configFilePath) 2152 fmt.Fprintf(configFile, "%s", daemonConfig) 2153 configFile.Close() 2154 2155 syscall.Kill(d.cmd.Process.Pid, syscall.SIGHUP) 2156 2157 time.Sleep(3 * time.Second) 2158 2159 out, err := d.Cmd("info") 2160 c.Assert(err, checker.IsNil) 2161 c.Assert(out, checker.Contains, fmt.Sprintf("Cluster store: consul://consuladdr:consulport/some/path")) 2162 c.Assert(out, checker.Contains, fmt.Sprintf("Cluster advertise: 192.168.56.100:0")) 2163 }