github.com/carlanton/docker@v1.8.0-rc1/integration-cli/docker_cli_daemon_test.go (about) 1 // +build daemon 2 3 package main 4 5 import ( 6 "encoding/json" 7 "fmt" 8 "io/ioutil" 9 "net" 10 "os" 11 "os/exec" 12 "path/filepath" 13 "regexp" 14 "strconv" 15 "strings" 16 "time" 17 18 "github.com/docker/libnetwork/iptables" 19 "github.com/docker/libtrust" 20 "github.com/go-check/check" 21 ) 22 23 func (s *DockerDaemonSuite) TestDaemonRestartWithRunningContainersPorts(c *check.C) { 24 if err := s.d.StartWithBusybox(); err != nil { 25 c.Fatalf("Could not start daemon with busybox: %v", err) 26 } 27 28 if out, err := s.d.Cmd("run", "-d", "--name", "top1", "-p", "1234:80", "--restart", "always", "busybox:latest", "top"); err != nil { 29 c.Fatalf("Could not run top1: err=%v\n%s", err, out) 30 } 31 // --restart=no by default 32 if out, err := s.d.Cmd("run", "-d", "--name", "top2", "-p", "80", "busybox:latest", "top"); err != nil { 33 c.Fatalf("Could not run top2: err=%v\n%s", err, out) 34 } 35 36 testRun := func(m map[string]bool, prefix string) { 37 var format string 38 for cont, shouldRun := range m { 39 out, err := s.d.Cmd("ps") 40 if err != nil { 41 c.Fatalf("Could not run ps: err=%v\n%q", err, out) 42 } 43 if shouldRun { 44 format = "%scontainer %q is not running" 45 } else { 46 format = "%scontainer %q is running" 47 } 48 if shouldRun != strings.Contains(out, cont) { 49 c.Fatalf(format, prefix, cont) 50 } 51 } 52 } 53 54 testRun(map[string]bool{"top1": true, "top2": true}, "") 55 56 if err := s.d.Restart(); err != nil { 57 c.Fatalf("Could not restart daemon: %v", err) 58 } 59 testRun(map[string]bool{"top1": true, "top2": false}, "After daemon restart: ") 60 } 61 62 func (s *DockerDaemonSuite) TestDaemonRestartWithVolumesRefs(c *check.C) { 63 if err := s.d.StartWithBusybox(); err != nil { 64 c.Fatal(err) 65 } 66 67 if out, err := s.d.Cmd("run", "-d", "--name", "volrestarttest1", "-v", "/foo", "busybox"); err != nil { 68 c.Fatal(err, out) 69 } 70 71 if err := s.d.Restart(); err != nil { 72 c.Fatal(err) 73 } 74 if _, err := s.d.Cmd("run", "-d", "--volumes-from", "volrestarttest1", "--name", "volrestarttest2", "busybox", "top"); err != nil { 75 c.Fatal(err) 76 } 77 78 if out, err := s.d.Cmd("rm", "-fv", "volrestarttest2"); err != nil { 79 c.Fatal(err, out) 80 } 81 82 out, err := s.d.Cmd("inspect", "-f", "{{json .Mounts}}", "volrestarttest1") 83 c.Assert(err, check.IsNil) 84 85 if _, err := inspectMountPointJSON(out, "/foo"); err != nil { 86 c.Fatalf("Expected volume to exist: /foo, error: %v\n", err) 87 } 88 } 89 90 func (s *DockerDaemonSuite) TestDaemonStartIptablesFalse(c *check.C) { 91 if err := s.d.Start("--iptables=false"); err != nil { 92 c.Fatalf("we should have been able to start the daemon with passing iptables=false: %v", err) 93 } 94 } 95 96 // Issue #8444: If docker0 bridge is modified (intentionally or unintentionally) and 97 // no longer has an IP associated, we should gracefully handle that case and associate 98 // an IP with it rather than fail daemon start 99 func (s *DockerDaemonSuite) TestDaemonStartBridgeWithoutIPAssociation(c *check.C) { 100 // rather than depending on brctl commands to verify docker0 is created and up 101 // let's start the daemon and stop it, and then make a modification to run the 102 // actual test 103 if err := s.d.Start(); err != nil { 104 c.Fatalf("Could not start daemon: %v", err) 105 } 106 if err := s.d.Stop(); err != nil { 107 c.Fatalf("Could not stop daemon: %v", err) 108 } 109 110 // now we will remove the ip from docker0 and then try starting the daemon 111 ipCmd := exec.Command("ip", "addr", "flush", "dev", "docker0") 112 stdout, stderr, _, err := runCommandWithStdoutStderr(ipCmd) 113 if err != nil { 114 c.Fatalf("failed to remove docker0 IP association: %v, stdout: %q, stderr: %q", err, stdout, stderr) 115 } 116 117 if err := s.d.Start(); err != nil { 118 warning := "**WARNING: Docker bridge network in bad state--delete docker0 bridge interface to fix" 119 c.Fatalf("Could not start daemon when docker0 has no IP address: %v\n%s", err, warning) 120 } 121 } 122 123 func (s *DockerDaemonSuite) TestDaemonIptablesClean(c *check.C) { 124 if err := s.d.StartWithBusybox(); err != nil { 125 c.Fatalf("Could not start daemon with busybox: %v", err) 126 } 127 128 if out, err := s.d.Cmd("run", "-d", "--name", "top", "-p", "80", "busybox:latest", "top"); err != nil { 129 c.Fatalf("Could not run top: %s, %v", out, err) 130 } 131 132 // get output from iptables with container running 133 ipTablesSearchString := "tcp dpt:80" 134 ipTablesCmd := exec.Command("iptables", "-nvL") 135 out, _, err := runCommandWithOutput(ipTablesCmd) 136 if err != nil { 137 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 138 } 139 140 if !strings.Contains(out, ipTablesSearchString) { 141 c.Fatalf("iptables output should have contained %q, but was %q", ipTablesSearchString, out) 142 } 143 144 if err := s.d.Stop(); err != nil { 145 c.Fatalf("Could not stop daemon: %v", err) 146 } 147 148 // get output from iptables after restart 149 ipTablesCmd = exec.Command("iptables", "-nvL") 150 out, _, err = runCommandWithOutput(ipTablesCmd) 151 if err != nil { 152 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 153 } 154 155 if strings.Contains(out, ipTablesSearchString) { 156 c.Fatalf("iptables output should not have contained %q, but was %q", ipTablesSearchString, out) 157 } 158 } 159 160 func (s *DockerDaemonSuite) TestDaemonIptablesCreate(c *check.C) { 161 if err := s.d.StartWithBusybox(); err != nil { 162 c.Fatalf("Could not start daemon with busybox: %v", err) 163 } 164 165 if out, err := s.d.Cmd("run", "-d", "--name", "top", "--restart=always", "-p", "80", "busybox:latest", "top"); err != nil { 166 c.Fatalf("Could not run top: %s, %v", out, err) 167 } 168 169 // get output from iptables with container running 170 ipTablesSearchString := "tcp dpt:80" 171 ipTablesCmd := exec.Command("iptables", "-nvL") 172 out, _, err := runCommandWithOutput(ipTablesCmd) 173 if err != nil { 174 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 175 } 176 177 if !strings.Contains(out, ipTablesSearchString) { 178 c.Fatalf("iptables output should have contained %q, but was %q", ipTablesSearchString, out) 179 } 180 181 if err := s.d.Restart(); err != nil { 182 c.Fatalf("Could not restart daemon: %v", err) 183 } 184 185 // make sure the container is not running 186 runningOut, err := s.d.Cmd("inspect", "--format='{{.State.Running}}'", "top") 187 if err != nil { 188 c.Fatalf("Could not inspect on container: %s, %v", out, err) 189 } 190 if strings.TrimSpace(runningOut) != "true" { 191 c.Fatalf("Container should have been restarted after daemon restart. Status running should have been true but was: %q", strings.TrimSpace(runningOut)) 192 } 193 194 // get output from iptables after restart 195 ipTablesCmd = exec.Command("iptables", "-nvL") 196 out, _, err = runCommandWithOutput(ipTablesCmd) 197 if err != nil { 198 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 199 } 200 201 if !strings.Contains(out, ipTablesSearchString) { 202 c.Fatalf("iptables output after restart should have contained %q, but was %q", ipTablesSearchString, out) 203 } 204 } 205 206 // TestDaemonIPv6Enabled checks that when the daemon is started with --ipv6=true that the docker0 bridge 207 // has the fe80::1 address and that a container is assigned a link-local address 208 func (s *DockerSuite) TestDaemonIPv6Enabled(c *check.C) { 209 testRequires(c, IPv6) 210 211 if err := setupV6(); err != nil { 212 c.Fatal("Could not set up host for IPv6 tests") 213 } 214 215 d := NewDaemon(c) 216 217 if err := d.StartWithBusybox("--ipv6"); err != nil { 218 c.Fatal(err) 219 } 220 defer d.Stop() 221 222 iface, err := net.InterfaceByName("docker0") 223 if err != nil { 224 c.Fatalf("Error getting docker0 interface: %v", err) 225 } 226 227 addrs, err := iface.Addrs() 228 if err != nil { 229 c.Fatalf("Error getting addresses for docker0 interface: %v", err) 230 } 231 232 var found bool 233 expected := "fe80::1/64" 234 235 for i := range addrs { 236 if addrs[i].String() == expected { 237 found = true 238 } 239 } 240 241 if !found { 242 c.Fatalf("Bridge does not have an IPv6 Address") 243 } 244 245 if out, err := d.Cmd("run", "-itd", "--name=ipv6test", "busybox:latest"); err != nil { 246 c.Fatalf("Could not run container: %s, %v", out, err) 247 } 248 249 out, err := d.Cmd("inspect", "--format", "'{{.NetworkSettings.LinkLocalIPv6Address}}'", "ipv6test") 250 out = strings.Trim(out, " \r\n'") 251 252 if err != nil { 253 c.Fatalf("Error inspecting container: %s, %v", out, err) 254 } 255 256 if ip := net.ParseIP(out); ip == nil { 257 c.Fatalf("Container should have a link-local IPv6 address") 258 } 259 260 out, err = d.Cmd("inspect", "--format", "'{{.NetworkSettings.GlobalIPv6Address}}'", "ipv6test") 261 out = strings.Trim(out, " \r\n'") 262 263 if err != nil { 264 c.Fatalf("Error inspecting container: %s, %v", out, err) 265 } 266 267 if ip := net.ParseIP(out); ip != nil { 268 c.Fatalf("Container should not have a global IPv6 address: %v", out) 269 } 270 271 if err := teardownV6(); err != nil { 272 c.Fatal("Could not perform teardown for IPv6 tests") 273 } 274 275 } 276 277 // TestDaemonIPv6FixedCIDR checks that when the daemon is started with --ipv6=true and a fixed CIDR 278 // that running containers are given a link-local and global IPv6 address 279 func (s *DockerSuite) TestDaemonIPv6FixedCIDR(c *check.C) { 280 testRequires(c, IPv6) 281 282 if err := setupV6(); err != nil { 283 c.Fatal("Could not set up host for IPv6 tests") 284 } 285 286 d := NewDaemon(c) 287 288 if err := d.StartWithBusybox("--ipv6", "--fixed-cidr-v6='2001:db8:1::/64'"); err != nil { 289 c.Fatalf("Could not start daemon with busybox: %v", err) 290 } 291 defer d.Stop() 292 293 if out, err := d.Cmd("run", "-itd", "--name=ipv6test", "busybox:latest"); err != nil { 294 c.Fatalf("Could not run container: %s, %v", out, err) 295 } 296 297 out, err := d.Cmd("inspect", "--format", "'{{.NetworkSettings.LinkLocalIPv6Address}}'", "ipv6test") 298 out = strings.Trim(out, " \r\n'") 299 300 if err != nil { 301 c.Fatalf("Error inspecting container: %s, %v", out, err) 302 } 303 304 if ip := net.ParseIP(out); ip == nil { 305 c.Fatalf("Container should have a link-local IPv6 address") 306 } 307 308 out, err = d.Cmd("inspect", "--format", "'{{.NetworkSettings.GlobalIPv6Address}}'", "ipv6test") 309 out = strings.Trim(out, " \r\n'") 310 311 if err != nil { 312 c.Fatalf("Error inspecting container: %s, %v", out, err) 313 } 314 315 if ip := net.ParseIP(out); ip == nil { 316 c.Fatalf("Container should have a global IPv6 address") 317 } 318 if err := teardownV6(); err != nil { 319 c.Fatal("Could not perform teardown for IPv6 tests") 320 } 321 } 322 323 func (s *DockerDaemonSuite) TestDaemonLogLevelWrong(c *check.C) { 324 c.Assert(s.d.Start("--log-level=bogus"), check.NotNil, check.Commentf("Daemon shouldn't start with wrong log level")) 325 } 326 327 func (s *DockerSuite) TestDaemonStartWithBackwardCompatibility(c *check.C) { 328 329 var validCommandArgs = [][]string{ 330 {"--selinux-enabled", "-l", "info"}, 331 {"--insecure-registry", "daemon"}, 332 } 333 334 var invalidCommandArgs = [][]string{ 335 {"--selinux-enabled", "--storage-opt"}, 336 {"-D", "-b"}, 337 {"--config", "/tmp"}, 338 } 339 340 for _, args := range validCommandArgs { 341 d := NewDaemon(c) 342 d.Command = "--daemon" 343 if err := d.Start(args...); err != nil { 344 c.Fatalf("Daemon should have started successfully with --daemon %v: %v", args, err) 345 } 346 d.Stop() 347 } 348 349 for _, args := range invalidCommandArgs { 350 d := NewDaemon(c) 351 if err := d.Start(args...); err == nil { 352 d.Stop() 353 c.Fatalf("Daemon should have failed to start with %v", args) 354 } 355 } 356 } 357 358 func (s *DockerSuite) TestDaemonStartWithDaemonCommand(c *check.C) { 359 360 type kind int 361 362 const ( 363 common kind = iota 364 daemon 365 ) 366 367 var flags = []map[kind][]string{ 368 {common: {"-l", "info"}, daemon: {"--selinux-enabled"}}, 369 {common: {"-D"}, daemon: {"--selinux-enabled", "-r"}}, 370 {common: {"-D"}, daemon: {"--restart"}}, 371 {common: {"--debug"}, daemon: {"--log-driver=json-file", "--log-opt=max-size=1k"}}, 372 } 373 374 var invalidGlobalFlags = [][]string{ 375 //Invalid because you cannot pass daemon flags as global flags. 376 {"--selinux-enabled", "-l", "info"}, 377 {"-D", "-r"}, 378 {"--config", "/tmp"}, 379 } 380 381 // `docker daemon -l info --selinux-enabled` 382 // should NOT error out 383 for _, f := range flags { 384 d := NewDaemon(c) 385 args := append(f[common], f[daemon]...) 386 if err := d.Start(args...); err != nil { 387 c.Fatalf("Daemon should have started successfully with %v: %v", args, err) 388 } 389 d.Stop() 390 } 391 392 // `docker -l info daemon --selinux-enabled` 393 // should error out 394 for _, f := range flags { 395 d := NewDaemon(c) 396 d.GlobalFlags = f[common] 397 if err := d.Start(f[daemon]...); err == nil { 398 d.Stop() 399 c.Fatalf("Daemon should have failed to start with docker %v daemon %v", d.GlobalFlags, f[daemon]) 400 } 401 } 402 403 for _, f := range invalidGlobalFlags { 404 cmd := exec.Command(dockerBinary, append(f, "daemon")...) 405 errch := make(chan error) 406 var err error 407 go func() { 408 errch <- cmd.Run() 409 }() 410 select { 411 case <-time.After(time.Second): 412 cmd.Process.Kill() 413 case err = <-errch: 414 } 415 if err == nil { 416 c.Fatalf("Daemon should have failed to start with docker %v daemon", f) 417 } 418 } 419 } 420 421 func (s *DockerDaemonSuite) TestDaemonLogLevelDebug(c *check.C) { 422 if err := s.d.Start("--log-level=debug"); err != nil { 423 c.Fatal(err) 424 } 425 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 426 if !strings.Contains(string(content), `level=debug`) { 427 c.Fatalf(`Missing level="debug" in log file:\n%s`, string(content)) 428 } 429 } 430 431 func (s *DockerDaemonSuite) TestDaemonLogLevelFatal(c *check.C) { 432 // we creating new daemons to create new logFile 433 if err := s.d.Start("--log-level=fatal"); err != nil { 434 c.Fatal(err) 435 } 436 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 437 if strings.Contains(string(content), `level=debug`) { 438 c.Fatalf(`Should not have level="debug" in log file:\n%s`, string(content)) 439 } 440 } 441 442 func (s *DockerDaemonSuite) TestDaemonFlagD(c *check.C) { 443 if err := s.d.Start("-D"); err != nil { 444 c.Fatal(err) 445 } 446 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 447 if !strings.Contains(string(content), `level=debug`) { 448 c.Fatalf(`Should have level="debug" in log file using -D:\n%s`, string(content)) 449 } 450 } 451 452 func (s *DockerDaemonSuite) TestDaemonFlagDebug(c *check.C) { 453 if err := s.d.Start("--debug"); err != nil { 454 c.Fatal(err) 455 } 456 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 457 if !strings.Contains(string(content), `level=debug`) { 458 c.Fatalf(`Should have level="debug" in log file using --debug:\n%s`, string(content)) 459 } 460 } 461 462 func (s *DockerDaemonSuite) TestDaemonFlagDebugLogLevelFatal(c *check.C) { 463 if err := s.d.Start("--debug", "--log-level=fatal"); err != nil { 464 c.Fatal(err) 465 } 466 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 467 if !strings.Contains(string(content), `level=debug`) { 468 c.Fatalf(`Should have level="debug" in log file when using both --debug and --log-level=fatal:\n%s`, string(content)) 469 } 470 } 471 472 func (s *DockerDaemonSuite) TestDaemonAllocatesListeningPort(c *check.C) { 473 listeningPorts := [][]string{ 474 {"0.0.0.0", "0.0.0.0", "5678"}, 475 {"127.0.0.1", "127.0.0.1", "1234"}, 476 {"localhost", "127.0.0.1", "1235"}, 477 } 478 479 cmdArgs := make([]string, 0, len(listeningPorts)*2) 480 for _, hostDirective := range listeningPorts { 481 cmdArgs = append(cmdArgs, "--host", fmt.Sprintf("tcp://%s:%s", hostDirective[0], hostDirective[2])) 482 } 483 484 if err := s.d.StartWithBusybox(cmdArgs...); err != nil { 485 c.Fatalf("Could not start daemon with busybox: %v", err) 486 } 487 488 for _, hostDirective := range listeningPorts { 489 output, err := s.d.Cmd("run", "-p", fmt.Sprintf("%s:%s:80", hostDirective[1], hostDirective[2]), "busybox", "true") 490 if err == nil { 491 c.Fatalf("Container should not start, expected port already allocated error: %q", output) 492 } else if !strings.Contains(output, "port is already allocated") { 493 c.Fatalf("Expected port is already allocated error: %q", output) 494 } 495 } 496 } 497 498 func (s *DockerDaemonSuite) TestDaemonKeyGeneration(c *check.C) { 499 // TODO: skip or update for Windows daemon 500 os.Remove("/etc/docker/key.json") 501 if err := s.d.Start(); err != nil { 502 c.Fatalf("Could not start daemon: %v", err) 503 } 504 s.d.Stop() 505 506 k, err := libtrust.LoadKeyFile("/etc/docker/key.json") 507 if err != nil { 508 c.Fatalf("Error opening key file") 509 } 510 kid := k.KeyID() 511 // Test Key ID is a valid fingerprint (e.g. QQXN:JY5W:TBXI:MK3X:GX6P:PD5D:F56N:NHCS:LVRZ:JA46:R24J:XEFF) 512 if len(kid) != 59 { 513 c.Fatalf("Bad key ID: %s", kid) 514 } 515 } 516 517 func (s *DockerDaemonSuite) TestDaemonKeyMigration(c *check.C) { 518 // TODO: skip or update for Windows daemon 519 os.Remove("/etc/docker/key.json") 520 k1, err := libtrust.GenerateECP256PrivateKey() 521 if err != nil { 522 c.Fatalf("Error generating private key: %s", err) 523 } 524 if err := os.MkdirAll(filepath.Join(os.Getenv("HOME"), ".docker"), 0755); err != nil { 525 c.Fatalf("Error creating .docker directory: %s", err) 526 } 527 if err := libtrust.SaveKey(filepath.Join(os.Getenv("HOME"), ".docker", "key.json"), k1); err != nil { 528 c.Fatalf("Error saving private key: %s", err) 529 } 530 531 if err := s.d.Start(); err != nil { 532 c.Fatalf("Could not start daemon: %v", err) 533 } 534 s.d.Stop() 535 536 k2, err := libtrust.LoadKeyFile("/etc/docker/key.json") 537 if err != nil { 538 c.Fatalf("Error opening key file") 539 } 540 if k1.KeyID() != k2.KeyID() { 541 c.Fatalf("Key not migrated") 542 } 543 } 544 545 // GH#11320 - verify that the daemon exits on failure properly 546 // Note that this explicitly tests the conflict of {-b,--bridge} and {--bip} options as the means 547 // to get a daemon init failure; no other tests for -b/--bip conflict are therefore required 548 func (s *DockerDaemonSuite) TestDaemonExitOnFailure(c *check.C) { 549 //attempt to start daemon with incorrect flags (we know -b and --bip conflict) 550 if err := s.d.Start("--bridge", "nosuchbridge", "--bip", "1.1.1.1"); err != nil { 551 //verify we got the right error 552 if !strings.Contains(err.Error(), "Daemon exited and never started") { 553 c.Fatalf("Expected daemon not to start, got %v", err) 554 } 555 // look in the log and make sure we got the message that daemon is shutting down 556 runCmd := exec.Command("grep", "Error starting daemon", s.d.LogfileName()) 557 if out, _, err := runCommandWithOutput(runCmd); err != nil { 558 c.Fatalf("Expected 'Error starting daemon' message; but doesn't exist in log: %q, err: %v", out, err) 559 } 560 } else { 561 //if we didn't get an error and the daemon is running, this is a failure 562 c.Fatal("Conflicting options should cause the daemon to error out with a failure") 563 } 564 } 565 566 func (s *DockerDaemonSuite) TestDaemonBridgeExternal(c *check.C) { 567 d := s.d 568 err := d.Start("--bridge", "nosuchbridge") 569 c.Assert(err, check.NotNil, check.Commentf("--bridge option with an invalid bridge should cause the daemon to fail")) 570 defer d.Restart() 571 572 bridgeName := "external-bridge" 573 bridgeIP := "192.169.1.1/24" 574 _, bridgeIPNet, _ := net.ParseCIDR(bridgeIP) 575 576 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 577 c.Assert(err, check.IsNil, check.Commentf(out)) 578 defer deleteInterface(c, bridgeName) 579 580 err = d.StartWithBusybox("--bridge", bridgeName) 581 c.Assert(err, check.IsNil) 582 583 ipTablesSearchString := bridgeIPNet.String() 584 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 585 out, _, err = runCommandWithOutput(ipTablesCmd) 586 c.Assert(err, check.IsNil) 587 588 c.Assert(strings.Contains(out, ipTablesSearchString), check.Equals, true, 589 check.Commentf("iptables output should have contained %q, but was %q", 590 ipTablesSearchString, out)) 591 592 _, err = d.Cmd("run", "-d", "--name", "ExtContainer", "busybox", "top") 593 c.Assert(err, check.IsNil) 594 595 containerIP := d.findContainerIP("ExtContainer") 596 ip := net.ParseIP(containerIP) 597 c.Assert(bridgeIPNet.Contains(ip), check.Equals, true, 598 check.Commentf("Container IP-Address must be in the same subnet range : %s", 599 containerIP)) 600 } 601 602 func createInterface(c *check.C, ifType string, ifName string, ipNet string) (string, error) { 603 args := []string{"link", "add", "name", ifName, "type", ifType} 604 ipLinkCmd := exec.Command("ip", args...) 605 out, _, err := runCommandWithOutput(ipLinkCmd) 606 if err != nil { 607 return out, err 608 } 609 610 ifCfgCmd := exec.Command("ifconfig", ifName, ipNet, "up") 611 out, _, err = runCommandWithOutput(ifCfgCmd) 612 return out, err 613 } 614 615 func deleteInterface(c *check.C, ifName string) { 616 ifCmd := exec.Command("ip", "link", "delete", ifName) 617 out, _, err := runCommandWithOutput(ifCmd) 618 c.Assert(err, check.IsNil, check.Commentf(out)) 619 620 flushCmd := exec.Command("iptables", "-t", "nat", "--flush") 621 out, _, err = runCommandWithOutput(flushCmd) 622 c.Assert(err, check.IsNil, check.Commentf(out)) 623 624 flushCmd = exec.Command("iptables", "--flush") 625 out, _, err = runCommandWithOutput(flushCmd) 626 c.Assert(err, check.IsNil, check.Commentf(out)) 627 } 628 629 func (s *DockerDaemonSuite) TestDaemonBridgeIP(c *check.C) { 630 // TestDaemonBridgeIP Steps 631 // 1. Delete the existing docker0 Bridge 632 // 2. Set --bip daemon configuration and start the new Docker Daemon 633 // 3. Check if the bip config has taken effect using ifconfig and iptables commands 634 // 4. Launch a Container and make sure the IP-Address is in the expected subnet 635 // 5. Delete the docker0 Bridge 636 // 6. Restart the Docker Daemon (via defered action) 637 // This Restart takes care of bringing docker0 interface back to auto-assigned IP 638 639 defaultNetworkBridge := "docker0" 640 deleteInterface(c, defaultNetworkBridge) 641 642 d := s.d 643 644 bridgeIP := "192.169.1.1/24" 645 ip, bridgeIPNet, _ := net.ParseCIDR(bridgeIP) 646 647 err := d.StartWithBusybox("--bip", bridgeIP) 648 c.Assert(err, check.IsNil) 649 defer d.Restart() 650 651 ifconfigSearchString := ip.String() 652 ifconfigCmd := exec.Command("ifconfig", defaultNetworkBridge) 653 out, _, _, err := runCommandWithStdoutStderr(ifconfigCmd) 654 c.Assert(err, check.IsNil) 655 656 c.Assert(strings.Contains(out, ifconfigSearchString), check.Equals, true, 657 check.Commentf("ifconfig output should have contained %q, but was %q", 658 ifconfigSearchString, out)) 659 660 ipTablesSearchString := bridgeIPNet.String() 661 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 662 out, _, err = runCommandWithOutput(ipTablesCmd) 663 c.Assert(err, check.IsNil) 664 665 c.Assert(strings.Contains(out, ipTablesSearchString), check.Equals, true, 666 check.Commentf("iptables output should have contained %q, but was %q", 667 ipTablesSearchString, out)) 668 669 out, err = d.Cmd("run", "-d", "--name", "test", "busybox", "top") 670 c.Assert(err, check.IsNil) 671 672 containerIP := d.findContainerIP("test") 673 ip = net.ParseIP(containerIP) 674 c.Assert(bridgeIPNet.Contains(ip), check.Equals, true, 675 check.Commentf("Container IP-Address must be in the same subnet range : %s", 676 containerIP)) 677 deleteInterface(c, defaultNetworkBridge) 678 } 679 680 func (s *DockerDaemonSuite) TestDaemonRestartWithBridgeIPChange(c *check.C) { 681 if err := s.d.Start(); err != nil { 682 c.Fatalf("Could not start daemon: %v", err) 683 } 684 defer s.d.Restart() 685 if err := s.d.Stop(); err != nil { 686 c.Fatalf("Could not stop daemon: %v", err) 687 } 688 689 // now we will change the docker0's IP and then try starting the daemon 690 bridgeIP := "192.169.100.1/24" 691 _, bridgeIPNet, _ := net.ParseCIDR(bridgeIP) 692 693 ipCmd := exec.Command("ifconfig", "docker0", bridgeIP) 694 stdout, stderr, _, err := runCommandWithStdoutStderr(ipCmd) 695 if err != nil { 696 c.Fatalf("failed to change docker0's IP association: %v, stdout: %q, stderr: %q", err, stdout, stderr) 697 } 698 699 if err := s.d.Start("--bip", bridgeIP); err != nil { 700 c.Fatalf("Could not start daemon: %v", err) 701 } 702 703 //check if the iptables contains new bridgeIP MASQUERADE rule 704 ipTablesSearchString := bridgeIPNet.String() 705 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 706 out, _, err := runCommandWithOutput(ipTablesCmd) 707 if err != nil { 708 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 709 } 710 if !strings.Contains(out, ipTablesSearchString) { 711 c.Fatalf("iptables output should have contained new MASQUERADE rule with IP %q, but was %q", ipTablesSearchString, out) 712 } 713 } 714 715 func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr(c *check.C) { 716 d := s.d 717 718 bridgeName := "external-bridge" 719 bridgeIP := "192.169.1.1/24" 720 721 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 722 c.Assert(err, check.IsNil, check.Commentf(out)) 723 defer deleteInterface(c, bridgeName) 724 725 args := []string{"--bridge", bridgeName, "--fixed-cidr", "192.169.1.0/30"} 726 err = d.StartWithBusybox(args...) 727 c.Assert(err, check.IsNil) 728 defer d.Restart() 729 730 for i := 0; i < 4; i++ { 731 cName := "Container" + strconv.Itoa(i) 732 out, err := d.Cmd("run", "-d", "--name", cName, "busybox", "top") 733 if err != nil { 734 c.Assert(strings.Contains(out, "no available ip addresses"), check.Equals, true, 735 check.Commentf("Could not run a Container : %s %s", err.Error(), out)) 736 } 737 } 738 } 739 740 func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4Implicit(c *check.C) { 741 defaultNetworkBridge := "docker0" 742 deleteInterface(c, defaultNetworkBridge) 743 744 d := s.d 745 746 bridgeIP := "192.169.1.1" 747 bridgeIPNet := fmt.Sprintf("%s/24", bridgeIP) 748 749 err := d.StartWithBusybox("--bip", bridgeIPNet) 750 c.Assert(err, check.IsNil) 751 defer d.Restart() 752 753 expectedMessage := fmt.Sprintf("default via %s dev", bridgeIP) 754 out, err := d.Cmd("run", "busybox", "ip", "-4", "route", "list", "0/0") 755 c.Assert(strings.Contains(out, expectedMessage), check.Equals, true, 756 check.Commentf("Implicit default gateway should be bridge IP %s, but default route was '%s'", 757 bridgeIP, strings.TrimSpace(out))) 758 deleteInterface(c, defaultNetworkBridge) 759 } 760 761 func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4Explicit(c *check.C) { 762 defaultNetworkBridge := "docker0" 763 deleteInterface(c, defaultNetworkBridge) 764 765 d := s.d 766 767 bridgeIP := "192.169.1.1" 768 bridgeIPNet := fmt.Sprintf("%s/24", bridgeIP) 769 gatewayIP := "192.169.1.254" 770 771 err := d.StartWithBusybox("--bip", bridgeIPNet, "--default-gateway", gatewayIP) 772 c.Assert(err, check.IsNil) 773 defer d.Restart() 774 775 expectedMessage := fmt.Sprintf("default via %s dev", gatewayIP) 776 out, err := d.Cmd("run", "busybox", "ip", "-4", "route", "list", "0/0") 777 c.Assert(strings.Contains(out, expectedMessage), check.Equals, true, 778 check.Commentf("Explicit default gateway should be %s, but default route was '%s'", 779 gatewayIP, strings.TrimSpace(out))) 780 deleteInterface(c, defaultNetworkBridge) 781 } 782 783 func (s *DockerDaemonSuite) TestDaemonIP(c *check.C) { 784 d := s.d 785 786 ipStr := "192.170.1.1/24" 787 ip, _, _ := net.ParseCIDR(ipStr) 788 args := []string{"--ip", ip.String()} 789 err := d.StartWithBusybox(args...) 790 c.Assert(err, check.IsNil) 791 defer d.Restart() 792 793 out, err := d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top") 794 c.Assert(err, check.NotNil, 795 check.Commentf("Running a container must fail with an invalid --ip option")) 796 c.Assert(strings.Contains(out, "Error starting userland proxy"), check.Equals, true) 797 798 ifName := "dummy" 799 out, err = createInterface(c, "dummy", ifName, ipStr) 800 c.Assert(err, check.IsNil, check.Commentf(out)) 801 defer deleteInterface(c, ifName) 802 803 _, err = d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top") 804 c.Assert(err, check.IsNil) 805 806 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 807 out, _, err = runCommandWithOutput(ipTablesCmd) 808 c.Assert(err, check.IsNil) 809 810 regex := fmt.Sprintf("DNAT.*%s.*dpt:8000", ip.String()) 811 matched, _ := regexp.MatchString(regex, out) 812 c.Assert(matched, check.Equals, true, 813 check.Commentf("iptables output should have contained %q, but was %q", regex, out)) 814 } 815 816 func (s *DockerDaemonSuite) TestDaemonICCPing(c *check.C) { 817 d := s.d 818 819 bridgeName := "external-bridge" 820 bridgeIP := "192.169.1.1/24" 821 822 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 823 c.Assert(err, check.IsNil, check.Commentf(out)) 824 defer deleteInterface(c, bridgeName) 825 826 args := []string{"--bridge", bridgeName, "--icc=false"} 827 err = d.StartWithBusybox(args...) 828 c.Assert(err, check.IsNil) 829 defer d.Restart() 830 831 ipTablesCmd := exec.Command("iptables", "-nvL", "FORWARD") 832 out, _, err = runCommandWithOutput(ipTablesCmd) 833 c.Assert(err, check.IsNil) 834 835 regex := fmt.Sprintf("DROP.*all.*%s.*%s", bridgeName, bridgeName) 836 matched, _ := regexp.MatchString(regex, out) 837 c.Assert(matched, check.Equals, true, 838 check.Commentf("iptables output should have contained %q, but was %q", regex, out)) 839 840 // Pinging another container must fail with --icc=false 841 pingContainers(c, d, true) 842 843 ipStr := "192.171.1.1/24" 844 ip, _, _ := net.ParseCIDR(ipStr) 845 ifName := "icc-dummy" 846 847 createInterface(c, "dummy", ifName, ipStr) 848 849 // But, Pinging external or a Host interface must succeed 850 pingCmd := fmt.Sprintf("ping -c 1 %s -W 1", ip.String()) 851 runArgs := []string{"--rm", "busybox", "sh", "-c", pingCmd} 852 _, err = d.Cmd("run", runArgs...) 853 c.Assert(err, check.IsNil) 854 } 855 856 func (s *DockerDaemonSuite) TestDaemonICCLinkExpose(c *check.C) { 857 d := s.d 858 859 bridgeName := "external-bridge" 860 bridgeIP := "192.169.1.1/24" 861 862 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 863 c.Assert(err, check.IsNil, check.Commentf(out)) 864 defer deleteInterface(c, bridgeName) 865 866 args := []string{"--bridge", bridgeName, "--icc=false"} 867 err = d.StartWithBusybox(args...) 868 c.Assert(err, check.IsNil) 869 defer d.Restart() 870 871 ipTablesCmd := exec.Command("iptables", "-nvL", "FORWARD") 872 out, _, err = runCommandWithOutput(ipTablesCmd) 873 c.Assert(err, check.IsNil) 874 875 regex := fmt.Sprintf("DROP.*all.*%s.*%s", bridgeName, bridgeName) 876 matched, _ := regexp.MatchString(regex, out) 877 c.Assert(matched, check.Equals, true, 878 check.Commentf("iptables output should have contained %q, but was %q", regex, out)) 879 880 out, err = d.Cmd("run", "-d", "--expose", "4567", "--name", "icc1", "busybox", "nc", "-l", "-p", "4567") 881 c.Assert(err, check.IsNil, check.Commentf(out)) 882 883 out, err = d.Cmd("run", "--link", "icc1:icc1", "busybox", "nc", "icc1", "4567") 884 c.Assert(err, check.IsNil, check.Commentf(out)) 885 } 886 887 func (s *DockerDaemonSuite) TestDaemonLinksIpTablesRulesWhenLinkAndUnlink(c *check.C) { 888 bridgeName := "external-bridge" 889 bridgeIP := "192.169.1.1/24" 890 891 out, err := createInterface(c, "bridge", bridgeName, bridgeIP) 892 c.Assert(err, check.IsNil, check.Commentf(out)) 893 defer deleteInterface(c, bridgeName) 894 895 err = s.d.StartWithBusybox("--bridge", bridgeName, "--icc=false") 896 c.Assert(err, check.IsNil) 897 defer s.d.Restart() 898 899 _, err = s.d.Cmd("run", "-d", "--name", "child", "--publish", "8080:80", "busybox", "top") 900 c.Assert(err, check.IsNil) 901 _, err = s.d.Cmd("run", "-d", "--name", "parent", "--link", "child:http", "busybox", "top") 902 c.Assert(err, check.IsNil) 903 904 childIP := s.d.findContainerIP("child") 905 parentIP := s.d.findContainerIP("parent") 906 907 sourceRule := []string{"-i", bridgeName, "-o", bridgeName, "-p", "tcp", "-s", childIP, "--sport", "80", "-d", parentIP, "-j", "ACCEPT"} 908 destinationRule := []string{"-i", bridgeName, "-o", bridgeName, "-p", "tcp", "-s", parentIP, "--dport", "80", "-d", childIP, "-j", "ACCEPT"} 909 if !iptables.Exists("filter", "DOCKER", sourceRule...) || !iptables.Exists("filter", "DOCKER", destinationRule...) { 910 c.Fatal("Iptables rules not found") 911 } 912 913 s.d.Cmd("rm", "--link", "parent/http") 914 if iptables.Exists("filter", "DOCKER", sourceRule...) || iptables.Exists("filter", "DOCKER", destinationRule...) { 915 c.Fatal("Iptables rules should be removed when unlink") 916 } 917 918 s.d.Cmd("kill", "child") 919 s.d.Cmd("kill", "parent") 920 } 921 922 func (s *DockerDaemonSuite) TestDaemonUlimitDefaults(c *check.C) { 923 testRequires(c, NativeExecDriver) 924 925 if err := s.d.StartWithBusybox("--default-ulimit", "nofile=42:42", "--default-ulimit", "nproc=1024:1024"); err != nil { 926 c.Fatal(err) 927 } 928 929 out, err := s.d.Cmd("run", "--ulimit", "nproc=2048", "--name=test", "busybox", "/bin/sh", "-c", "echo $(ulimit -n); echo $(ulimit -p)") 930 if err != nil { 931 c.Fatal(out, err) 932 } 933 934 outArr := strings.Split(out, "\n") 935 if len(outArr) < 2 { 936 c.Fatalf("got unexpected output: %s", out) 937 } 938 nofile := strings.TrimSpace(outArr[0]) 939 nproc := strings.TrimSpace(outArr[1]) 940 941 if nofile != "42" { 942 c.Fatalf("expected `ulimit -n` to be `42`, got: %s", nofile) 943 } 944 if nproc != "2048" { 945 c.Fatalf("exepcted `ulimit -p` to be 2048, got: %s", nproc) 946 } 947 948 // Now restart daemon with a new default 949 if err := s.d.Restart("--default-ulimit", "nofile=43"); err != nil { 950 c.Fatal(err) 951 } 952 953 out, err = s.d.Cmd("start", "-a", "test") 954 if err != nil { 955 c.Fatal(err) 956 } 957 958 outArr = strings.Split(out, "\n") 959 if len(outArr) < 2 { 960 c.Fatalf("got unexpected output: %s", out) 961 } 962 nofile = strings.TrimSpace(outArr[0]) 963 nproc = strings.TrimSpace(outArr[1]) 964 965 if nofile != "43" { 966 c.Fatalf("expected `ulimit -n` to be `43`, got: %s", nofile) 967 } 968 if nproc != "2048" { 969 c.Fatalf("exepcted `ulimit -p` to be 2048, got: %s", nproc) 970 } 971 } 972 973 // #11315 974 func (s *DockerDaemonSuite) TestDaemonRestartRenameContainer(c *check.C) { 975 if err := s.d.StartWithBusybox(); err != nil { 976 c.Fatal(err) 977 } 978 979 if out, err := s.d.Cmd("run", "--name=test", "busybox"); err != nil { 980 c.Fatal(err, out) 981 } 982 983 if out, err := s.d.Cmd("rename", "test", "test2"); err != nil { 984 c.Fatal(err, out) 985 } 986 987 if err := s.d.Restart(); err != nil { 988 c.Fatal(err) 989 } 990 991 if out, err := s.d.Cmd("start", "test2"); err != nil { 992 c.Fatal(err, out) 993 } 994 } 995 996 func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefault(c *check.C) { 997 if err := s.d.StartWithBusybox(); err != nil { 998 c.Fatal(err) 999 } 1000 1001 out, err := s.d.Cmd("run", "-d", "busybox", "echo", "testline") 1002 if err != nil { 1003 c.Fatal(out, err) 1004 } 1005 id := strings.TrimSpace(out) 1006 1007 if out, err := s.d.Cmd("wait", id); err != nil { 1008 c.Fatal(out, err) 1009 } 1010 logPath := filepath.Join(s.d.folder, "graph", "containers", id, id+"-json.log") 1011 1012 if _, err := os.Stat(logPath); err != nil { 1013 c.Fatal(err) 1014 } 1015 f, err := os.Open(logPath) 1016 if err != nil { 1017 c.Fatal(err) 1018 } 1019 var res struct { 1020 Log string `json:"log"` 1021 Stream string `json:"stream"` 1022 Time time.Time `json:"time"` 1023 } 1024 if err := json.NewDecoder(f).Decode(&res); err != nil { 1025 c.Fatal(err) 1026 } 1027 if res.Log != "testline\n" { 1028 c.Fatalf("Unexpected log line: %q, expected: %q", res.Log, "testline\n") 1029 } 1030 if res.Stream != "stdout" { 1031 c.Fatalf("Unexpected stream: %q, expected: %q", res.Stream, "stdout") 1032 } 1033 if !time.Now().After(res.Time) { 1034 c.Fatalf("Log time %v in future", res.Time) 1035 } 1036 } 1037 1038 func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefaultOverride(c *check.C) { 1039 if err := s.d.StartWithBusybox(); err != nil { 1040 c.Fatal(err) 1041 } 1042 1043 out, err := s.d.Cmd("run", "-d", "--log-driver=none", "busybox", "echo", "testline") 1044 if err != nil { 1045 c.Fatal(out, err) 1046 } 1047 id := strings.TrimSpace(out) 1048 1049 if out, err := s.d.Cmd("wait", id); err != nil { 1050 c.Fatal(out, err) 1051 } 1052 logPath := filepath.Join(s.d.folder, "graph", "containers", id, id+"-json.log") 1053 1054 if _, err := os.Stat(logPath); err == nil || !os.IsNotExist(err) { 1055 c.Fatalf("%s shouldn't exits, error on Stat: %s", logPath, err) 1056 } 1057 } 1058 1059 func (s *DockerDaemonSuite) TestDaemonLoggingDriverNone(c *check.C) { 1060 if err := s.d.StartWithBusybox("--log-driver=none"); err != nil { 1061 c.Fatal(err) 1062 } 1063 1064 out, err := s.d.Cmd("run", "-d", "busybox", "echo", "testline") 1065 if err != nil { 1066 c.Fatal(out, err) 1067 } 1068 id := strings.TrimSpace(out) 1069 if out, err := s.d.Cmd("wait", id); err != nil { 1070 c.Fatal(out, err) 1071 } 1072 1073 logPath := filepath.Join(s.d.folder, "graph", "containers", id, id+"-json.log") 1074 1075 if _, err := os.Stat(logPath); err == nil || !os.IsNotExist(err) { 1076 c.Fatalf("%s shouldn't exits, error on Stat: %s", logPath, err) 1077 } 1078 } 1079 1080 func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneOverride(c *check.C) { 1081 if err := s.d.StartWithBusybox("--log-driver=none"); err != nil { 1082 c.Fatal(err) 1083 } 1084 1085 out, err := s.d.Cmd("run", "-d", "--log-driver=json-file", "busybox", "echo", "testline") 1086 if err != nil { 1087 c.Fatal(out, err) 1088 } 1089 id := strings.TrimSpace(out) 1090 1091 if out, err := s.d.Cmd("wait", id); err != nil { 1092 c.Fatal(out, err) 1093 } 1094 logPath := filepath.Join(s.d.folder, "graph", "containers", id, id+"-json.log") 1095 1096 if _, err := os.Stat(logPath); err != nil { 1097 c.Fatal(err) 1098 } 1099 f, err := os.Open(logPath) 1100 if err != nil { 1101 c.Fatal(err) 1102 } 1103 var res struct { 1104 Log string `json:"log"` 1105 Stream string `json:"stream"` 1106 Time time.Time `json:"time"` 1107 } 1108 if err := json.NewDecoder(f).Decode(&res); err != nil { 1109 c.Fatal(err) 1110 } 1111 if res.Log != "testline\n" { 1112 c.Fatalf("Unexpected log line: %q, expected: %q", res.Log, "testline\n") 1113 } 1114 if res.Stream != "stdout" { 1115 c.Fatalf("Unexpected stream: %q, expected: %q", res.Stream, "stdout") 1116 } 1117 if !time.Now().After(res.Time) { 1118 c.Fatalf("Log time %v in future", res.Time) 1119 } 1120 } 1121 1122 func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneLogsError(c *check.C) { 1123 if err := s.d.StartWithBusybox("--log-driver=none"); err != nil { 1124 c.Fatal(err) 1125 } 1126 1127 out, err := s.d.Cmd("run", "-d", "busybox", "echo", "testline") 1128 if err != nil { 1129 c.Fatal(out, err) 1130 } 1131 id := strings.TrimSpace(out) 1132 out, err = s.d.Cmd("logs", id) 1133 if err == nil { 1134 c.Fatalf("Logs should fail with \"none\" driver") 1135 } 1136 if !strings.Contains(out, `"logs" command is supported only for "json-file" logging driver`) { 1137 c.Fatalf("There should be error about non-json-file driver, got: %s", out) 1138 } 1139 } 1140 1141 func (s *DockerDaemonSuite) TestDaemonDots(c *check.C) { 1142 if err := s.d.StartWithBusybox(); err != nil { 1143 c.Fatal(err) 1144 } 1145 1146 // Now create 4 containers 1147 if _, err := s.d.Cmd("create", "busybox"); err != nil { 1148 c.Fatalf("Error creating container: %q", err) 1149 } 1150 if _, err := s.d.Cmd("create", "busybox"); err != nil { 1151 c.Fatalf("Error creating container: %q", err) 1152 } 1153 if _, err := s.d.Cmd("create", "busybox"); err != nil { 1154 c.Fatalf("Error creating container: %q", err) 1155 } 1156 if _, err := s.d.Cmd("create", "busybox"); err != nil { 1157 c.Fatalf("Error creating container: %q", err) 1158 } 1159 1160 s.d.Stop() 1161 1162 s.d.Start("--log-level=debug") 1163 s.d.Stop() 1164 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 1165 if strings.Contains(string(content), "....") { 1166 c.Fatalf("Debug level should not have ....\n%s", string(content)) 1167 } 1168 1169 s.d.Start("--log-level=error") 1170 s.d.Stop() 1171 content, _ = ioutil.ReadFile(s.d.logFile.Name()) 1172 if strings.Contains(string(content), "....") { 1173 c.Fatalf("Error level should not have ....\n%s", string(content)) 1174 } 1175 1176 s.d.Start("--log-level=info") 1177 s.d.Stop() 1178 content, _ = ioutil.ReadFile(s.d.logFile.Name()) 1179 if !strings.Contains(string(content), "....") { 1180 c.Fatalf("Info level should have ....\n%s", string(content)) 1181 } 1182 } 1183 1184 func (s *DockerDaemonSuite) TestDaemonUnixSockCleanedUp(c *check.C) { 1185 dir, err := ioutil.TempDir("", "socket-cleanup-test") 1186 if err != nil { 1187 c.Fatal(err) 1188 } 1189 defer os.RemoveAll(dir) 1190 1191 sockPath := filepath.Join(dir, "docker.sock") 1192 if err := s.d.Start("--host", "unix://"+sockPath); err != nil { 1193 c.Fatal(err) 1194 } 1195 1196 if _, err := os.Stat(sockPath); err != nil { 1197 c.Fatal("socket does not exist") 1198 } 1199 1200 if err := s.d.Stop(); err != nil { 1201 c.Fatal(err) 1202 } 1203 1204 if _, err := os.Stat(sockPath); err == nil || !os.IsNotExist(err) { 1205 c.Fatal("unix socket is not cleaned up") 1206 } 1207 } 1208 1209 func (s *DockerDaemonSuite) TestDaemonWithWrongkey(c *check.C) { 1210 type Config struct { 1211 Crv string `json:"crv"` 1212 D string `json:"d"` 1213 Kid string `json:"kid"` 1214 Kty string `json:"kty"` 1215 X string `json:"x"` 1216 Y string `json:"y"` 1217 } 1218 1219 os.Remove("/etc/docker/key.json") 1220 if err := s.d.Start(); err != nil { 1221 c.Fatalf("Failed to start daemon: %v", err) 1222 } 1223 1224 if err := s.d.Stop(); err != nil { 1225 c.Fatalf("Could not stop daemon: %v", err) 1226 } 1227 1228 config := &Config{} 1229 bytes, err := ioutil.ReadFile("/etc/docker/key.json") 1230 if err != nil { 1231 c.Fatalf("Error reading key.json file: %s", err) 1232 } 1233 1234 // byte[] to Data-Struct 1235 if err := json.Unmarshal(bytes, &config); err != nil { 1236 c.Fatalf("Error Unmarshal: %s", err) 1237 } 1238 1239 //replace config.Kid with the fake value 1240 config.Kid = "VSAJ:FUYR:X3H2:B2VZ:KZ6U:CJD5:K7BX:ZXHY:UZXT:P4FT:MJWG:HRJ4" 1241 1242 // NEW Data-Struct to byte[] 1243 newBytes, err := json.Marshal(&config) 1244 if err != nil { 1245 c.Fatalf("Error Marshal: %s", err) 1246 } 1247 1248 // write back 1249 if err := ioutil.WriteFile("/etc/docker/key.json", newBytes, 0400); err != nil { 1250 c.Fatalf("Error ioutil.WriteFile: %s", err) 1251 } 1252 1253 defer os.Remove("/etc/docker/key.json") 1254 1255 if err := s.d.Start(); err == nil { 1256 c.Fatalf("It should not be successful to start daemon with wrong key: %v", err) 1257 } 1258 1259 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 1260 1261 if !strings.Contains(string(content), "Public Key ID does not match") { 1262 c.Fatal("Missing KeyID message from daemon logs") 1263 } 1264 } 1265 1266 func (s *DockerDaemonSuite) TestDaemonRestartKillWait(c *check.C) { 1267 if err := s.d.StartWithBusybox(); err != nil { 1268 c.Fatalf("Could not start daemon with busybox: %v", err) 1269 } 1270 1271 out, err := s.d.Cmd("run", "-id", "busybox", "/bin/cat") 1272 if err != nil { 1273 c.Fatalf("Could not run /bin/cat: err=%v\n%s", err, out) 1274 } 1275 containerID := strings.TrimSpace(out) 1276 1277 if out, err := s.d.Cmd("kill", containerID); err != nil { 1278 c.Fatalf("Could not kill %s: err=%v\n%s", containerID, err, out) 1279 } 1280 1281 if err := s.d.Restart(); err != nil { 1282 c.Fatalf("Could not restart daemon: %v", err) 1283 } 1284 1285 errchan := make(chan error) 1286 go func() { 1287 if out, err := s.d.Cmd("wait", containerID); err != nil { 1288 errchan <- fmt.Errorf("%v:\n%s", err, out) 1289 } 1290 close(errchan) 1291 }() 1292 1293 select { 1294 case <-time.After(5 * time.Second): 1295 c.Fatal("Waiting on a stopped (killed) container timed out") 1296 case err := <-errchan: 1297 if err != nil { 1298 c.Fatal(err) 1299 } 1300 } 1301 } 1302 1303 // TestHttpsInfo connects via two-way authenticated HTTPS to the info endpoint 1304 func (s *DockerDaemonSuite) TestHttpsInfo(c *check.C) { 1305 const ( 1306 testDaemonHTTPSAddr = "tcp://localhost:4271" 1307 ) 1308 1309 if err := s.d.Start("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-cert.pem", 1310 "--tlskey", "fixtures/https/server-key.pem", "-H", testDaemonHTTPSAddr); err != nil { 1311 c.Fatalf("Could not start daemon with busybox: %v", err) 1312 } 1313 1314 daemonArgs := []string{"--host", testDaemonHTTPSAddr, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/client-cert.pem", "--tlskey", "fixtures/https/client-key.pem"} 1315 out, err := s.d.CmdWithArgs(daemonArgs, "info") 1316 if err != nil { 1317 c.Fatalf("Error Occurred: %s and output: %s", err, out) 1318 } 1319 } 1320 1321 // TestHttpsInfoRogueCert connects via two-way authenticated HTTPS to the info endpoint 1322 // by using a rogue client certificate and checks that it fails with the expected error. 1323 func (s *DockerDaemonSuite) TestHttpsInfoRogueCert(c *check.C) { 1324 const ( 1325 errBadCertificate = "remote error: bad certificate" 1326 testDaemonHTTPSAddr = "tcp://localhost:4271" 1327 ) 1328 1329 if err := s.d.Start("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-cert.pem", 1330 "--tlskey", "fixtures/https/server-key.pem", "-H", testDaemonHTTPSAddr); err != nil { 1331 c.Fatalf("Could not start daemon with busybox: %v", err) 1332 } 1333 1334 daemonArgs := []string{"--host", testDaemonHTTPSAddr, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/client-rogue-cert.pem", "--tlskey", "fixtures/https/client-rogue-key.pem"} 1335 out, err := s.d.CmdWithArgs(daemonArgs, "info") 1336 if err == nil || !strings.Contains(out, errBadCertificate) { 1337 c.Fatalf("Expected err: %s, got instead: %s and output: %s", errBadCertificate, err, out) 1338 } 1339 } 1340 1341 // TestHttpsInfoRogueServerCert connects via two-way authenticated HTTPS to the info endpoint 1342 // which provides a rogue server certificate and checks that it fails with the expected error 1343 func (s *DockerDaemonSuite) TestHttpsInfoRogueServerCert(c *check.C) { 1344 const ( 1345 errCaUnknown = "x509: certificate signed by unknown authority" 1346 testDaemonRogueHTTPSAddr = "tcp://localhost:4272" 1347 ) 1348 if err := s.d.Start("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-rogue-cert.pem", 1349 "--tlskey", "fixtures/https/server-rogue-key.pem", "-H", testDaemonRogueHTTPSAddr); err != nil { 1350 c.Fatalf("Could not start daemon with busybox: %v", err) 1351 } 1352 1353 daemonArgs := []string{"--host", testDaemonRogueHTTPSAddr, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/client-rogue-cert.pem", "--tlskey", "fixtures/https/client-rogue-key.pem"} 1354 out, err := s.d.CmdWithArgs(daemonArgs, "info") 1355 if err == nil || !strings.Contains(out, errCaUnknown) { 1356 c.Fatalf("Expected err: %s, got instead: %s and output: %s", errCaUnknown, err, out) 1357 } 1358 } 1359 1360 func pingContainers(c *check.C, d *Daemon, expectFailure bool) { 1361 var dargs []string 1362 if d != nil { 1363 dargs = []string{"--host", d.sock()} 1364 } 1365 1366 args := append(dargs, "run", "-d", "--name", "container1", "busybox", "top") 1367 dockerCmd(c, args...) 1368 1369 args = append(dargs, "run", "--rm", "--link", "container1:alias1", "busybox", "sh", "-c") 1370 pingCmd := "ping -c 1 %s -W 1" 1371 args = append(args, fmt.Sprintf(pingCmd, "alias1")) 1372 _, _, err := dockerCmdWithError(c, args...) 1373 1374 if expectFailure { 1375 c.Assert(err, check.NotNil) 1376 } else { 1377 c.Assert(err, check.IsNil) 1378 } 1379 1380 args = append(dargs, "rm", "-f", "container1") 1381 dockerCmd(c, args...) 1382 } 1383 1384 func (s *DockerDaemonSuite) TestDaemonRestartWithSocketAsVolume(c *check.C) { 1385 c.Assert(s.d.StartWithBusybox(), check.IsNil) 1386 1387 socket := filepath.Join(s.d.folder, "docker.sock") 1388 1389 out, err := s.d.Cmd("run", "-d", "-v", socket+":/sock", "busybox") 1390 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1391 c.Assert(s.d.Restart(), check.IsNil) 1392 } 1393 1394 func (s *DockerDaemonSuite) TestCleanupMountsAfterCrash(c *check.C) { 1395 c.Assert(s.d.StartWithBusybox(), check.IsNil) 1396 1397 out, err := s.d.Cmd("run", "-d", "busybox", "top") 1398 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1399 id := strings.TrimSpace(out) 1400 c.Assert(s.d.cmd.Process.Signal(os.Kill), check.IsNil) 1401 c.Assert(s.d.Start(), check.IsNil) 1402 mountOut, err := exec.Command("mount").CombinedOutput() 1403 c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut)) 1404 c.Assert(strings.Contains(string(mountOut), id), check.Equals, false, check.Commentf("Something mounted from older daemon start: %s", mountOut)) 1405 } 1406 1407 func (s *DockerDaemonSuite) TestRunContainerWithBridgeNone(c *check.C) { 1408 testRequires(c, NativeExecDriver) 1409 c.Assert(s.d.StartWithBusybox("-b", "none"), check.IsNil) 1410 1411 out, err := s.d.Cmd("run", "--rm", "busybox", "ip", "l") 1412 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1413 c.Assert(strings.Contains(out, "eth0"), check.Equals, false, 1414 check.Commentf("There shouldn't be eth0 in container in default(bridge) mode when bridge network is disabled: %s", out)) 1415 1416 out, err = s.d.Cmd("run", "--rm", "--net=bridge", "busybox", "ip", "l") 1417 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1418 c.Assert(strings.Contains(out, "eth0"), check.Equals, false, 1419 check.Commentf("There shouldn't be eth0 in container in bridge mode when bridge network is disabled: %s", out)) 1420 1421 out, err = s.d.Cmd("run", "--rm", "--net=host", "busybox", "ip", "l") 1422 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1423 c.Assert(strings.Contains(out, "eth0"), check.Equals, true, 1424 check.Commentf("There should be eth0 in container when --net=host when bridge network is disabled: %s", out)) 1425 } 1426 1427 func (s *DockerDaemonSuite) TestDaemonRestartWithContainerRunning(t *check.C) { 1428 if err := s.d.StartWithBusybox(); err != nil { 1429 t.Fatal(err) 1430 } 1431 if out, err := s.d.Cmd("run", "-ti", "-d", "--name", "test", "busybox"); err != nil { 1432 t.Fatal(out, err) 1433 } 1434 1435 if err := s.d.Restart(); err != nil { 1436 t.Fatal(err) 1437 } 1438 // Container 'test' should be removed without error 1439 if out, err := s.d.Cmd("rm", "test"); err != nil { 1440 t.Fatal(out, err) 1441 } 1442 } 1443 1444 func (s *DockerDaemonSuite) TestDaemonRestartCleanupNetns(c *check.C) { 1445 if err := s.d.StartWithBusybox(); err != nil { 1446 c.Fatal(err) 1447 } 1448 out, err := s.d.Cmd("run", "--name", "netns", "-d", "busybox", "top") 1449 if err != nil { 1450 c.Fatal(out, err) 1451 } 1452 if out, err := s.d.Cmd("stop", "netns"); err != nil { 1453 c.Fatal(out, err) 1454 } 1455 1456 // Construct netns file name from container id 1457 out = strings.TrimSpace(out) 1458 nsFile := out[:12] 1459 1460 // Test if the file still exists 1461 out, _, err = runCommandWithOutput(exec.Command("stat", "-c", "%n", "/var/run/docker/netns/"+nsFile)) 1462 out = strings.TrimSpace(out) 1463 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1464 c.Assert(out, check.Equals, "/var/run/docker/netns/"+nsFile, check.Commentf("Output: %s", out)) 1465 1466 // Remove the container and restart the daemon 1467 if out, err := s.d.Cmd("rm", "netns"); err != nil { 1468 c.Fatal(out, err) 1469 } 1470 1471 if err := s.d.Restart(); err != nil { 1472 c.Fatal(err) 1473 } 1474 1475 // Test again and see now the netns file does not exist 1476 out, _, err = runCommandWithOutput(exec.Command("stat", "-c", "%n", "/var/run/docker/netns/"+nsFile)) 1477 out = strings.TrimSpace(out) 1478 c.Assert(err, check.Not(check.IsNil), check.Commentf("Output: %s", out)) 1479 // c.Assert(out, check.Equals, "", check.Commentf("Output: %s", out)) 1480 } 1481 1482 // tests regression detailed in #13964 where DOCKER_TLS_VERIFY env is ignored 1483 func (s *DockerDaemonSuite) TestDaemonNoTlsCliTlsVerifyWithEnv(c *check.C) { 1484 host := "tcp://localhost:4271" 1485 c.Assert(s.d.Start("-H", host), check.IsNil) 1486 cmd := exec.Command(dockerBinary, "-H", host, "info") 1487 cmd.Env = []string{"DOCKER_TLS_VERIFY=1", "DOCKER_CERT_PATH=fixtures/https"} 1488 out, _, err := runCommandWithOutput(cmd) 1489 c.Assert(err, check.Not(check.IsNil), check.Commentf("%s", out)) 1490 c.Assert(strings.Contains(out, "error occurred trying to connect"), check.Equals, true) 1491 1492 } 1493 1494 func setupV6() error { 1495 // Hack to get the right IPv6 address on docker0, which has already been created 1496 err := exec.Command("ip", "addr", "add", "fe80::1/64", "dev", "docker0").Run() 1497 if err != nil { 1498 return err 1499 } 1500 return nil 1501 } 1502 1503 func teardownV6() error { 1504 err := exec.Command("ip", "addr", "del", "fe80::1/64", "dev", "docker0").Run() 1505 if err != nil { 1506 return err 1507 } 1508 return nil 1509 }