github.com/squaremo/docker@v1.3.2-0.20150516120342-42cfc9554972/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/libtrust" 19 "github.com/go-check/check" 20 ) 21 22 func (s *DockerDaemonSuite) TestDaemonRestartWithRunningContainersPorts(c *check.C) { 23 if err := s.d.StartWithBusybox(); err != nil { 24 c.Fatalf("Could not start daemon with busybox: %v", err) 25 } 26 27 if out, err := s.d.Cmd("run", "-d", "--name", "top1", "-p", "1234:80", "--restart", "always", "busybox:latest", "top"); err != nil { 28 c.Fatalf("Could not run top1: err=%v\n%s", err, out) 29 } 30 // --restart=no by default 31 if out, err := s.d.Cmd("run", "-d", "--name", "top2", "-p", "80", "busybox:latest", "top"); err != nil { 32 c.Fatalf("Could not run top2: err=%v\n%s", err, out) 33 } 34 35 testRun := func(m map[string]bool, prefix string) { 36 var format string 37 for cont, shouldRun := range m { 38 out, err := s.d.Cmd("ps") 39 if err != nil { 40 c.Fatalf("Could not run ps: err=%v\n%q", err, out) 41 } 42 if shouldRun { 43 format = "%scontainer %q is not running" 44 } else { 45 format = "%scontainer %q is running" 46 } 47 if shouldRun != strings.Contains(out, cont) { 48 c.Fatalf(format, prefix, cont) 49 } 50 } 51 } 52 53 testRun(map[string]bool{"top1": true, "top2": true}, "") 54 55 if err := s.d.Restart(); err != nil { 56 c.Fatalf("Could not restart daemon: %v", err) 57 } 58 testRun(map[string]bool{"top1": true, "top2": false}, "After daemon restart: ") 59 } 60 61 func (s *DockerDaemonSuite) TestDaemonRestartWithVolumesRefs(c *check.C) { 62 if err := s.d.StartWithBusybox(); err != nil { 63 c.Fatal(err) 64 } 65 66 if out, err := s.d.Cmd("run", "-d", "--name", "volrestarttest1", "-v", "/foo", "busybox"); err != nil { 67 c.Fatal(err, out) 68 } 69 if err := s.d.Restart(); err != nil { 70 c.Fatal(err) 71 } 72 if _, err := s.d.Cmd("run", "-d", "--volumes-from", "volrestarttest1", "--name", "volrestarttest2", "busybox", "top"); err != nil { 73 c.Fatal(err) 74 } 75 if out, err := s.d.Cmd("rm", "-fv", "volrestarttest2"); err != nil { 76 c.Fatal(err, out) 77 } 78 v, err := s.d.Cmd("inspect", "--format", "{{ json .Volumes }}", "volrestarttest1") 79 if err != nil { 80 c.Fatal(err) 81 } 82 volumes := make(map[string]string) 83 json.Unmarshal([]byte(v), &volumes) 84 if _, err := os.Stat(volumes["/foo"]); err != nil { 85 c.Fatalf("Expected volume to exist: %s - %s", volumes["/foo"], err) 86 } 87 } 88 89 func (s *DockerDaemonSuite) TestDaemonStartIptablesFalse(c *check.C) { 90 if err := s.d.Start("--iptables=false"); err != nil { 91 c.Fatalf("we should have been able to start the daemon with passing iptables=false: %v", err) 92 } 93 } 94 95 // Issue #8444: If docker0 bridge is modified (intentionally or unintentionally) and 96 // no longer has an IP associated, we should gracefully handle that case and associate 97 // an IP with it rather than fail daemon start 98 func (s *DockerDaemonSuite) TestDaemonStartBridgeWithoutIPAssociation(c *check.C) { 99 // rather than depending on brctl commands to verify docker0 is created and up 100 // let's start the daemon and stop it, and then make a modification to run the 101 // actual test 102 if err := s.d.Start(); err != nil { 103 c.Fatalf("Could not start daemon: %v", err) 104 } 105 if err := s.d.Stop(); err != nil { 106 c.Fatalf("Could not stop daemon: %v", err) 107 } 108 109 // now we will remove the ip from docker0 and then try starting the daemon 110 ipCmd := exec.Command("ip", "addr", "flush", "dev", "docker0") 111 stdout, stderr, _, err := runCommandWithStdoutStderr(ipCmd) 112 if err != nil { 113 c.Fatalf("failed to remove docker0 IP association: %v, stdout: %q, stderr: %q", err, stdout, stderr) 114 } 115 116 if err := s.d.Start(); err != nil { 117 warning := "**WARNING: Docker bridge network in bad state--delete docker0 bridge interface to fix" 118 c.Fatalf("Could not start daemon when docker0 has no IP address: %v\n%s", err, warning) 119 } 120 } 121 122 func (s *DockerDaemonSuite) TestDaemonIptablesClean(c *check.C) { 123 if err := s.d.StartWithBusybox(); err != nil { 124 c.Fatalf("Could not start daemon with busybox: %v", err) 125 } 126 127 if out, err := s.d.Cmd("run", "-d", "--name", "top", "-p", "80", "busybox:latest", "top"); err != nil { 128 c.Fatalf("Could not run top: %s, %v", out, err) 129 } 130 131 // get output from iptables with container running 132 ipTablesSearchString := "tcp dpt:80" 133 ipTablesCmd := exec.Command("iptables", "-nvL") 134 out, _, err := runCommandWithOutput(ipTablesCmd) 135 if err != nil { 136 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 137 } 138 139 if !strings.Contains(out, ipTablesSearchString) { 140 c.Fatalf("iptables output should have contained %q, but was %q", ipTablesSearchString, out) 141 } 142 143 if err := s.d.Stop(); err != nil { 144 c.Fatalf("Could not stop daemon: %v", err) 145 } 146 147 // get output from iptables after restart 148 ipTablesCmd = exec.Command("iptables", "-nvL") 149 out, _, err = runCommandWithOutput(ipTablesCmd) 150 if err != nil { 151 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 152 } 153 154 if strings.Contains(out, ipTablesSearchString) { 155 c.Fatalf("iptables output should not have contained %q, but was %q", ipTablesSearchString, out) 156 } 157 } 158 159 func (s *DockerDaemonSuite) TestDaemonIptablesCreate(c *check.C) { 160 if err := s.d.StartWithBusybox(); err != nil { 161 c.Fatalf("Could not start daemon with busybox: %v", err) 162 } 163 164 if out, err := s.d.Cmd("run", "-d", "--name", "top", "--restart=always", "-p", "80", "busybox:latest", "top"); err != nil { 165 c.Fatalf("Could not run top: %s, %v", out, err) 166 } 167 168 // get output from iptables with container running 169 ipTablesSearchString := "tcp dpt:80" 170 ipTablesCmd := exec.Command("iptables", "-nvL") 171 out, _, err := runCommandWithOutput(ipTablesCmd) 172 if err != nil { 173 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 174 } 175 176 if !strings.Contains(out, ipTablesSearchString) { 177 c.Fatalf("iptables output should have contained %q, but was %q", ipTablesSearchString, out) 178 } 179 180 if err := s.d.Restart(); err != nil { 181 c.Fatalf("Could not restart daemon: %v", err) 182 } 183 184 // make sure the container is not running 185 runningOut, err := s.d.Cmd("inspect", "--format='{{.State.Running}}'", "top") 186 if err != nil { 187 c.Fatalf("Could not inspect on container: %s, %v", out, err) 188 } 189 if strings.TrimSpace(runningOut) != "true" { 190 c.Fatalf("Container should have been restarted after daemon restart. Status running should have been true but was: %q", strings.TrimSpace(runningOut)) 191 } 192 193 // get output from iptables after restart 194 ipTablesCmd = exec.Command("iptables", "-nvL") 195 out, _, err = runCommandWithOutput(ipTablesCmd) 196 if err != nil { 197 c.Fatalf("Could not run iptables -nvL: %s, %v", out, err) 198 } 199 200 if !strings.Contains(out, ipTablesSearchString) { 201 c.Fatalf("iptables output after restart should have contained %q, but was %q", ipTablesSearchString, out) 202 } 203 } 204 205 func (s *DockerDaemonSuite) TestDaemonLogLevelWrong(c *check.C) { 206 c.Assert(s.d.Start("--log-level=bogus"), check.NotNil, check.Commentf("Daemon shouldn't start with wrong log level")) 207 } 208 209 func (s *DockerDaemonSuite) TestDaemonLogLevelDebug(c *check.C) { 210 if err := s.d.Start("--log-level=debug"); err != nil { 211 c.Fatal(err) 212 } 213 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 214 if !strings.Contains(string(content), `level=debug`) { 215 c.Fatalf(`Missing level="debug" in log file:\n%s`, string(content)) 216 } 217 } 218 219 func (s *DockerDaemonSuite) TestDaemonLogLevelFatal(c *check.C) { 220 // we creating new daemons to create new logFile 221 if err := s.d.Start("--log-level=fatal"); err != nil { 222 c.Fatal(err) 223 } 224 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 225 if strings.Contains(string(content), `level=debug`) { 226 c.Fatalf(`Should not have level="debug" in log file:\n%s`, string(content)) 227 } 228 } 229 230 func (s *DockerDaemonSuite) TestDaemonFlagD(c *check.C) { 231 if err := s.d.Start("-D"); err != nil { 232 c.Fatal(err) 233 } 234 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 235 if !strings.Contains(string(content), `level=debug`) { 236 c.Fatalf(`Should have level="debug" in log file using -D:\n%s`, string(content)) 237 } 238 } 239 240 func (s *DockerDaemonSuite) TestDaemonFlagDebug(c *check.C) { 241 if err := s.d.Start("--debug"); err != nil { 242 c.Fatal(err) 243 } 244 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 245 if !strings.Contains(string(content), `level=debug`) { 246 c.Fatalf(`Should have level="debug" in log file using --debug:\n%s`, string(content)) 247 } 248 } 249 250 func (s *DockerDaemonSuite) TestDaemonFlagDebugLogLevelFatal(c *check.C) { 251 if err := s.d.Start("--debug", "--log-level=fatal"); err != nil { 252 c.Fatal(err) 253 } 254 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 255 if !strings.Contains(string(content), `level=debug`) { 256 c.Fatalf(`Should have level="debug" in log file when using both --debug and --log-level=fatal:\n%s`, string(content)) 257 } 258 } 259 260 func (s *DockerDaemonSuite) TestDaemonAllocatesListeningPort(c *check.C) { 261 listeningPorts := [][]string{ 262 {"0.0.0.0", "0.0.0.0", "5678"}, 263 {"127.0.0.1", "127.0.0.1", "1234"}, 264 {"localhost", "127.0.0.1", "1235"}, 265 } 266 267 cmdArgs := []string{} 268 for _, hostDirective := range listeningPorts { 269 cmdArgs = append(cmdArgs, "--host", fmt.Sprintf("tcp://%s:%s", hostDirective[0], hostDirective[2])) 270 } 271 272 if err := s.d.StartWithBusybox(cmdArgs...); err != nil { 273 c.Fatalf("Could not start daemon with busybox: %v", err) 274 } 275 276 for _, hostDirective := range listeningPorts { 277 output, err := s.d.Cmd("run", "-p", fmt.Sprintf("%s:%s:80", hostDirective[1], hostDirective[2]), "busybox", "true") 278 if err == nil { 279 c.Fatalf("Container should not start, expected port already allocated error: %q", output) 280 } else if !strings.Contains(output, "port is already allocated") { 281 c.Fatalf("Expected port is already allocated error: %q", output) 282 } 283 } 284 } 285 286 // #9629 287 func (s *DockerDaemonSuite) TestDaemonVolumesBindsRefs(c *check.C) { 288 if err := s.d.StartWithBusybox(); err != nil { 289 c.Fatal(err) 290 } 291 292 tmp, err := ioutil.TempDir(os.TempDir(), "") 293 if err != nil { 294 c.Fatal(err) 295 } 296 defer os.RemoveAll(tmp) 297 298 if err := ioutil.WriteFile(tmp+"/test", []byte("testing"), 0655); err != nil { 299 c.Fatal(err) 300 } 301 302 if out, err := s.d.Cmd("create", "-v", tmp+":/foo", "--name=voltest", "busybox"); err != nil { 303 c.Fatal(err, out) 304 } 305 306 if err := s.d.Restart(); err != nil { 307 c.Fatal(err) 308 } 309 310 if out, err := s.d.Cmd("run", "--volumes-from=voltest", "--name=consumer", "busybox", "/bin/sh", "-c", "[ -f /foo/test ]"); err != nil { 311 c.Fatal(err, out) 312 } 313 } 314 315 func (s *DockerDaemonSuite) TestDaemonKeyGeneration(c *check.C) { 316 // TODO: skip or update for Windows daemon 317 os.Remove("/etc/docker/key.json") 318 if err := s.d.Start(); err != nil { 319 c.Fatalf("Could not start daemon: %v", err) 320 } 321 s.d.Stop() 322 323 k, err := libtrust.LoadKeyFile("/etc/docker/key.json") 324 if err != nil { 325 c.Fatalf("Error opening key file") 326 } 327 kid := k.KeyID() 328 // Test Key ID is a valid fingerprint (e.g. QQXN:JY5W:TBXI:MK3X:GX6P:PD5D:F56N:NHCS:LVRZ:JA46:R24J:XEFF) 329 if len(kid) != 59 { 330 c.Fatalf("Bad key ID: %s", kid) 331 } 332 } 333 334 func (s *DockerDaemonSuite) TestDaemonKeyMigration(c *check.C) { 335 // TODO: skip or update for Windows daemon 336 os.Remove("/etc/docker/key.json") 337 k1, err := libtrust.GenerateECP256PrivateKey() 338 if err != nil { 339 c.Fatalf("Error generating private key: %s", err) 340 } 341 if err := os.MkdirAll(filepath.Join(os.Getenv("HOME"), ".docker"), 0755); err != nil { 342 c.Fatalf("Error creating .docker directory: %s", err) 343 } 344 if err := libtrust.SaveKey(filepath.Join(os.Getenv("HOME"), ".docker", "key.json"), k1); err != nil { 345 c.Fatalf("Error saving private key: %s", err) 346 } 347 348 if err := s.d.Start(); err != nil { 349 c.Fatalf("Could not start daemon: %v", err) 350 } 351 s.d.Stop() 352 353 k2, err := libtrust.LoadKeyFile("/etc/docker/key.json") 354 if err != nil { 355 c.Fatalf("Error opening key file") 356 } 357 if k1.KeyID() != k2.KeyID() { 358 c.Fatalf("Key not migrated") 359 } 360 } 361 362 // Simulate an older daemon (pre 1.3) coming up with volumes specified in containers 363 // without corresponding volume json 364 func (s *DockerDaemonSuite) TestDaemonUpgradeWithVolumes(c *check.C) { 365 graphDir := filepath.Join(os.TempDir(), "docker-test") 366 defer os.RemoveAll(graphDir) 367 if err := s.d.StartWithBusybox("-g", graphDir); err != nil { 368 c.Fatal(err) 369 } 370 371 tmpDir := filepath.Join(os.TempDir(), "test") 372 defer os.RemoveAll(tmpDir) 373 374 if out, err := s.d.Cmd("create", "-v", tmpDir+":/foo", "--name=test", "busybox"); err != nil { 375 c.Fatal(err, out) 376 } 377 378 if err := s.d.Stop(); err != nil { 379 c.Fatal(err) 380 } 381 382 // Remove this since we're expecting the daemon to re-create it too 383 if err := os.RemoveAll(tmpDir); err != nil { 384 c.Fatal(err) 385 } 386 387 configDir := filepath.Join(graphDir, "volumes") 388 389 if err := os.RemoveAll(configDir); err != nil { 390 c.Fatal(err) 391 } 392 393 if err := s.d.Start("-g", graphDir); err != nil { 394 c.Fatal(err) 395 } 396 397 if _, err := os.Stat(tmpDir); os.IsNotExist(err) { 398 c.Fatalf("expected volume path %s to exist but it does not", tmpDir) 399 } 400 401 dir, err := ioutil.ReadDir(configDir) 402 if err != nil { 403 c.Fatal(err) 404 } 405 if len(dir) == 0 { 406 c.Fatalf("expected volumes config dir to contain data for new volume") 407 } 408 409 // Now with just removing the volume config and not the volume data 410 if err := s.d.Stop(); err != nil { 411 c.Fatal(err) 412 } 413 414 if err := os.RemoveAll(configDir); err != nil { 415 c.Fatal(err) 416 } 417 418 if err := s.d.Start("-g", graphDir); err != nil { 419 c.Fatal(err) 420 } 421 422 dir, err = ioutil.ReadDir(configDir) 423 if err != nil { 424 c.Fatal(err) 425 } 426 427 if len(dir) == 0 { 428 c.Fatalf("expected volumes config dir to contain data for new volume") 429 } 430 } 431 432 // GH#11320 - verify that the daemon exits on failure properly 433 // Note that this explicitly tests the conflict of {-b,--bridge} and {--bip} options as the means 434 // to get a daemon init failure; no other tests for -b/--bip conflict are therefore required 435 func (s *DockerDaemonSuite) TestDaemonExitOnFailure(c *check.C) { 436 //attempt to start daemon with incorrect flags (we know -b and --bip conflict) 437 if err := s.d.Start("--bridge", "nosuchbridge", "--bip", "1.1.1.1"); err != nil { 438 //verify we got the right error 439 if !strings.Contains(err.Error(), "Daemon exited and never started") { 440 c.Fatalf("Expected daemon not to start, got %v", err) 441 } 442 // look in the log and make sure we got the message that daemon is shutting down 443 runCmd := exec.Command("grep", "Error starting daemon", s.d.LogfileName()) 444 if out, _, err := runCommandWithOutput(runCmd); err != nil { 445 c.Fatalf("Expected 'Error starting daemon' message; but doesn't exist in log: %q, err: %v", out, err) 446 } 447 } else { 448 //if we didn't get an error and the daemon is running, this is a failure 449 c.Fatal("Conflicting options should cause the daemon to error out with a failure") 450 } 451 } 452 453 func (s *DockerDaemonSuite) TestDaemonBridgeExternal(c *check.C) { 454 d := s.d 455 err := d.Start("--bridge", "nosuchbridge") 456 c.Assert(err, check.NotNil, check.Commentf("--bridge option with an invalid bridge should cause the daemon to fail")) 457 defer d.Restart() 458 459 bridgeName := "external-bridge" 460 bridgeIp := "192.169.1.1/24" 461 _, bridgeIPNet, _ := net.ParseCIDR(bridgeIp) 462 463 out, err := createInterface(c, "bridge", bridgeName, bridgeIp) 464 c.Assert(err, check.IsNil, check.Commentf(out)) 465 defer deleteInterface(c, bridgeName) 466 467 err = d.StartWithBusybox("--bridge", bridgeName) 468 c.Assert(err, check.IsNil) 469 470 ipTablesSearchString := bridgeIPNet.String() 471 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 472 out, _, err = runCommandWithOutput(ipTablesCmd) 473 c.Assert(err, check.IsNil) 474 475 c.Assert(strings.Contains(out, ipTablesSearchString), check.Equals, true, 476 check.Commentf("iptables output should have contained %q, but was %q", 477 ipTablesSearchString, out)) 478 479 _, err = d.Cmd("run", "-d", "--name", "ExtContainer", "busybox", "top") 480 c.Assert(err, check.IsNil) 481 482 containerIp := d.findContainerIP("ExtContainer") 483 ip := net.ParseIP(containerIp) 484 c.Assert(bridgeIPNet.Contains(ip), check.Equals, true, 485 check.Commentf("Container IP-Address must be in the same subnet range : %s", 486 containerIp)) 487 } 488 489 func createInterface(c *check.C, ifType string, ifName string, ipNet string) (string, error) { 490 args := []string{"link", "add", "name", ifName, "type", ifType} 491 ipLinkCmd := exec.Command("ip", args...) 492 out, _, err := runCommandWithOutput(ipLinkCmd) 493 if err != nil { 494 return out, err 495 } 496 497 ifCfgCmd := exec.Command("ifconfig", ifName, ipNet, "up") 498 out, _, err = runCommandWithOutput(ifCfgCmd) 499 return out, err 500 } 501 502 func deleteInterface(c *check.C, ifName string) { 503 ifCmd := exec.Command("ip", "link", "delete", ifName) 504 out, _, err := runCommandWithOutput(ifCmd) 505 c.Assert(err, check.IsNil, check.Commentf(out)) 506 507 flushCmd := exec.Command("iptables", "-t", "nat", "--flush") 508 out, _, err = runCommandWithOutput(flushCmd) 509 c.Assert(err, check.IsNil, check.Commentf(out)) 510 511 flushCmd = exec.Command("iptables", "--flush") 512 out, _, err = runCommandWithOutput(flushCmd) 513 c.Assert(err, check.IsNil, check.Commentf(out)) 514 } 515 516 func (s *DockerDaemonSuite) TestDaemonBridgeIP(c *check.C) { 517 // TestDaemonBridgeIP Steps 518 // 1. Delete the existing docker0 Bridge 519 // 2. Set --bip daemon configuration and start the new Docker Daemon 520 // 3. Check if the bip config has taken effect using ifconfig and iptables commands 521 // 4. Launch a Container and make sure the IP-Address is in the expected subnet 522 // 5. Delete the docker0 Bridge 523 // 6. Restart the Docker Daemon (via defered action) 524 // This Restart takes care of bringing docker0 interface back to auto-assigned IP 525 526 defaultNetworkBridge := "docker0" 527 deleteInterface(c, defaultNetworkBridge) 528 529 d := s.d 530 531 bridgeIp := "192.169.1.1/24" 532 ip, bridgeIPNet, _ := net.ParseCIDR(bridgeIp) 533 534 err := d.StartWithBusybox("--bip", bridgeIp) 535 c.Assert(err, check.IsNil) 536 defer d.Restart() 537 538 ifconfigSearchString := ip.String() 539 ifconfigCmd := exec.Command("ifconfig", defaultNetworkBridge) 540 out, _, _, err := runCommandWithStdoutStderr(ifconfigCmd) 541 c.Assert(err, check.IsNil) 542 543 c.Assert(strings.Contains(out, ifconfigSearchString), check.Equals, true, 544 check.Commentf("ifconfig output should have contained %q, but was %q", 545 ifconfigSearchString, out)) 546 547 ipTablesSearchString := bridgeIPNet.String() 548 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 549 out, _, err = runCommandWithOutput(ipTablesCmd) 550 c.Assert(err, check.IsNil) 551 552 c.Assert(strings.Contains(out, ipTablesSearchString), check.Equals, true, 553 check.Commentf("iptables output should have contained %q, but was %q", 554 ipTablesSearchString, out)) 555 556 out, err = d.Cmd("run", "-d", "--name", "test", "busybox", "top") 557 c.Assert(err, check.IsNil) 558 559 containerIp := d.findContainerIP("test") 560 ip = net.ParseIP(containerIp) 561 c.Assert(bridgeIPNet.Contains(ip), check.Equals, true, 562 check.Commentf("Container IP-Address must be in the same subnet range : %s", 563 containerIp)) 564 deleteInterface(c, defaultNetworkBridge) 565 } 566 567 func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr(c *check.C) { 568 d := s.d 569 570 bridgeName := "external-bridge" 571 bridgeIp := "192.169.1.1/24" 572 573 out, err := createInterface(c, "bridge", bridgeName, bridgeIp) 574 c.Assert(err, check.IsNil, check.Commentf(out)) 575 defer deleteInterface(c, bridgeName) 576 577 args := []string{"--bridge", bridgeName, "--fixed-cidr", "192.169.1.0/30"} 578 err = d.StartWithBusybox(args...) 579 c.Assert(err, check.IsNil) 580 defer d.Restart() 581 582 for i := 0; i < 4; i++ { 583 cName := "Container" + strconv.Itoa(i) 584 out, err := d.Cmd("run", "-d", "--name", cName, "busybox", "top") 585 if err != nil { 586 c.Assert(strings.Contains(out, "no available ip addresses"), check.Equals, true, 587 check.Commentf("Could not run a Container : %s %s", err.Error(), out)) 588 } 589 } 590 } 591 592 func (s *DockerDaemonSuite) TestDaemonIP(c *check.C) { 593 d := s.d 594 595 ipStr := "192.170.1.1/24" 596 ip, _, _ := net.ParseCIDR(ipStr) 597 args := []string{"--ip", ip.String()} 598 err := d.StartWithBusybox(args...) 599 c.Assert(err, check.IsNil) 600 defer d.Restart() 601 602 out, err := d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top") 603 c.Assert(err, check.NotNil, 604 check.Commentf("Running a container must fail with an invalid --ip option")) 605 c.Assert(strings.Contains(out, "Error starting userland proxy"), check.Equals, true) 606 607 ifName := "dummy" 608 out, err = createInterface(c, "dummy", ifName, ipStr) 609 c.Assert(err, check.IsNil, check.Commentf(out)) 610 defer deleteInterface(c, ifName) 611 612 _, err = d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top") 613 c.Assert(err, check.IsNil) 614 615 ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL") 616 out, _, err = runCommandWithOutput(ipTablesCmd) 617 c.Assert(err, check.IsNil) 618 619 regex := fmt.Sprintf("DNAT.*%s.*dpt:8000", ip.String()) 620 matched, _ := regexp.MatchString(regex, out) 621 c.Assert(matched, check.Equals, true, 622 check.Commentf("iptables output should have contained %q, but was %q", regex, out)) 623 } 624 625 func (s *DockerDaemonSuite) TestDaemonICCPing(c *check.C) { 626 d := s.d 627 628 bridgeName := "external-bridge" 629 bridgeIp := "192.169.1.1/24" 630 631 out, err := createInterface(c, "bridge", bridgeName, bridgeIp) 632 c.Assert(err, check.IsNil, check.Commentf(out)) 633 defer deleteInterface(c, bridgeName) 634 635 args := []string{"--bridge", bridgeName, "--icc=false"} 636 err = d.StartWithBusybox(args...) 637 c.Assert(err, check.IsNil) 638 defer d.Restart() 639 640 ipTablesCmd := exec.Command("iptables", "-nvL", "FORWARD") 641 out, _, err = runCommandWithOutput(ipTablesCmd) 642 c.Assert(err, check.IsNil) 643 644 regex := fmt.Sprintf("DROP.*all.*%s.*%s", bridgeName, bridgeName) 645 matched, _ := regexp.MatchString(regex, out) 646 c.Assert(matched, check.Equals, true, 647 check.Commentf("iptables output should have contained %q, but was %q", regex, out)) 648 649 // Pinging another container must fail with --icc=false 650 pingContainers(c, d, true) 651 652 ipStr := "192.171.1.1/24" 653 ip, _, _ := net.ParseCIDR(ipStr) 654 ifName := "icc-dummy" 655 656 createInterface(c, "dummy", ifName, ipStr) 657 658 // But, Pinging external or a Host interface must succeed 659 pingCmd := fmt.Sprintf("ping -c 1 %s -W 1", ip.String()) 660 runArgs := []string{"--rm", "busybox", "sh", "-c", pingCmd} 661 _, err = d.Cmd("run", runArgs...) 662 c.Assert(err, check.IsNil) 663 } 664 665 func (s *DockerDaemonSuite) TestDaemonICCLinkExpose(c *check.C) { 666 d := s.d 667 668 bridgeName := "external-bridge" 669 bridgeIp := "192.169.1.1/24" 670 671 out, err := createInterface(c, "bridge", bridgeName, bridgeIp) 672 c.Assert(err, check.IsNil, check.Commentf(out)) 673 defer deleteInterface(c, bridgeName) 674 675 args := []string{"--bridge", bridgeName, "--icc=false"} 676 err = d.StartWithBusybox(args...) 677 c.Assert(err, check.IsNil) 678 defer d.Restart() 679 680 ipTablesCmd := exec.Command("iptables", "-nvL", "FORWARD") 681 out, _, err = runCommandWithOutput(ipTablesCmd) 682 c.Assert(err, check.IsNil) 683 684 regex := fmt.Sprintf("DROP.*all.*%s.*%s", bridgeName, bridgeName) 685 matched, _ := regexp.MatchString(regex, out) 686 c.Assert(matched, check.Equals, true, 687 check.Commentf("iptables output should have contained %q, but was %q", regex, out)) 688 689 _, err = d.Cmd("run", "-d", "--expose", "4567", "--name", "icc1", "busybox", "nc", "-l", "-p", "4567") 690 c.Assert(err, check.IsNil) 691 692 out, err = d.Cmd("run", "--link", "icc1:icc1", "busybox", "nc", "icc1", "4567") 693 c.Assert(err, check.IsNil, check.Commentf(out)) 694 } 695 696 func (s *DockerDaemonSuite) TestDaemonUlimitDefaults(c *check.C) { 697 testRequires(c, NativeExecDriver) 698 699 if err := s.d.StartWithBusybox("--default-ulimit", "nofile=42:42", "--default-ulimit", "nproc=1024:1024"); err != nil { 700 c.Fatal(err) 701 } 702 703 out, err := s.d.Cmd("run", "--ulimit", "nproc=2048", "--name=test", "busybox", "/bin/sh", "-c", "echo $(ulimit -n); echo $(ulimit -p)") 704 if err != nil { 705 c.Fatal(out, err) 706 } 707 708 outArr := strings.Split(out, "\n") 709 if len(outArr) < 2 { 710 c.Fatalf("got unexpected output: %s", out) 711 } 712 nofile := strings.TrimSpace(outArr[0]) 713 nproc := strings.TrimSpace(outArr[1]) 714 715 if nofile != "42" { 716 c.Fatalf("expected `ulimit -n` to be `42`, got: %s", nofile) 717 } 718 if nproc != "2048" { 719 c.Fatalf("exepcted `ulimit -p` to be 2048, got: %s", nproc) 720 } 721 722 // Now restart daemon with a new default 723 if err := s.d.Restart("--default-ulimit", "nofile=43"); err != nil { 724 c.Fatal(err) 725 } 726 727 out, err = s.d.Cmd("start", "-a", "test") 728 if err != nil { 729 c.Fatal(err) 730 } 731 732 outArr = strings.Split(out, "\n") 733 if len(outArr) < 2 { 734 c.Fatalf("got unexpected output: %s", out) 735 } 736 nofile = strings.TrimSpace(outArr[0]) 737 nproc = strings.TrimSpace(outArr[1]) 738 739 if nofile != "43" { 740 c.Fatalf("expected `ulimit -n` to be `43`, got: %s", nofile) 741 } 742 if nproc != "2048" { 743 c.Fatalf("exepcted `ulimit -p` to be 2048, got: %s", nproc) 744 } 745 } 746 747 // #11315 748 func (s *DockerDaemonSuite) TestDaemonRestartRenameContainer(c *check.C) { 749 if err := s.d.StartWithBusybox(); err != nil { 750 c.Fatal(err) 751 } 752 753 if out, err := s.d.Cmd("run", "--name=test", "busybox"); err != nil { 754 c.Fatal(err, out) 755 } 756 757 if out, err := s.d.Cmd("rename", "test", "test2"); err != nil { 758 c.Fatal(err, out) 759 } 760 761 if err := s.d.Restart(); err != nil { 762 c.Fatal(err) 763 } 764 765 if out, err := s.d.Cmd("start", "test2"); err != nil { 766 c.Fatal(err, out) 767 } 768 } 769 770 func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefault(c *check.C) { 771 if err := s.d.StartWithBusybox(); err != nil { 772 c.Fatal(err) 773 } 774 775 out, err := s.d.Cmd("run", "-d", "busybox", "echo", "testline") 776 if err != nil { 777 c.Fatal(out, err) 778 } 779 id := strings.TrimSpace(out) 780 781 if out, err := s.d.Cmd("wait", id); err != nil { 782 c.Fatal(out, err) 783 } 784 logPath := filepath.Join(s.d.folder, "graph", "containers", id, id+"-json.log") 785 786 if _, err := os.Stat(logPath); err != nil { 787 c.Fatal(err) 788 } 789 f, err := os.Open(logPath) 790 if err != nil { 791 c.Fatal(err) 792 } 793 var res struct { 794 Log string `json:"log"` 795 Stream string `json:"stream"` 796 Time time.Time `json:"time"` 797 } 798 if err := json.NewDecoder(f).Decode(&res); err != nil { 799 c.Fatal(err) 800 } 801 if res.Log != "testline\n" { 802 c.Fatalf("Unexpected log line: %q, expected: %q", res.Log, "testline\n") 803 } 804 if res.Stream != "stdout" { 805 c.Fatalf("Unexpected stream: %q, expected: %q", res.Stream, "stdout") 806 } 807 if !time.Now().After(res.Time) { 808 c.Fatalf("Log time %v in future", res.Time) 809 } 810 } 811 812 func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefaultOverride(c *check.C) { 813 if err := s.d.StartWithBusybox(); err != nil { 814 c.Fatal(err) 815 } 816 817 out, err := s.d.Cmd("run", "-d", "--log-driver=none", "busybox", "echo", "testline") 818 if err != nil { 819 c.Fatal(out, err) 820 } 821 id := strings.TrimSpace(out) 822 823 if out, err := s.d.Cmd("wait", id); err != nil { 824 c.Fatal(out, err) 825 } 826 logPath := filepath.Join(s.d.folder, "graph", "containers", id, id+"-json.log") 827 828 if _, err := os.Stat(logPath); err == nil || !os.IsNotExist(err) { 829 c.Fatalf("%s shouldn't exits, error on Stat: %s", logPath, err) 830 } 831 } 832 833 func (s *DockerDaemonSuite) TestDaemonLoggingDriverNone(c *check.C) { 834 if err := s.d.StartWithBusybox("--log-driver=none"); err != nil { 835 c.Fatal(err) 836 } 837 838 out, err := s.d.Cmd("run", "-d", "busybox", "echo", "testline") 839 if err != nil { 840 c.Fatal(out, err) 841 } 842 id := strings.TrimSpace(out) 843 if out, err := s.d.Cmd("wait", id); err != nil { 844 c.Fatal(out, err) 845 } 846 847 logPath := filepath.Join(s.d.folder, "graph", "containers", id, id+"-json.log") 848 849 if _, err := os.Stat(logPath); err == nil || !os.IsNotExist(err) { 850 c.Fatalf("%s shouldn't exits, error on Stat: %s", logPath, err) 851 } 852 } 853 854 func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneOverride(c *check.C) { 855 if err := s.d.StartWithBusybox("--log-driver=none"); err != nil { 856 c.Fatal(err) 857 } 858 859 out, err := s.d.Cmd("run", "-d", "--log-driver=json-file", "busybox", "echo", "testline") 860 if err != nil { 861 c.Fatal(out, err) 862 } 863 id := strings.TrimSpace(out) 864 865 if out, err := s.d.Cmd("wait", id); err != nil { 866 c.Fatal(out, err) 867 } 868 logPath := filepath.Join(s.d.folder, "graph", "containers", id, id+"-json.log") 869 870 if _, err := os.Stat(logPath); err != nil { 871 c.Fatal(err) 872 } 873 f, err := os.Open(logPath) 874 if err != nil { 875 c.Fatal(err) 876 } 877 var res struct { 878 Log string `json:"log"` 879 Stream string `json:"stream"` 880 Time time.Time `json:"time"` 881 } 882 if err := json.NewDecoder(f).Decode(&res); err != nil { 883 c.Fatal(err) 884 } 885 if res.Log != "testline\n" { 886 c.Fatalf("Unexpected log line: %q, expected: %q", res.Log, "testline\n") 887 } 888 if res.Stream != "stdout" { 889 c.Fatalf("Unexpected stream: %q, expected: %q", res.Stream, "stdout") 890 } 891 if !time.Now().After(res.Time) { 892 c.Fatalf("Log time %v in future", res.Time) 893 } 894 } 895 896 func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneLogsError(c *check.C) { 897 if err := s.d.StartWithBusybox("--log-driver=none"); err != nil { 898 c.Fatal(err) 899 } 900 901 out, err := s.d.Cmd("run", "-d", "busybox", "echo", "testline") 902 if err != nil { 903 c.Fatal(out, err) 904 } 905 id := strings.TrimSpace(out) 906 out, err = s.d.Cmd("logs", id) 907 if err == nil { 908 c.Fatalf("Logs should fail with \"none\" driver") 909 } 910 if !strings.Contains(out, `"logs" command is supported only for "json-file" logging driver`) { 911 c.Fatalf("There should be error about non-json-file driver, got: %s", out) 912 } 913 } 914 915 func (s *DockerDaemonSuite) TestDaemonDots(c *check.C) { 916 if err := s.d.StartWithBusybox(); err != nil { 917 c.Fatal(err) 918 } 919 920 // Now create 4 containers 921 if _, err := s.d.Cmd("create", "busybox"); err != nil { 922 c.Fatalf("Error creating container: %q", err) 923 } 924 if _, err := s.d.Cmd("create", "busybox"); err != nil { 925 c.Fatalf("Error creating container: %q", err) 926 } 927 if _, err := s.d.Cmd("create", "busybox"); err != nil { 928 c.Fatalf("Error creating container: %q", err) 929 } 930 if _, err := s.d.Cmd("create", "busybox"); err != nil { 931 c.Fatalf("Error creating container: %q", err) 932 } 933 934 s.d.Stop() 935 936 s.d.Start("--log-level=debug") 937 s.d.Stop() 938 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 939 if strings.Contains(string(content), "....") { 940 c.Fatalf("Debug level should not have ....\n%s", string(content)) 941 } 942 943 s.d.Start("--log-level=error") 944 s.d.Stop() 945 content, _ = ioutil.ReadFile(s.d.logFile.Name()) 946 if strings.Contains(string(content), "....") { 947 c.Fatalf("Error level should not have ....\n%s", string(content)) 948 } 949 950 s.d.Start("--log-level=info") 951 s.d.Stop() 952 content, _ = ioutil.ReadFile(s.d.logFile.Name()) 953 if !strings.Contains(string(content), "....") { 954 c.Fatalf("Info level should have ....\n%s", string(content)) 955 } 956 } 957 958 func (s *DockerDaemonSuite) TestDaemonUnixSockCleanedUp(c *check.C) { 959 dir, err := ioutil.TempDir("", "socket-cleanup-test") 960 if err != nil { 961 c.Fatal(err) 962 } 963 defer os.RemoveAll(dir) 964 965 sockPath := filepath.Join(dir, "docker.sock") 966 if err := s.d.Start("--host", "unix://"+sockPath); err != nil { 967 c.Fatal(err) 968 } 969 970 if _, err := os.Stat(sockPath); err != nil { 971 c.Fatal("socket does not exist") 972 } 973 974 if err := s.d.Stop(); err != nil { 975 c.Fatal(err) 976 } 977 978 if _, err := os.Stat(sockPath); err == nil || !os.IsNotExist(err) { 979 c.Fatal("unix socket is not cleaned up") 980 } 981 } 982 983 func (s *DockerDaemonSuite) TestDaemonWithWrongkey(c *check.C) { 984 type Config struct { 985 Crv string `json:"crv"` 986 D string `json:"d"` 987 Kid string `json:"kid"` 988 Kty string `json:"kty"` 989 X string `json:"x"` 990 Y string `json:"y"` 991 } 992 993 os.Remove("/etc/docker/key.json") 994 if err := s.d.Start(); err != nil { 995 c.Fatalf("Failed to start daemon: %v", err) 996 } 997 998 if err := s.d.Stop(); err != nil { 999 c.Fatalf("Could not stop daemon: %v", err) 1000 } 1001 1002 config := &Config{} 1003 bytes, err := ioutil.ReadFile("/etc/docker/key.json") 1004 if err != nil { 1005 c.Fatalf("Error reading key.json file: %s", err) 1006 } 1007 1008 // byte[] to Data-Struct 1009 if err := json.Unmarshal(bytes, &config); err != nil { 1010 c.Fatalf("Error Unmarshal: %s", err) 1011 } 1012 1013 //replace config.Kid with the fake value 1014 config.Kid = "VSAJ:FUYR:X3H2:B2VZ:KZ6U:CJD5:K7BX:ZXHY:UZXT:P4FT:MJWG:HRJ4" 1015 1016 // NEW Data-Struct to byte[] 1017 newBytes, err := json.Marshal(&config) 1018 if err != nil { 1019 c.Fatalf("Error Marshal: %s", err) 1020 } 1021 1022 // write back 1023 if err := ioutil.WriteFile("/etc/docker/key.json", newBytes, 0400); err != nil { 1024 c.Fatalf("Error ioutil.WriteFile: %s", err) 1025 } 1026 1027 defer os.Remove("/etc/docker/key.json") 1028 1029 if err := s.d.Start(); err == nil { 1030 c.Fatalf("It should not be successful to start daemon with wrong key: %v", err) 1031 } 1032 1033 content, _ := ioutil.ReadFile(s.d.logFile.Name()) 1034 1035 if !strings.Contains(string(content), "Public Key ID does not match") { 1036 c.Fatal("Missing KeyID message from daemon logs") 1037 } 1038 } 1039 1040 func (s *DockerDaemonSuite) TestDaemonRestartKillWait(c *check.C) { 1041 if err := s.d.StartWithBusybox(); err != nil { 1042 c.Fatalf("Could not start daemon with busybox: %v", err) 1043 } 1044 1045 out, err := s.d.Cmd("run", "-id", "busybox", "/bin/cat") 1046 if err != nil { 1047 c.Fatalf("Could not run /bin/cat: err=%v\n%s", err, out) 1048 } 1049 containerID := strings.TrimSpace(out) 1050 1051 if out, err := s.d.Cmd("kill", containerID); err != nil { 1052 c.Fatalf("Could not kill %s: err=%v\n%s", containerID, err, out) 1053 } 1054 1055 if err := s.d.Restart(); err != nil { 1056 c.Fatalf("Could not restart daemon: %v", err) 1057 } 1058 1059 errchan := make(chan error) 1060 go func() { 1061 if out, err := s.d.Cmd("wait", containerID); err != nil { 1062 errchan <- fmt.Errorf("%v:\n%s", err, out) 1063 } 1064 close(errchan) 1065 }() 1066 1067 select { 1068 case <-time.After(5 * time.Second): 1069 c.Fatal("Waiting on a stopped (killed) container timed out") 1070 case err := <-errchan: 1071 if err != nil { 1072 c.Fatal(err) 1073 } 1074 } 1075 } 1076 1077 // TestHttpsInfo connects via two-way authenticated HTTPS to the info endpoint 1078 func (s *DockerDaemonSuite) TestHttpsInfo(c *check.C) { 1079 const ( 1080 testDaemonHttpsAddr = "localhost:4271" 1081 ) 1082 1083 if err := s.d.Start("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-cert.pem", 1084 "--tlskey", "fixtures/https/server-key.pem", "-H", testDaemonHttpsAddr); err != nil { 1085 c.Fatalf("Could not start daemon with busybox: %v", err) 1086 } 1087 1088 //force tcp protocol 1089 host := fmt.Sprintf("tcp://%s", testDaemonHttpsAddr) 1090 daemonArgs := []string{"--host", host, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/client-cert.pem", "--tlskey", "fixtures/https/client-key.pem"} 1091 out, err := s.d.CmdWithArgs(daemonArgs, "info") 1092 if err != nil { 1093 c.Fatalf("Error Occurred: %s and output: %s", err, out) 1094 } 1095 } 1096 1097 // TestHttpsInfoRogueCert connects via two-way authenticated HTTPS to the info endpoint 1098 // by using a rogue client certificate and checks that it fails with the expected error. 1099 func (s *DockerDaemonSuite) TestHttpsInfoRogueCert(c *check.C) { 1100 const ( 1101 errBadCertificate = "remote error: bad certificate" 1102 testDaemonHttpsAddr = "localhost:4271" 1103 ) 1104 if err := s.d.Start("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-cert.pem", 1105 "--tlskey", "fixtures/https/server-key.pem", "-H", testDaemonHttpsAddr); err != nil { 1106 c.Fatalf("Could not start daemon with busybox: %v", err) 1107 } 1108 1109 //force tcp protocol 1110 host := fmt.Sprintf("tcp://%s", testDaemonHttpsAddr) 1111 daemonArgs := []string{"--host", host, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/client-rogue-cert.pem", "--tlskey", "fixtures/https/client-rogue-key.pem"} 1112 out, err := s.d.CmdWithArgs(daemonArgs, "info") 1113 if err == nil || !strings.Contains(out, errBadCertificate) { 1114 c.Fatalf("Expected err: %s, got instead: %s and output: %s", errBadCertificate, err, out) 1115 } 1116 } 1117 1118 // TestHttpsInfoRogueServerCert connects via two-way authenticated HTTPS to the info endpoint 1119 // which provides a rogue server certificate and checks that it fails with the expected error 1120 func (s *DockerDaemonSuite) TestHttpsInfoRogueServerCert(c *check.C) { 1121 const ( 1122 errCaUnknown = "x509: certificate signed by unknown authority" 1123 testDaemonRogueHttpsAddr = "localhost:4272" 1124 ) 1125 if err := s.d.Start("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-rogue-cert.pem", 1126 "--tlskey", "fixtures/https/server-rogue-key.pem", "-H", testDaemonRogueHttpsAddr); err != nil { 1127 c.Fatalf("Could not start daemon with busybox: %v", err) 1128 } 1129 1130 //force tcp protocol 1131 host := fmt.Sprintf("tcp://%s", testDaemonRogueHttpsAddr) 1132 daemonArgs := []string{"--host", host, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/client-rogue-cert.pem", "--tlskey", "fixtures/https/client-rogue-key.pem"} 1133 out, err := s.d.CmdWithArgs(daemonArgs, "info") 1134 if err == nil || !strings.Contains(out, errCaUnknown) { 1135 c.Fatalf("Expected err: %s, got instead: %s and output: %s", errCaUnknown, err, out) 1136 } 1137 } 1138 1139 func pingContainers(c *check.C, d *Daemon, expectFailure bool) { 1140 var dargs []string 1141 if d != nil { 1142 dargs = []string{"--host", d.sock()} 1143 } 1144 1145 args := append(dargs, "run", "-d", "--name", "container1", "busybox", "top") 1146 _, err := runCommand(exec.Command(dockerBinary, args...)) 1147 c.Assert(err, check.IsNil) 1148 1149 args = append(dargs, "run", "--rm", "--link", "container1:alias1", "busybox", "sh", "-c") 1150 pingCmd := "ping -c 1 %s -W 1" 1151 args = append(args, fmt.Sprintf(pingCmd, "alias1")) 1152 _, err = runCommand(exec.Command(dockerBinary, args...)) 1153 1154 if expectFailure { 1155 c.Assert(err, check.NotNil) 1156 } else { 1157 c.Assert(err, check.IsNil) 1158 } 1159 1160 args = append(dargs, "rm", "-f", "container1") 1161 runCommand(exec.Command(dockerBinary, args...)) 1162 } 1163 1164 func (s *DockerDaemonSuite) TestDaemonRestartWithSockerAsVolume(c *check.C) { 1165 c.Assert(s.d.StartWithBusybox(), check.IsNil) 1166 1167 socket := filepath.Join(s.d.folder, "docker.sock") 1168 1169 out, err := s.d.Cmd("run", "-d", "-v", socket+":/sock", "busybox") 1170 c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) 1171 c.Assert(s.d.Restart(), check.IsNil) 1172 }