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