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