2015-08-05 16:21:45 +00:00
|
|
|
// +build daemon,!windows
|
2014-11-20 05:19:16 +00:00
|
|
|
|
2014-07-23 18:39:14 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2015-09-19 00:49:36 +00:00
|
|
|
"bytes"
|
2014-10-08 17:13:32 +00:00
|
|
|
"encoding/json"
|
2014-11-15 04:38:02 +00:00
|
|
|
"fmt"
|
2014-10-01 13:07:24 +00:00
|
|
|
"io/ioutil"
|
2015-04-27 20:16:33 +00:00
|
|
|
"net"
|
2014-10-08 17:13:32 +00:00
|
|
|
"os"
|
2014-10-05 04:21:59 +00:00
|
|
|
"os/exec"
|
2015-01-22 18:51:04 +00:00
|
|
|
"path/filepath"
|
2015-04-28 17:26:59 +00:00
|
|
|
"regexp"
|
2015-04-28 15:55:04 +00:00
|
|
|
"strconv"
|
2014-07-23 18:39:14 +00:00
|
|
|
"strings"
|
2015-02-04 21:44:52 +00:00
|
|
|
"time"
|
2015-01-21 16:14:30 +00:00
|
|
|
|
2015-10-21 02:17:18 +00:00
|
|
|
"github.com/docker/docker/pkg/integration/checker"
|
2015-05-06 22:39:29 +00:00
|
|
|
"github.com/docker/libnetwork/iptables"
|
2015-01-21 16:14:30 +00:00
|
|
|
"github.com/docker/libtrust"
|
2015-04-18 16:46:47 +00:00
|
|
|
"github.com/go-check/check"
|
2014-07-23 18:39:14 +00:00
|
|
|
)
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonRestartWithRunningContainersPorts(c *check.C) {
|
|
|
|
if err := s.d.StartWithBusybox(); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not start daemon with busybox: %v", err)
|
2014-07-23 18:39:14 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if out, err := s.d.Cmd("run", "-d", "--name", "top1", "-p", "1234:80", "--restart", "always", "busybox:latest", "top"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not run top1: err=%v\n%s", err, out)
|
2014-07-23 18:39:14 +00:00
|
|
|
}
|
|
|
|
// --restart=no by default
|
2015-04-26 02:47:42 +00:00
|
|
|
if out, err := s.d.Cmd("run", "-d", "--name", "top2", "-p", "80", "busybox:latest", "top"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not run top2: err=%v\n%s", err, out)
|
2014-07-23 18:39:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
testRun := func(m map[string]bool, prefix string) {
|
|
|
|
var format string
|
2015-04-18 16:46:47 +00:00
|
|
|
for cont, shouldRun := range m {
|
2015-04-26 02:47:42 +00:00
|
|
|
out, err := s.d.Cmd("ps")
|
2014-07-23 18:39:14 +00:00
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not run ps: err=%v\n%q", err, out)
|
2014-07-23 18:39:14 +00:00
|
|
|
}
|
|
|
|
if shouldRun {
|
|
|
|
format = "%scontainer %q is not running"
|
|
|
|
} else {
|
|
|
|
format = "%scontainer %q is running"
|
|
|
|
}
|
2015-04-18 16:46:47 +00:00
|
|
|
if shouldRun != strings.Contains(out, cont) {
|
|
|
|
c.Fatalf(format, prefix, cont)
|
2014-07-23 18:39:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
testRun(map[string]bool{"top1": true, "top2": true}, "")
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.Restart(); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not restart daemon: %v", err)
|
2014-07-23 18:39:14 +00:00
|
|
|
}
|
|
|
|
testRun(map[string]bool{"top1": true, "top2": false}, "After daemon restart: ")
|
|
|
|
}
|
2014-10-08 17:13:32 +00:00
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonRestartWithVolumesRefs(c *check.C) {
|
|
|
|
if err := s.d.StartWithBusybox(); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2014-10-08 17:13:32 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if out, err := s.d.Cmd("run", "-d", "--name", "volrestarttest1", "-v", "/foo", "busybox"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err, out)
|
2014-10-08 17:13:32 +00:00
|
|
|
}
|
2015-06-03 19:21:38 +00:00
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.Restart(); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2014-10-08 17:13:32 +00:00
|
|
|
}
|
2015-06-12 13:25:32 +00:00
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if _, err := s.d.Cmd("run", "-d", "--volumes-from", "volrestarttest1", "--name", "volrestarttest2", "busybox", "top"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2014-10-08 17:13:32 +00:00
|
|
|
}
|
2015-06-03 19:21:38 +00:00
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if out, err := s.d.Cmd("rm", "-fv", "volrestarttest2"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err, out)
|
2014-10-08 17:13:32 +00:00
|
|
|
}
|
2015-06-03 19:21:38 +00:00
|
|
|
|
|
|
|
out, err := s.d.Cmd("inspect", "-f", "{{json .Mounts}}", "volrestarttest1")
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
|
|
|
|
if _, err := inspectMountPointJSON(out, "/foo"); err != nil {
|
|
|
|
c.Fatalf("Expected volume to exist: /foo, error: %v\n", err)
|
2014-10-08 17:13:32 +00:00
|
|
|
}
|
|
|
|
}
|
2014-10-16 18:39:22 +00:00
|
|
|
|
2015-08-05 21:09:08 +00:00
|
|
|
// #11008
|
|
|
|
func (s *DockerDaemonSuite) TestDaemonRestartUnlessStopped(c *check.C) {
|
|
|
|
err := s.d.StartWithBusybox()
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
|
|
|
|
out, err := s.d.Cmd("run", "-d", "--name", "top1", "--restart", "always", "busybox:latest", "top")
|
|
|
|
c.Assert(err, check.IsNil, check.Commentf("run top1: %v", out))
|
|
|
|
|
|
|
|
out, err = s.d.Cmd("run", "-d", "--name", "top2", "--restart", "unless-stopped", "busybox:latest", "top")
|
|
|
|
c.Assert(err, check.IsNil, check.Commentf("run top2: %v", out))
|
|
|
|
|
|
|
|
testRun := func(m map[string]bool, prefix string) {
|
|
|
|
var format string
|
|
|
|
for name, shouldRun := range m {
|
|
|
|
out, err := s.d.Cmd("ps")
|
|
|
|
c.Assert(err, check.IsNil, check.Commentf("run ps: %v", out))
|
|
|
|
if shouldRun {
|
|
|
|
format = "%scontainer %q is not running"
|
|
|
|
} else {
|
|
|
|
format = "%scontainer %q is running"
|
|
|
|
}
|
|
|
|
c.Assert(strings.Contains(out, name), check.Equals, shouldRun, check.Commentf(format, prefix, name))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// both running
|
|
|
|
testRun(map[string]bool{"top1": true, "top2": true}, "")
|
|
|
|
|
|
|
|
out, err = s.d.Cmd("stop", "top1")
|
|
|
|
c.Assert(err, check.IsNil, check.Commentf(out))
|
|
|
|
|
|
|
|
out, err = s.d.Cmd("stop", "top2")
|
|
|
|
c.Assert(err, check.IsNil, check.Commentf(out))
|
|
|
|
|
|
|
|
// both stopped
|
|
|
|
testRun(map[string]bool{"top1": false, "top2": false}, "")
|
|
|
|
|
|
|
|
err = s.d.Restart()
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
|
|
|
|
// restart=always running
|
|
|
|
testRun(map[string]bool{"top1": true, "top2": false}, "After daemon restart: ")
|
|
|
|
|
|
|
|
out, err = s.d.Cmd("start", "top2")
|
|
|
|
c.Assert(err, check.IsNil, check.Commentf("start top2: %v", out))
|
|
|
|
|
|
|
|
err = s.d.Restart()
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
|
|
|
|
// both running
|
|
|
|
testRun(map[string]bool{"top1": true, "top2": true}, "After second daemon restart: ")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonStartIptablesFalse(c *check.C) {
|
|
|
|
if err := s.d.Start("--iptables=false"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("we should have been able to start the daemon with passing iptables=false: %v", err)
|
2014-10-16 18:39:22 +00:00
|
|
|
}
|
|
|
|
}
|
2014-10-05 04:21:59 +00:00
|
|
|
|
|
|
|
// Issue #8444: If docker0 bridge is modified (intentionally or unintentionally) and
|
|
|
|
// no longer has an IP associated, we should gracefully handle that case and associate
|
|
|
|
// an IP with it rather than fail daemon start
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonStartBridgeWithoutIPAssociation(c *check.C) {
|
2014-10-05 04:21:59 +00:00
|
|
|
// rather than depending on brctl commands to verify docker0 is created and up
|
|
|
|
// let's start the daemon and stop it, and then make a modification to run the
|
|
|
|
// actual test
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.Start(); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not start daemon: %v", err)
|
2014-10-05 04:21:59 +00:00
|
|
|
}
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.Stop(); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not stop daemon: %v", err)
|
2014-10-05 04:21:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// now we will remove the ip from docker0 and then try starting the daemon
|
|
|
|
ipCmd := exec.Command("ip", "addr", "flush", "dev", "docker0")
|
|
|
|
stdout, stderr, _, err := runCommandWithStdoutStderr(ipCmd)
|
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("failed to remove docker0 IP association: %v, stdout: %q, stderr: %q", err, stdout, stderr)
|
2014-10-05 04:21:59 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.Start(); err != nil {
|
2014-10-05 04:21:59 +00:00
|
|
|
warning := "**WARNING: Docker bridge network in bad state--delete docker0 bridge interface to fix"
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not start daemon when docker0 has no IP address: %v\n%s", err, warning)
|
2014-10-05 04:21:59 +00:00
|
|
|
}
|
|
|
|
}
|
2014-09-30 19:18:26 +00:00
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonIptablesClean(c *check.C) {
|
|
|
|
if err := s.d.StartWithBusybox(); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not start daemon with busybox: %v", err)
|
2014-09-30 19:18:26 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if out, err := s.d.Cmd("run", "-d", "--name", "top", "-p", "80", "busybox:latest", "top"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not run top: %s, %v", out, err)
|
2014-09-30 19:18:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// get output from iptables with container running
|
|
|
|
ipTablesSearchString := "tcp dpt:80"
|
|
|
|
ipTablesCmd := exec.Command("iptables", "-nvL")
|
|
|
|
out, _, err := runCommandWithOutput(ipTablesCmd)
|
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not run iptables -nvL: %s, %v", out, err)
|
2014-09-30 19:18:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if !strings.Contains(out, ipTablesSearchString) {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("iptables output should have contained %q, but was %q", ipTablesSearchString, out)
|
2014-09-30 19:18:26 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.Stop(); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not stop daemon: %v", err)
|
2014-09-30 19:18:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// get output from iptables after restart
|
|
|
|
ipTablesCmd = exec.Command("iptables", "-nvL")
|
|
|
|
out, _, err = runCommandWithOutput(ipTablesCmd)
|
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not run iptables -nvL: %s, %v", out, err)
|
2014-09-30 19:18:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if strings.Contains(out, ipTablesSearchString) {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("iptables output should not have contained %q, but was %q", ipTablesSearchString, out)
|
2014-09-30 19:18:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonIptablesCreate(c *check.C) {
|
|
|
|
if err := s.d.StartWithBusybox(); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not start daemon with busybox: %v", err)
|
2014-09-30 19:18:26 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if out, err := s.d.Cmd("run", "-d", "--name", "top", "--restart=always", "-p", "80", "busybox:latest", "top"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not run top: %s, %v", out, err)
|
2014-09-30 19:18:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// get output from iptables with container running
|
|
|
|
ipTablesSearchString := "tcp dpt:80"
|
|
|
|
ipTablesCmd := exec.Command("iptables", "-nvL")
|
|
|
|
out, _, err := runCommandWithOutput(ipTablesCmd)
|
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not run iptables -nvL: %s, %v", out, err)
|
2014-09-30 19:18:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if !strings.Contains(out, ipTablesSearchString) {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("iptables output should have contained %q, but was %q", ipTablesSearchString, out)
|
2014-09-30 19:18:26 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.Restart(); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not restart daemon: %v", err)
|
2014-09-30 19:18:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// make sure the container is not running
|
2015-04-26 02:47:42 +00:00
|
|
|
runningOut, err := s.d.Cmd("inspect", "--format='{{.State.Running}}'", "top")
|
2014-09-30 19:18:26 +00:00
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not inspect on container: %s, %v", out, err)
|
2014-09-30 19:18:26 +00:00
|
|
|
}
|
|
|
|
if strings.TrimSpace(runningOut) != "true" {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Container should have been restarted after daemon restart. Status running should have been true but was: %q", strings.TrimSpace(runningOut))
|
2014-09-30 19:18:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// get output from iptables after restart
|
|
|
|
ipTablesCmd = exec.Command("iptables", "-nvL")
|
|
|
|
out, _, err = runCommandWithOutput(ipTablesCmd)
|
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not run iptables -nvL: %s, %v", out, err)
|
2014-09-30 19:18:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if !strings.Contains(out, ipTablesSearchString) {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("iptables output after restart should have contained %q, but was %q", ipTablesSearchString, out)
|
2014-09-30 19:18:26 +00:00
|
|
|
}
|
|
|
|
}
|
2014-10-01 13:07:24 +00:00
|
|
|
|
2015-04-28 11:50:20 +00:00
|
|
|
// TestDaemonIPv6Enabled checks that when the daemon is started with --ipv6=true that the docker0 bridge
|
|
|
|
// has the fe80::1 address and that a container is assigned a link-local address
|
|
|
|
func (s *DockerSuite) TestDaemonIPv6Enabled(c *check.C) {
|
|
|
|
testRequires(c, IPv6)
|
|
|
|
|
|
|
|
if err := setupV6(); err != nil {
|
|
|
|
c.Fatal("Could not set up host for IPv6 tests")
|
|
|
|
}
|
|
|
|
|
|
|
|
d := NewDaemon(c)
|
|
|
|
|
|
|
|
if err := d.StartWithBusybox("--ipv6"); err != nil {
|
|
|
|
c.Fatal(err)
|
|
|
|
}
|
|
|
|
defer d.Stop()
|
|
|
|
|
|
|
|
iface, err := net.InterfaceByName("docker0")
|
|
|
|
if err != nil {
|
|
|
|
c.Fatalf("Error getting docker0 interface: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
addrs, err := iface.Addrs()
|
|
|
|
if err != nil {
|
|
|
|
c.Fatalf("Error getting addresses for docker0 interface: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var found bool
|
|
|
|
expected := "fe80::1/64"
|
|
|
|
|
|
|
|
for i := range addrs {
|
|
|
|
if addrs[i].String() == expected {
|
|
|
|
found = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !found {
|
|
|
|
c.Fatalf("Bridge does not have an IPv6 Address")
|
|
|
|
}
|
|
|
|
|
|
|
|
if out, err := d.Cmd("run", "-itd", "--name=ipv6test", "busybox:latest"); err != nil {
|
|
|
|
c.Fatalf("Could not run container: %s, %v", out, err)
|
|
|
|
}
|
|
|
|
|
2015-10-27 02:35:49 +00:00
|
|
|
out, err := d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.LinkLocalIPv6Address}}'", "ipv6test")
|
2015-04-28 11:50:20 +00:00
|
|
|
out = strings.Trim(out, " \r\n'")
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
c.Fatalf("Error inspecting container: %s, %v", out, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if ip := net.ParseIP(out); ip == nil {
|
|
|
|
c.Fatalf("Container should have a link-local IPv6 address")
|
|
|
|
}
|
|
|
|
|
2015-10-27 02:35:49 +00:00
|
|
|
out, err = d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.GlobalIPv6Address}}'", "ipv6test")
|
2015-04-28 11:50:20 +00:00
|
|
|
out = strings.Trim(out, " \r\n'")
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
c.Fatalf("Error inspecting container: %s, %v", out, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if ip := net.ParseIP(out); ip != nil {
|
|
|
|
c.Fatalf("Container should not have a global IPv6 address: %v", out)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := teardownV6(); err != nil {
|
|
|
|
c.Fatal("Could not perform teardown for IPv6 tests")
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestDaemonIPv6FixedCIDR checks that when the daemon is started with --ipv6=true and a fixed CIDR
|
|
|
|
// that running containers are given a link-local and global IPv6 address
|
|
|
|
func (s *DockerSuite) TestDaemonIPv6FixedCIDR(c *check.C) {
|
|
|
|
testRequires(c, IPv6)
|
|
|
|
|
|
|
|
if err := setupV6(); err != nil {
|
|
|
|
c.Fatal("Could not set up host for IPv6 tests")
|
|
|
|
}
|
|
|
|
|
|
|
|
d := NewDaemon(c)
|
|
|
|
|
|
|
|
if err := d.StartWithBusybox("--ipv6", "--fixed-cidr-v6='2001:db8:1::/64'"); err != nil {
|
|
|
|
c.Fatalf("Could not start daemon with busybox: %v", err)
|
|
|
|
}
|
|
|
|
defer d.Stop()
|
|
|
|
|
|
|
|
if out, err := d.Cmd("run", "-itd", "--name=ipv6test", "busybox:latest"); err != nil {
|
|
|
|
c.Fatalf("Could not run container: %s, %v", out, err)
|
|
|
|
}
|
|
|
|
|
2015-10-27 02:35:49 +00:00
|
|
|
out, err := d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.LinkLocalIPv6Address}}'", "ipv6test")
|
2015-04-28 11:50:20 +00:00
|
|
|
out = strings.Trim(out, " \r\n'")
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
c.Fatalf("Error inspecting container: %s, %v", out, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if ip := net.ParseIP(out); ip == nil {
|
|
|
|
c.Fatalf("Container should have a link-local IPv6 address")
|
|
|
|
}
|
|
|
|
|
2015-10-27 02:35:49 +00:00
|
|
|
out, err = d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.GlobalIPv6Address}}'", "ipv6test")
|
2015-04-28 11:50:20 +00:00
|
|
|
out = strings.Trim(out, " \r\n'")
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
c.Fatalf("Error inspecting container: %s, %v", out, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if ip := net.ParseIP(out); ip == nil {
|
|
|
|
c.Fatalf("Container should have a global IPv6 address")
|
|
|
|
}
|
|
|
|
if err := teardownV6(); err != nil {
|
|
|
|
c.Fatal("Could not perform teardown for IPv6 tests")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-11 05:14:05 +00:00
|
|
|
// TestDaemonIPv6FixedCIDRAndMac checks that when the daemon is started with ipv6 fixed CIDR
|
|
|
|
// the running containers are given a an IPv6 address derived from the MAC address and the ipv6 fixed CIDR
|
|
|
|
func (s *DockerSuite) TestDaemonIPv6FixedCIDRAndMac(c *check.C) {
|
|
|
|
err := setupV6()
|
|
|
|
c.Assert(err, checker.IsNil)
|
|
|
|
|
|
|
|
d := NewDaemon(c)
|
|
|
|
|
|
|
|
err = d.StartWithBusybox("--ipv6", "--fixed-cidr-v6='2001:db8:1::/64'")
|
|
|
|
c.Assert(err, checker.IsNil)
|
|
|
|
defer d.Stop()
|
|
|
|
|
|
|
|
out, err := d.Cmd("run", "-itd", "--name=ipv6test", "--mac-address", "AA:BB:CC:DD:EE:FF", "busybox")
|
|
|
|
c.Assert(err, checker.IsNil)
|
|
|
|
|
|
|
|
out, err = d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.GlobalIPv6Address}}'", "ipv6test")
|
|
|
|
c.Assert(err, checker.IsNil)
|
|
|
|
c.Assert(strings.Trim(out, " \r\n'"), checker.Equals, "2001:db8:1::aabb:ccdd:eeff")
|
|
|
|
|
|
|
|
err = teardownV6()
|
|
|
|
c.Assert(err, checker.IsNil)
|
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonLogLevelWrong(c *check.C) {
|
|
|
|
c.Assert(s.d.Start("--log-level=bogus"), check.NotNil, check.Commentf("Daemon shouldn't start with wrong log level"))
|
|
|
|
}
|
2014-10-01 13:07:24 +00:00
|
|
|
|
2015-05-01 14:00:43 +00:00
|
|
|
func (s *DockerSuite) TestDaemonStartWithDaemonCommand(c *check.C) {
|
|
|
|
|
|
|
|
type kind int
|
|
|
|
|
|
|
|
const (
|
|
|
|
common kind = iota
|
|
|
|
daemon
|
|
|
|
)
|
|
|
|
|
|
|
|
var flags = []map[kind][]string{
|
|
|
|
{common: {"-l", "info"}, daemon: {"--selinux-enabled"}},
|
|
|
|
{common: {"-D"}, daemon: {"--selinux-enabled", "-r"}},
|
|
|
|
{common: {"-D"}, daemon: {"--restart"}},
|
|
|
|
{common: {"--debug"}, daemon: {"--log-driver=json-file", "--log-opt=max-size=1k"}},
|
|
|
|
}
|
|
|
|
|
|
|
|
var invalidGlobalFlags = [][]string{
|
|
|
|
//Invalid because you cannot pass daemon flags as global flags.
|
|
|
|
{"--selinux-enabled", "-l", "info"},
|
|
|
|
{"-D", "-r"},
|
|
|
|
{"--config", "/tmp"},
|
|
|
|
}
|
|
|
|
|
|
|
|
// `docker daemon -l info --selinux-enabled`
|
|
|
|
// should NOT error out
|
|
|
|
for _, f := range flags {
|
|
|
|
d := NewDaemon(c)
|
|
|
|
args := append(f[common], f[daemon]...)
|
|
|
|
if err := d.Start(args...); err != nil {
|
|
|
|
c.Fatalf("Daemon should have started successfully with %v: %v", args, err)
|
|
|
|
}
|
|
|
|
d.Stop()
|
|
|
|
}
|
|
|
|
|
|
|
|
// `docker -l info daemon --selinux-enabled`
|
|
|
|
// should error out
|
|
|
|
for _, f := range flags {
|
|
|
|
d := NewDaemon(c)
|
|
|
|
d.GlobalFlags = f[common]
|
|
|
|
if err := d.Start(f[daemon]...); err == nil {
|
|
|
|
d.Stop()
|
|
|
|
c.Fatalf("Daemon should have failed to start with docker %v daemon %v", d.GlobalFlags, f[daemon])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, f := range invalidGlobalFlags {
|
|
|
|
cmd := exec.Command(dockerBinary, append(f, "daemon")...)
|
|
|
|
errch := make(chan error)
|
|
|
|
var err error
|
|
|
|
go func() {
|
|
|
|
errch <- cmd.Run()
|
|
|
|
}()
|
|
|
|
select {
|
|
|
|
case <-time.After(time.Second):
|
|
|
|
cmd.Process.Kill()
|
|
|
|
case err = <-errch:
|
|
|
|
}
|
|
|
|
if err == nil {
|
|
|
|
c.Fatalf("Daemon should have failed to start with docker %v daemon", f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonLogLevelDebug(c *check.C) {
|
|
|
|
if err := s.d.Start("--log-level=debug"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2014-10-01 13:07:24 +00:00
|
|
|
}
|
2015-04-26 02:47:42 +00:00
|
|
|
content, _ := ioutil.ReadFile(s.d.logFile.Name())
|
2015-03-11 17:43:56 +00:00
|
|
|
if !strings.Contains(string(content), `level=debug`) {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf(`Missing level="debug" in log file:\n%s`, string(content))
|
2014-10-01 13:07:24 +00:00
|
|
|
}
|
2015-04-26 02:47:42 +00:00
|
|
|
}
|
2014-10-01 13:07:24 +00:00
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonLogLevelFatal(c *check.C) {
|
|
|
|
// we creating new daemons to create new logFile
|
|
|
|
if err := s.d.Start("--log-level=fatal"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2014-10-01 13:07:24 +00:00
|
|
|
}
|
2015-04-26 02:47:42 +00:00
|
|
|
content, _ := ioutil.ReadFile(s.d.logFile.Name())
|
2015-03-11 17:43:56 +00:00
|
|
|
if strings.Contains(string(content), `level=debug`) {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf(`Should not have level="debug" in log file:\n%s`, string(content))
|
2014-10-01 13:07:24 +00:00
|
|
|
}
|
2015-04-26 02:47:42 +00:00
|
|
|
}
|
2014-10-01 13:07:24 +00:00
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonFlagD(c *check.C) {
|
|
|
|
if err := s.d.Start("-D"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2014-10-01 13:07:24 +00:00
|
|
|
}
|
2015-04-26 02:47:42 +00:00
|
|
|
content, _ := ioutil.ReadFile(s.d.logFile.Name())
|
2015-05-14 17:07:21 +00:00
|
|
|
if !strings.Contains(string(content), `level=debug`) {
|
|
|
|
c.Fatalf(`Should have level="debug" in log file using -D:\n%s`, string(content))
|
2014-10-01 13:07:24 +00:00
|
|
|
}
|
2015-04-26 02:47:42 +00:00
|
|
|
}
|
2014-10-01 13:07:24 +00:00
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonFlagDebug(c *check.C) {
|
|
|
|
if err := s.d.Start("--debug"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2014-10-01 13:07:24 +00:00
|
|
|
}
|
2015-04-26 02:47:42 +00:00
|
|
|
content, _ := ioutil.ReadFile(s.d.logFile.Name())
|
2015-05-14 17:07:21 +00:00
|
|
|
if !strings.Contains(string(content), `level=debug`) {
|
|
|
|
c.Fatalf(`Should have level="debug" in log file using --debug:\n%s`, string(content))
|
2014-10-01 13:07:24 +00:00
|
|
|
}
|
2015-04-26 02:47:42 +00:00
|
|
|
}
|
2014-10-01 13:07:24 +00:00
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonFlagDebugLogLevelFatal(c *check.C) {
|
|
|
|
if err := s.d.Start("--debug", "--log-level=fatal"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2014-10-01 13:07:24 +00:00
|
|
|
}
|
2015-04-26 02:47:42 +00:00
|
|
|
content, _ := ioutil.ReadFile(s.d.logFile.Name())
|
2015-05-14 17:07:21 +00:00
|
|
|
if !strings.Contains(string(content), `level=debug`) {
|
|
|
|
c.Fatalf(`Should have level="debug" in log file when using both --debug and --log-level=fatal:\n%s`, string(content))
|
2014-10-01 13:07:24 +00:00
|
|
|
}
|
|
|
|
}
|
2014-11-15 04:38:02 +00:00
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonAllocatesListeningPort(c *check.C) {
|
2014-11-15 04:38:02 +00:00
|
|
|
listeningPorts := [][]string{
|
|
|
|
{"0.0.0.0", "0.0.0.0", "5678"},
|
|
|
|
{"127.0.0.1", "127.0.0.1", "1234"},
|
|
|
|
{"localhost", "127.0.0.1", "1235"},
|
|
|
|
}
|
|
|
|
|
2015-05-01 14:00:43 +00:00
|
|
|
cmdArgs := make([]string, 0, len(listeningPorts)*2)
|
2014-11-15 04:38:02 +00:00
|
|
|
for _, hostDirective := range listeningPorts {
|
|
|
|
cmdArgs = append(cmdArgs, "--host", fmt.Sprintf("tcp://%s:%s", hostDirective[0], hostDirective[2]))
|
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.StartWithBusybox(cmdArgs...); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not start daemon with busybox: %v", err)
|
2014-11-15 04:38:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, hostDirective := range listeningPorts {
|
2015-04-26 02:47:42 +00:00
|
|
|
output, err := s.d.Cmd("run", "-p", fmt.Sprintf("%s:%s:80", hostDirective[1], hostDirective[2]), "busybox", "true")
|
2014-11-15 04:38:02 +00:00
|
|
|
if err == nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Container should not start, expected port already allocated error: %q", output)
|
2014-11-15 04:38:02 +00:00
|
|
|
} else if !strings.Contains(output, "port is already allocated") {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Expected port is already allocated error: %q", output)
|
2014-11-15 04:38:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-01-16 19:48:25 +00:00
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonKeyGeneration(c *check.C) {
|
2015-01-22 18:29:15 +00:00
|
|
|
// TODO: skip or update for Windows daemon
|
2015-01-21 16:14:30 +00:00
|
|
|
os.Remove("/etc/docker/key.json")
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.Start(); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not start daemon: %v", err)
|
2015-01-21 16:14:30 +00:00
|
|
|
}
|
2015-04-26 02:47:42 +00:00
|
|
|
s.d.Stop()
|
2015-01-21 16:14:30 +00:00
|
|
|
|
|
|
|
k, err := libtrust.LoadKeyFile("/etc/docker/key.json")
|
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Error opening key file")
|
2015-01-21 16:14:30 +00:00
|
|
|
}
|
|
|
|
kid := k.KeyID()
|
|
|
|
// Test Key ID is a valid fingerprint (e.g. QQXN:JY5W:TBXI:MK3X:GX6P:PD5D:F56N:NHCS:LVRZ:JA46:R24J:XEFF)
|
|
|
|
if len(kid) != 59 {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Bad key ID: %s", kid)
|
2015-01-21 16:14:30 +00:00
|
|
|
}
|
|
|
|
}
|
2015-01-22 18:51:04 +00:00
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonKeyMigration(c *check.C) {
|
2015-01-22 18:51:04 +00:00
|
|
|
// TODO: skip or update for Windows daemon
|
|
|
|
os.Remove("/etc/docker/key.json")
|
|
|
|
k1, err := libtrust.GenerateECP256PrivateKey()
|
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Error generating private key: %s", err)
|
2015-01-22 18:51:04 +00:00
|
|
|
}
|
2015-01-29 21:46:12 +00:00
|
|
|
if err := os.MkdirAll(filepath.Join(os.Getenv("HOME"), ".docker"), 0755); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Error creating .docker directory: %s", err)
|
2015-01-29 21:46:12 +00:00
|
|
|
}
|
2015-01-22 18:51:04 +00:00
|
|
|
if err := libtrust.SaveKey(filepath.Join(os.Getenv("HOME"), ".docker", "key.json"), k1); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Error saving private key: %s", err)
|
2015-01-22 18:51:04 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.Start(); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not start daemon: %v", err)
|
2015-01-22 18:51:04 +00:00
|
|
|
}
|
2015-04-26 02:47:42 +00:00
|
|
|
s.d.Stop()
|
2015-01-22 18:51:04 +00:00
|
|
|
|
|
|
|
k2, err := libtrust.LoadKeyFile("/etc/docker/key.json")
|
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Error opening key file")
|
2015-01-22 18:51:04 +00:00
|
|
|
}
|
|
|
|
if k1.KeyID() != k2.KeyID() {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Key not migrated")
|
2015-01-22 18:51:04 +00:00
|
|
|
}
|
|
|
|
}
|
2015-01-22 02:40:19 +00:00
|
|
|
|
2015-03-11 14:33:06 +00:00
|
|
|
// GH#11320 - verify that the daemon exits on failure properly
|
|
|
|
// Note that this explicitly tests the conflict of {-b,--bridge} and {--bip} options as the means
|
|
|
|
// to get a daemon init failure; no other tests for -b/--bip conflict are therefore required
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonExitOnFailure(c *check.C) {
|
2015-03-11 14:33:06 +00:00
|
|
|
//attempt to start daemon with incorrect flags (we know -b and --bip conflict)
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.Start("--bridge", "nosuchbridge", "--bip", "1.1.1.1"); err != nil {
|
2015-03-11 14:33:06 +00:00
|
|
|
//verify we got the right error
|
|
|
|
if !strings.Contains(err.Error(), "Daemon exited and never started") {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Expected daemon not to start, got %v", err)
|
2015-03-11 14:33:06 +00:00
|
|
|
}
|
|
|
|
// look in the log and make sure we got the message that daemon is shutting down
|
2015-04-26 02:47:42 +00:00
|
|
|
runCmd := exec.Command("grep", "Error starting daemon", s.d.LogfileName())
|
2015-03-11 14:33:06 +00:00
|
|
|
if out, _, err := runCommandWithOutput(runCmd); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Expected 'Error starting daemon' message; but doesn't exist in log: %q, err: %v", out, err)
|
2015-03-11 14:33:06 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
//if we didn't get an error and the daemon is running, this is a failure
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal("Conflicting options should cause the daemon to error out with a failure")
|
2015-03-11 14:33:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-27 20:16:33 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonBridgeExternal(c *check.C) {
|
|
|
|
d := s.d
|
|
|
|
err := d.Start("--bridge", "nosuchbridge")
|
2015-04-28 23:17:00 +00:00
|
|
|
c.Assert(err, check.NotNil, check.Commentf("--bridge option with an invalid bridge should cause the daemon to fail"))
|
2015-04-29 18:41:13 +00:00
|
|
|
defer d.Restart()
|
2015-04-27 20:16:33 +00:00
|
|
|
|
|
|
|
bridgeName := "external-bridge"
|
2015-07-22 12:59:24 +00:00
|
|
|
bridgeIP := "192.169.1.1/24"
|
|
|
|
_, bridgeIPNet, _ := net.ParseCIDR(bridgeIP)
|
2015-04-27 20:16:33 +00:00
|
|
|
|
2015-07-22 12:59:24 +00:00
|
|
|
out, err := createInterface(c, "bridge", bridgeName, bridgeIP)
|
2015-04-29 18:41:13 +00:00
|
|
|
c.Assert(err, check.IsNil, check.Commentf(out))
|
|
|
|
defer deleteInterface(c, bridgeName)
|
2015-04-27 20:16:33 +00:00
|
|
|
|
|
|
|
err = d.StartWithBusybox("--bridge", bridgeName)
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
|
|
|
|
ipTablesSearchString := bridgeIPNet.String()
|
|
|
|
ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL")
|
2015-04-29 18:41:13 +00:00
|
|
|
out, _, err = runCommandWithOutput(ipTablesCmd)
|
2015-04-27 20:16:33 +00:00
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
|
|
|
|
c.Assert(strings.Contains(out, ipTablesSearchString), check.Equals, true,
|
|
|
|
check.Commentf("iptables output should have contained %q, but was %q",
|
|
|
|
ipTablesSearchString, out))
|
|
|
|
|
|
|
|
_, err = d.Cmd("run", "-d", "--name", "ExtContainer", "busybox", "top")
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
|
2015-07-22 12:59:24 +00:00
|
|
|
containerIP := d.findContainerIP("ExtContainer")
|
|
|
|
ip := net.ParseIP(containerIP)
|
2015-04-27 20:16:33 +00:00
|
|
|
c.Assert(bridgeIPNet.Contains(ip), check.Equals, true,
|
|
|
|
check.Commentf("Container IP-Address must be in the same subnet range : %s",
|
2015-07-22 12:59:24 +00:00
|
|
|
containerIP))
|
2015-04-27 20:16:33 +00:00
|
|
|
}
|
|
|
|
|
2015-04-29 18:41:13 +00:00
|
|
|
func createInterface(c *check.C, ifType string, ifName string, ipNet string) (string, error) {
|
2015-04-28 23:17:00 +00:00
|
|
|
args := []string{"link", "add", "name", ifName, "type", ifType}
|
|
|
|
ipLinkCmd := exec.Command("ip", args...)
|
|
|
|
out, _, err := runCommandWithOutput(ipLinkCmd)
|
2015-04-29 18:41:13 +00:00
|
|
|
if err != nil {
|
|
|
|
return out, err
|
|
|
|
}
|
2015-04-28 23:17:00 +00:00
|
|
|
|
|
|
|
ifCfgCmd := exec.Command("ifconfig", ifName, ipNet, "up")
|
|
|
|
out, _, err = runCommandWithOutput(ifCfgCmd)
|
2015-04-29 18:41:13 +00:00
|
|
|
return out, err
|
2015-04-28 23:17:00 +00:00
|
|
|
}
|
|
|
|
|
2015-04-29 18:41:13 +00:00
|
|
|
func deleteInterface(c *check.C, ifName string) {
|
|
|
|
ifCmd := exec.Command("ip", "link", "delete", ifName)
|
2015-04-28 23:17:00 +00:00
|
|
|
out, _, err := runCommandWithOutput(ifCmd)
|
|
|
|
c.Assert(err, check.IsNil, check.Commentf(out))
|
2015-04-28 03:36:40 +00:00
|
|
|
|
|
|
|
flushCmd := exec.Command("iptables", "-t", "nat", "--flush")
|
2015-04-28 23:17:00 +00:00
|
|
|
out, _, err = runCommandWithOutput(flushCmd)
|
|
|
|
c.Assert(err, check.IsNil, check.Commentf(out))
|
|
|
|
|
|
|
|
flushCmd = exec.Command("iptables", "--flush")
|
|
|
|
out, _, err = runCommandWithOutput(flushCmd)
|
|
|
|
c.Assert(err, check.IsNil, check.Commentf(out))
|
2015-04-28 03:36:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *DockerDaemonSuite) TestDaemonBridgeIP(c *check.C) {
|
|
|
|
// TestDaemonBridgeIP Steps
|
|
|
|
// 1. Delete the existing docker0 Bridge
|
|
|
|
// 2. Set --bip daemon configuration and start the new Docker Daemon
|
|
|
|
// 3. Check if the bip config has taken effect using ifconfig and iptables commands
|
|
|
|
// 4. Launch a Container and make sure the IP-Address is in the expected subnet
|
|
|
|
// 5. Delete the docker0 Bridge
|
2015-08-07 22:24:18 +00:00
|
|
|
// 6. Restart the Docker Daemon (via deferred action)
|
2015-04-28 03:36:40 +00:00
|
|
|
// This Restart takes care of bringing docker0 interface back to auto-assigned IP
|
|
|
|
|
|
|
|
defaultNetworkBridge := "docker0"
|
2015-04-28 17:26:59 +00:00
|
|
|
deleteInterface(c, defaultNetworkBridge)
|
2015-04-28 03:36:40 +00:00
|
|
|
|
|
|
|
d := s.d
|
|
|
|
|
2015-07-22 12:59:24 +00:00
|
|
|
bridgeIP := "192.169.1.1/24"
|
|
|
|
ip, bridgeIPNet, _ := net.ParseCIDR(bridgeIP)
|
2015-04-28 03:36:40 +00:00
|
|
|
|
2015-07-22 12:59:24 +00:00
|
|
|
err := d.StartWithBusybox("--bip", bridgeIP)
|
2015-04-28 03:36:40 +00:00
|
|
|
c.Assert(err, check.IsNil)
|
2015-04-29 18:41:13 +00:00
|
|
|
defer d.Restart()
|
2015-04-28 03:36:40 +00:00
|
|
|
|
|
|
|
ifconfigSearchString := ip.String()
|
|
|
|
ifconfigCmd := exec.Command("ifconfig", defaultNetworkBridge)
|
|
|
|
out, _, _, err := runCommandWithStdoutStderr(ifconfigCmd)
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
|
|
|
|
c.Assert(strings.Contains(out, ifconfigSearchString), check.Equals, true,
|
|
|
|
check.Commentf("ifconfig output should have contained %q, but was %q",
|
|
|
|
ifconfigSearchString, out))
|
|
|
|
|
|
|
|
ipTablesSearchString := bridgeIPNet.String()
|
|
|
|
ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL")
|
|
|
|
out, _, err = runCommandWithOutput(ipTablesCmd)
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
|
|
|
|
c.Assert(strings.Contains(out, ipTablesSearchString), check.Equals, true,
|
|
|
|
check.Commentf("iptables output should have contained %q, but was %q",
|
|
|
|
ipTablesSearchString, out))
|
|
|
|
|
|
|
|
out, err = d.Cmd("run", "-d", "--name", "test", "busybox", "top")
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
|
2015-07-22 12:59:24 +00:00
|
|
|
containerIP := d.findContainerIP("test")
|
|
|
|
ip = net.ParseIP(containerIP)
|
2015-04-28 03:36:40 +00:00
|
|
|
c.Assert(bridgeIPNet.Contains(ip), check.Equals, true,
|
|
|
|
check.Commentf("Container IP-Address must be in the same subnet range : %s",
|
2015-07-22 12:59:24 +00:00
|
|
|
containerIP))
|
2015-04-28 17:26:59 +00:00
|
|
|
deleteInterface(c, defaultNetworkBridge)
|
2015-04-28 03:36:40 +00:00
|
|
|
}
|
|
|
|
|
2015-04-16 07:09:36 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonRestartWithBridgeIPChange(c *check.C) {
|
|
|
|
if err := s.d.Start(); err != nil {
|
|
|
|
c.Fatalf("Could not start daemon: %v", err)
|
|
|
|
}
|
|
|
|
defer s.d.Restart()
|
|
|
|
if err := s.d.Stop(); err != nil {
|
|
|
|
c.Fatalf("Could not stop daemon: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// now we will change the docker0's IP and then try starting the daemon
|
|
|
|
bridgeIP := "192.169.100.1/24"
|
|
|
|
_, bridgeIPNet, _ := net.ParseCIDR(bridgeIP)
|
|
|
|
|
|
|
|
ipCmd := exec.Command("ifconfig", "docker0", bridgeIP)
|
|
|
|
stdout, stderr, _, err := runCommandWithStdoutStderr(ipCmd)
|
|
|
|
if err != nil {
|
|
|
|
c.Fatalf("failed to change docker0's IP association: %v, stdout: %q, stderr: %q", err, stdout, stderr)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := s.d.Start("--bip", bridgeIP); err != nil {
|
|
|
|
c.Fatalf("Could not start daemon: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
//check if the iptables contains new bridgeIP MASQUERADE rule
|
|
|
|
ipTablesSearchString := bridgeIPNet.String()
|
|
|
|
ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL")
|
|
|
|
out, _, err := runCommandWithOutput(ipTablesCmd)
|
|
|
|
if err != nil {
|
|
|
|
c.Fatalf("Could not run iptables -nvL: %s, %v", out, err)
|
|
|
|
}
|
|
|
|
if !strings.Contains(out, ipTablesSearchString) {
|
|
|
|
c.Fatalf("iptables output should have contained new MASQUERADE rule with IP %q, but was %q", ipTablesSearchString, out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-28 15:55:04 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr(c *check.C) {
|
|
|
|
d := s.d
|
|
|
|
|
|
|
|
bridgeName := "external-bridge"
|
2015-07-22 12:59:24 +00:00
|
|
|
bridgeIP := "192.169.1.1/24"
|
2015-04-28 15:55:04 +00:00
|
|
|
|
2015-07-22 12:59:24 +00:00
|
|
|
out, err := createInterface(c, "bridge", bridgeName, bridgeIP)
|
2015-04-29 18:41:13 +00:00
|
|
|
c.Assert(err, check.IsNil, check.Commentf(out))
|
|
|
|
defer deleteInterface(c, bridgeName)
|
2015-04-28 15:55:04 +00:00
|
|
|
|
2015-04-28 23:17:00 +00:00
|
|
|
args := []string{"--bridge", bridgeName, "--fixed-cidr", "192.169.1.0/30"}
|
2015-04-29 18:41:13 +00:00
|
|
|
err = d.StartWithBusybox(args...)
|
2015-04-28 15:55:04 +00:00
|
|
|
c.Assert(err, check.IsNil)
|
2015-04-29 18:41:13 +00:00
|
|
|
defer d.Restart()
|
2015-04-28 15:55:04 +00:00
|
|
|
|
|
|
|
for i := 0; i < 4; i++ {
|
|
|
|
cName := "Container" + strconv.Itoa(i)
|
|
|
|
out, err := d.Cmd("run", "-d", "--name", cName, "busybox", "top")
|
|
|
|
if err != nil {
|
2015-10-10 16:43:03 +00:00
|
|
|
c.Assert(strings.Contains(out, "no available IPv4 addresses"), check.Equals, true,
|
2015-04-28 15:55:04 +00:00
|
|
|
check.Commentf("Could not run a Container : %s %s", err.Error(), out))
|
|
|
|
}
|
|
|
|
}
|
2015-04-28 17:26:59 +00:00
|
|
|
}
|
|
|
|
|
2015-11-09 23:30:30 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr2(c *check.C) {
|
|
|
|
d := s.d
|
|
|
|
|
|
|
|
bridgeName := "external-bridge"
|
|
|
|
bridgeIP := "10.2.2.1/16"
|
|
|
|
|
|
|
|
out, err := createInterface(c, "bridge", bridgeName, bridgeIP)
|
|
|
|
c.Assert(err, check.IsNil, check.Commentf(out))
|
|
|
|
defer deleteInterface(c, bridgeName)
|
|
|
|
|
|
|
|
err = d.StartWithBusybox("--bip", bridgeIP, "--fixed-cidr", "10.2.2.0/24")
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
defer s.d.Restart()
|
|
|
|
|
|
|
|
out, err = d.Cmd("run", "-d", "--name", "bb", "busybox", "top")
|
|
|
|
c.Assert(err, checker.IsNil, check.Commentf(out))
|
|
|
|
defer d.Cmd("stop", "bb")
|
|
|
|
|
|
|
|
out, err = d.Cmd("exec", "bb", "/bin/sh", "-c", "ifconfig eth0 | awk '/inet addr/{print substr($2,6)}'")
|
|
|
|
c.Assert(out, checker.Equals, "10.2.2.0\n")
|
|
|
|
|
|
|
|
out, err = d.Cmd("run", "--rm", "busybox", "/bin/sh", "-c", "ifconfig eth0 | awk '/inet addr/{print substr($2,6)}'")
|
|
|
|
c.Assert(err, checker.IsNil, check.Commentf(out))
|
|
|
|
c.Assert(out, checker.Equals, "10.2.2.2\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *DockerDaemonSuite) TestDaemonBridgeFixedCIDREqualBridgeNetwork(c *check.C) {
|
2015-10-22 20:51:52 +00:00
|
|
|
d := s.d
|
|
|
|
|
|
|
|
bridgeName := "external-bridge"
|
|
|
|
bridgeIP := "172.27.42.1/16"
|
|
|
|
|
|
|
|
out, err := createInterface(c, "bridge", bridgeName, bridgeIP)
|
|
|
|
c.Assert(err, check.IsNil, check.Commentf(out))
|
|
|
|
defer deleteInterface(c, bridgeName)
|
|
|
|
|
|
|
|
err = d.StartWithBusybox("--bridge", bridgeName, "--fixed-cidr", bridgeIP)
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
defer s.d.Restart()
|
|
|
|
|
|
|
|
out, err = d.Cmd("run", "-d", "busybox", "top")
|
|
|
|
c.Assert(err, check.IsNil, check.Commentf(out))
|
|
|
|
cid1 := strings.TrimSpace(out)
|
|
|
|
defer d.Cmd("stop", cid1)
|
|
|
|
}
|
|
|
|
|
2015-06-05 05:57:59 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4Implicit(c *check.C) {
|
|
|
|
defaultNetworkBridge := "docker0"
|
|
|
|
deleteInterface(c, defaultNetworkBridge)
|
|
|
|
|
|
|
|
d := s.d
|
|
|
|
|
2015-07-22 12:59:24 +00:00
|
|
|
bridgeIP := "192.169.1.1"
|
|
|
|
bridgeIPNet := fmt.Sprintf("%s/24", bridgeIP)
|
2015-06-05 05:57:59 +00:00
|
|
|
|
2015-07-22 12:59:24 +00:00
|
|
|
err := d.StartWithBusybox("--bip", bridgeIPNet)
|
2015-06-05 05:57:59 +00:00
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
defer d.Restart()
|
|
|
|
|
2015-07-22 12:59:24 +00:00
|
|
|
expectedMessage := fmt.Sprintf("default via %s dev", bridgeIP)
|
2015-06-05 05:57:59 +00:00
|
|
|
out, err := d.Cmd("run", "busybox", "ip", "-4", "route", "list", "0/0")
|
|
|
|
c.Assert(strings.Contains(out, expectedMessage), check.Equals, true,
|
|
|
|
check.Commentf("Implicit default gateway should be bridge IP %s, but default route was '%s'",
|
2015-07-22 12:59:24 +00:00
|
|
|
bridgeIP, strings.TrimSpace(out)))
|
2015-06-05 05:57:59 +00:00
|
|
|
deleteInterface(c, defaultNetworkBridge)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4Explicit(c *check.C) {
|
|
|
|
defaultNetworkBridge := "docker0"
|
|
|
|
deleteInterface(c, defaultNetworkBridge)
|
|
|
|
|
|
|
|
d := s.d
|
|
|
|
|
2015-07-22 12:59:24 +00:00
|
|
|
bridgeIP := "192.169.1.1"
|
|
|
|
bridgeIPNet := fmt.Sprintf("%s/24", bridgeIP)
|
|
|
|
gatewayIP := "192.169.1.254"
|
2015-06-05 05:57:59 +00:00
|
|
|
|
2015-07-22 12:59:24 +00:00
|
|
|
err := d.StartWithBusybox("--bip", bridgeIPNet, "--default-gateway", gatewayIP)
|
2015-06-05 05:57:59 +00:00
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
defer d.Restart()
|
|
|
|
|
2015-07-22 12:59:24 +00:00
|
|
|
expectedMessage := fmt.Sprintf("default via %s dev", gatewayIP)
|
2015-06-05 05:57:59 +00:00
|
|
|
out, err := d.Cmd("run", "busybox", "ip", "-4", "route", "list", "0/0")
|
|
|
|
c.Assert(strings.Contains(out, expectedMessage), check.Equals, true,
|
|
|
|
check.Commentf("Explicit default gateway should be %s, but default route was '%s'",
|
2015-07-22 12:59:24 +00:00
|
|
|
gatewayIP, strings.TrimSpace(out)))
|
2015-06-05 05:57:59 +00:00
|
|
|
deleteInterface(c, defaultNetworkBridge)
|
|
|
|
}
|
|
|
|
|
2015-07-31 00:29:02 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4ExplicitOutsideContainerSubnet(c *check.C) {
|
|
|
|
defaultNetworkBridge := "docker0"
|
|
|
|
deleteInterface(c, defaultNetworkBridge)
|
|
|
|
|
|
|
|
// Program a custom default gateway outside of the container subnet, daemon should accept it and start
|
|
|
|
err := s.d.StartWithBusybox("--bip", "172.16.0.10/16", "--fixed-cidr", "172.16.1.0/24", "--default-gateway", "172.16.0.254")
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
|
|
|
|
deleteInterface(c, defaultNetworkBridge)
|
|
|
|
s.d.Restart()
|
|
|
|
}
|
|
|
|
|
2015-10-21 02:17:18 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonDefaultNetworkInvalidClusterConfig(c *check.C) {
|
2015-11-05 00:40:58 +00:00
|
|
|
testRequires(c, DaemonIsLinux, SameHostDaemon)
|
2015-10-21 02:17:18 +00:00
|
|
|
|
|
|
|
// Start daemon without docker0 bridge
|
|
|
|
defaultNetworkBridge := "docker0"
|
|
|
|
deleteInterface(c, defaultNetworkBridge)
|
|
|
|
|
|
|
|
d := NewDaemon(c)
|
|
|
|
discoveryBackend := "consul://consuladdr:consulport/some/path"
|
|
|
|
err := d.Start(fmt.Sprintf("--cluster-store=%s", discoveryBackend))
|
|
|
|
c.Assert(err, checker.IsNil)
|
|
|
|
|
|
|
|
// Start daemon with docker0 bridge
|
|
|
|
ifconfigCmd := exec.Command("ifconfig", defaultNetworkBridge)
|
|
|
|
_, err = runCommand(ifconfigCmd)
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
|
|
|
|
err = d.Restart(fmt.Sprintf("--cluster-store=%s", discoveryBackend))
|
|
|
|
c.Assert(err, checker.IsNil)
|
|
|
|
|
|
|
|
d.Stop()
|
|
|
|
}
|
|
|
|
|
2015-04-28 17:26:59 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonIP(c *check.C) {
|
|
|
|
d := s.d
|
|
|
|
|
|
|
|
ipStr := "192.170.1.1/24"
|
|
|
|
ip, _, _ := net.ParseCIDR(ipStr)
|
|
|
|
args := []string{"--ip", ip.String()}
|
|
|
|
err := d.StartWithBusybox(args...)
|
|
|
|
c.Assert(err, check.IsNil)
|
2015-04-29 18:41:13 +00:00
|
|
|
defer d.Restart()
|
2015-04-28 17:26:59 +00:00
|
|
|
|
|
|
|
out, err := d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top")
|
2015-04-28 23:17:00 +00:00
|
|
|
c.Assert(err, check.NotNil,
|
2015-04-28 17:26:59 +00:00
|
|
|
check.Commentf("Running a container must fail with an invalid --ip option"))
|
2015-09-16 16:55:14 +00:00
|
|
|
c.Assert(strings.Contains(out, "Error starting userland proxy"), check.Equals, true)
|
2015-04-28 17:26:59 +00:00
|
|
|
|
|
|
|
ifName := "dummy"
|
2015-04-29 18:41:13 +00:00
|
|
|
out, err = createInterface(c, "dummy", ifName, ipStr)
|
|
|
|
c.Assert(err, check.IsNil, check.Commentf(out))
|
|
|
|
defer deleteInterface(c, ifName)
|
2015-04-28 17:26:59 +00:00
|
|
|
|
|
|
|
_, err = d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top")
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
|
|
|
|
ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL")
|
|
|
|
out, _, err = runCommandWithOutput(ipTablesCmd)
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
|
|
|
|
regex := fmt.Sprintf("DNAT.*%s.*dpt:8000", ip.String())
|
|
|
|
matched, _ := regexp.MatchString(regex, out)
|
|
|
|
c.Assert(matched, check.Equals, true,
|
|
|
|
check.Commentf("iptables output should have contained %q, but was %q", regex, out))
|
2015-04-28 15:55:04 +00:00
|
|
|
}
|
|
|
|
|
2015-04-28 23:17:00 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonICCPing(c *check.C) {
|
|
|
|
d := s.d
|
|
|
|
|
|
|
|
bridgeName := "external-bridge"
|
2015-07-22 12:59:24 +00:00
|
|
|
bridgeIP := "192.169.1.1/24"
|
2015-04-28 23:17:00 +00:00
|
|
|
|
2015-07-22 12:59:24 +00:00
|
|
|
out, err := createInterface(c, "bridge", bridgeName, bridgeIP)
|
2015-04-29 18:41:13 +00:00
|
|
|
c.Assert(err, check.IsNil, check.Commentf(out))
|
|
|
|
defer deleteInterface(c, bridgeName)
|
2015-04-28 23:17:00 +00:00
|
|
|
|
|
|
|
args := []string{"--bridge", bridgeName, "--icc=false"}
|
2015-04-29 18:41:13 +00:00
|
|
|
err = d.StartWithBusybox(args...)
|
2015-04-28 23:17:00 +00:00
|
|
|
c.Assert(err, check.IsNil)
|
2015-04-29 18:41:13 +00:00
|
|
|
defer d.Restart()
|
2015-04-28 23:17:00 +00:00
|
|
|
|
|
|
|
ipTablesCmd := exec.Command("iptables", "-nvL", "FORWARD")
|
2015-04-29 18:41:13 +00:00
|
|
|
out, _, err = runCommandWithOutput(ipTablesCmd)
|
2015-04-28 23:17:00 +00:00
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
|
|
|
|
regex := fmt.Sprintf("DROP.*all.*%s.*%s", bridgeName, bridgeName)
|
|
|
|
matched, _ := regexp.MatchString(regex, out)
|
|
|
|
c.Assert(matched, check.Equals, true,
|
|
|
|
check.Commentf("iptables output should have contained %q, but was %q", regex, out))
|
|
|
|
|
|
|
|
// Pinging another container must fail with --icc=false
|
|
|
|
pingContainers(c, d, true)
|
|
|
|
|
|
|
|
ipStr := "192.171.1.1/24"
|
|
|
|
ip, _, _ := net.ParseCIDR(ipStr)
|
|
|
|
ifName := "icc-dummy"
|
|
|
|
|
|
|
|
createInterface(c, "dummy", ifName, ipStr)
|
|
|
|
|
|
|
|
// But, Pinging external or a Host interface must succeed
|
|
|
|
pingCmd := fmt.Sprintf("ping -c 1 %s -W 1", ip.String())
|
|
|
|
runArgs := []string{"--rm", "busybox", "sh", "-c", pingCmd}
|
|
|
|
_, err = d.Cmd("run", runArgs...)
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *DockerDaemonSuite) TestDaemonICCLinkExpose(c *check.C) {
|
|
|
|
d := s.d
|
|
|
|
|
|
|
|
bridgeName := "external-bridge"
|
2015-07-22 12:59:24 +00:00
|
|
|
bridgeIP := "192.169.1.1/24"
|
2015-04-28 23:17:00 +00:00
|
|
|
|
2015-07-22 12:59:24 +00:00
|
|
|
out, err := createInterface(c, "bridge", bridgeName, bridgeIP)
|
2015-04-29 18:41:13 +00:00
|
|
|
c.Assert(err, check.IsNil, check.Commentf(out))
|
|
|
|
defer deleteInterface(c, bridgeName)
|
2015-04-28 23:17:00 +00:00
|
|
|
|
|
|
|
args := []string{"--bridge", bridgeName, "--icc=false"}
|
2015-04-29 18:41:13 +00:00
|
|
|
err = d.StartWithBusybox(args...)
|
2015-04-28 23:17:00 +00:00
|
|
|
c.Assert(err, check.IsNil)
|
2015-04-29 18:41:13 +00:00
|
|
|
defer d.Restart()
|
2015-04-28 23:17:00 +00:00
|
|
|
|
|
|
|
ipTablesCmd := exec.Command("iptables", "-nvL", "FORWARD")
|
2015-04-29 18:41:13 +00:00
|
|
|
out, _, err = runCommandWithOutput(ipTablesCmd)
|
2015-04-28 23:17:00 +00:00
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
|
|
|
|
regex := fmt.Sprintf("DROP.*all.*%s.*%s", bridgeName, bridgeName)
|
|
|
|
matched, _ := regexp.MatchString(regex, out)
|
|
|
|
c.Assert(matched, check.Equals, true,
|
|
|
|
check.Commentf("iptables output should have contained %q, but was %q", regex, out))
|
|
|
|
|
2015-05-06 22:39:29 +00:00
|
|
|
out, err = d.Cmd("run", "-d", "--expose", "4567", "--name", "icc1", "busybox", "nc", "-l", "-p", "4567")
|
|
|
|
c.Assert(err, check.IsNil, check.Commentf(out))
|
2015-04-28 23:17:00 +00:00
|
|
|
|
|
|
|
out, err = d.Cmd("run", "--link", "icc1:icc1", "busybox", "nc", "icc1", "4567")
|
|
|
|
c.Assert(err, check.IsNil, check.Commentf(out))
|
|
|
|
}
|
|
|
|
|
2015-05-06 22:39:29 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonLinksIpTablesRulesWhenLinkAndUnlink(c *check.C) {
|
|
|
|
bridgeName := "external-bridge"
|
2015-07-22 12:59:24 +00:00
|
|
|
bridgeIP := "192.169.1.1/24"
|
2015-05-06 22:39:29 +00:00
|
|
|
|
2015-07-22 12:59:24 +00:00
|
|
|
out, err := createInterface(c, "bridge", bridgeName, bridgeIP)
|
2015-05-06 22:39:29 +00:00
|
|
|
c.Assert(err, check.IsNil, check.Commentf(out))
|
|
|
|
defer deleteInterface(c, bridgeName)
|
|
|
|
|
2015-05-01 14:00:43 +00:00
|
|
|
err = s.d.StartWithBusybox("--bridge", bridgeName, "--icc=false")
|
2015-05-06 22:39:29 +00:00
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
defer s.d.Restart()
|
|
|
|
|
|
|
|
_, err = s.d.Cmd("run", "-d", "--name", "child", "--publish", "8080:80", "busybox", "top")
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
_, err = s.d.Cmd("run", "-d", "--name", "parent", "--link", "child:http", "busybox", "top")
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
|
|
|
|
childIP := s.d.findContainerIP("child")
|
|
|
|
parentIP := s.d.findContainerIP("parent")
|
|
|
|
|
|
|
|
sourceRule := []string{"-i", bridgeName, "-o", bridgeName, "-p", "tcp", "-s", childIP, "--sport", "80", "-d", parentIP, "-j", "ACCEPT"}
|
|
|
|
destinationRule := []string{"-i", bridgeName, "-o", bridgeName, "-p", "tcp", "-s", parentIP, "--dport", "80", "-d", childIP, "-j", "ACCEPT"}
|
|
|
|
if !iptables.Exists("filter", "DOCKER", sourceRule...) || !iptables.Exists("filter", "DOCKER", destinationRule...) {
|
|
|
|
c.Fatal("Iptables rules not found")
|
|
|
|
}
|
|
|
|
|
|
|
|
s.d.Cmd("rm", "--link", "parent/http")
|
|
|
|
if iptables.Exists("filter", "DOCKER", sourceRule...) || iptables.Exists("filter", "DOCKER", destinationRule...) {
|
|
|
|
c.Fatal("Iptables rules should be removed when unlink")
|
|
|
|
}
|
|
|
|
|
|
|
|
s.d.Cmd("kill", "child")
|
|
|
|
s.d.Cmd("kill", "parent")
|
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonUlimitDefaults(c *check.C) {
|
2015-11-05 00:40:58 +00:00
|
|
|
testRequires(c, DaemonIsLinux)
|
2015-02-11 19:21:38 +00:00
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.StartWithBusybox("--default-ulimit", "nofile=42:42", "--default-ulimit", "nproc=1024:1024"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2015-02-11 19:21:38 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
out, err := s.d.Cmd("run", "--ulimit", "nproc=2048", "--name=test", "busybox", "/bin/sh", "-c", "echo $(ulimit -n); echo $(ulimit -p)")
|
2015-02-11 19:21:38 +00:00
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(out, err)
|
2015-02-11 19:21:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
outArr := strings.Split(out, "\n")
|
|
|
|
if len(outArr) < 2 {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("got unexpected output: %s", out)
|
2015-02-11 19:21:38 +00:00
|
|
|
}
|
|
|
|
nofile := strings.TrimSpace(outArr[0])
|
|
|
|
nproc := strings.TrimSpace(outArr[1])
|
|
|
|
|
|
|
|
if nofile != "42" {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("expected `ulimit -n` to be `42`, got: %s", nofile)
|
2015-02-11 19:21:38 +00:00
|
|
|
}
|
|
|
|
if nproc != "2048" {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("exepcted `ulimit -p` to be 2048, got: %s", nproc)
|
2015-02-11 19:21:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Now restart daemon with a new default
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.Restart("--default-ulimit", "nofile=43"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2015-02-11 19:21:38 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
out, err = s.d.Cmd("start", "-a", "test")
|
2015-02-11 19:21:38 +00:00
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2015-02-11 19:21:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
outArr = strings.Split(out, "\n")
|
|
|
|
if len(outArr) < 2 {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("got unexpected output: %s", out)
|
2015-02-11 19:21:38 +00:00
|
|
|
}
|
|
|
|
nofile = strings.TrimSpace(outArr[0])
|
|
|
|
nproc = strings.TrimSpace(outArr[1])
|
|
|
|
|
|
|
|
if nofile != "43" {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("expected `ulimit -n` to be `43`, got: %s", nofile)
|
2015-02-11 19:21:38 +00:00
|
|
|
}
|
|
|
|
if nproc != "2048" {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("exepcted `ulimit -p` to be 2048, got: %s", nproc)
|
2015-02-11 19:21:38 +00:00
|
|
|
}
|
|
|
|
}
|
2015-03-11 16:17:23 +00:00
|
|
|
|
|
|
|
// #11315
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonRestartRenameContainer(c *check.C) {
|
|
|
|
if err := s.d.StartWithBusybox(); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2015-03-11 16:17:23 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if out, err := s.d.Cmd("run", "--name=test", "busybox"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err, out)
|
2015-03-11 16:17:23 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if out, err := s.d.Cmd("rename", "test", "test2"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err, out)
|
2015-03-11 16:17:23 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.Restart(); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2015-03-11 16:17:23 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if out, err := s.d.Cmd("start", "test2"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err, out)
|
2015-03-11 16:17:23 +00:00
|
|
|
}
|
|
|
|
}
|
2015-02-04 21:44:52 +00:00
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefault(c *check.C) {
|
|
|
|
if err := s.d.StartWithBusybox(); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
out, err := s.d.Cmd("run", "-d", "busybox", "echo", "testline")
|
2015-02-04 21:44:52 +00:00
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(out, err)
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
id := strings.TrimSpace(out)
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if out, err := s.d.Cmd("wait", id); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(out, err)
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
2015-10-08 15:51:41 +00:00
|
|
|
logPath := filepath.Join(s.d.root, "containers", id, id+"-json.log")
|
2015-02-04 21:44:52 +00:00
|
|
|
|
|
|
|
if _, err := os.Stat(logPath); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
f, err := os.Open(logPath)
|
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
var res struct {
|
2015-03-26 03:18:42 +00:00
|
|
|
Log string `json:"log"`
|
|
|
|
Stream string `json:"stream"`
|
|
|
|
Time time.Time `json:"time"`
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
if err := json.NewDecoder(f).Decode(&res); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
if res.Log != "testline\n" {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Unexpected log line: %q, expected: %q", res.Log, "testline\n")
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
if res.Stream != "stdout" {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Unexpected stream: %q, expected: %q", res.Stream, "stdout")
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
if !time.Now().After(res.Time) {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Log time %v in future", res.Time)
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefaultOverride(c *check.C) {
|
|
|
|
if err := s.d.StartWithBusybox(); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
out, err := s.d.Cmd("run", "-d", "--log-driver=none", "busybox", "echo", "testline")
|
2015-02-04 21:44:52 +00:00
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(out, err)
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
id := strings.TrimSpace(out)
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if out, err := s.d.Cmd("wait", id); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(out, err)
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
2015-10-08 15:51:41 +00:00
|
|
|
logPath := filepath.Join(s.d.root, "containers", id, id+"-json.log")
|
2015-02-04 21:44:52 +00:00
|
|
|
|
|
|
|
if _, err := os.Stat(logPath); err == nil || !os.IsNotExist(err) {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("%s shouldn't exits, error on Stat: %s", logPath, err)
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonLoggingDriverNone(c *check.C) {
|
|
|
|
if err := s.d.StartWithBusybox("--log-driver=none"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
out, err := s.d.Cmd("run", "-d", "busybox", "echo", "testline")
|
2015-02-04 21:44:52 +00:00
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(out, err)
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
id := strings.TrimSpace(out)
|
2015-04-26 02:47:42 +00:00
|
|
|
if out, err := s.d.Cmd("wait", id); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(out, err)
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
logPath := filepath.Join(s.d.folder, "graph", "containers", id, id+"-json.log")
|
2015-02-04 21:44:52 +00:00
|
|
|
|
|
|
|
if _, err := os.Stat(logPath); err == nil || !os.IsNotExist(err) {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("%s shouldn't exits, error on Stat: %s", logPath, err)
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneOverride(c *check.C) {
|
|
|
|
if err := s.d.StartWithBusybox("--log-driver=none"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
out, err := s.d.Cmd("run", "-d", "--log-driver=json-file", "busybox", "echo", "testline")
|
2015-02-04 21:44:52 +00:00
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(out, err)
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
id := strings.TrimSpace(out)
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if out, err := s.d.Cmd("wait", id); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(out, err)
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
2015-10-08 15:51:41 +00:00
|
|
|
logPath := filepath.Join(s.d.root, "containers", id, id+"-json.log")
|
2015-02-04 21:44:52 +00:00
|
|
|
|
|
|
|
if _, err := os.Stat(logPath); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
f, err := os.Open(logPath)
|
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
var res struct {
|
2015-03-26 03:18:42 +00:00
|
|
|
Log string `json:"log"`
|
|
|
|
Stream string `json:"stream"`
|
|
|
|
Time time.Time `json:"time"`
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
if err := json.NewDecoder(f).Decode(&res); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
if res.Log != "testline\n" {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Unexpected log line: %q, expected: %q", res.Log, "testline\n")
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
if res.Stream != "stdout" {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Unexpected stream: %q, expected: %q", res.Stream, "stdout")
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
if !time.Now().After(res.Time) {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Log time %v in future", res.Time)
|
2015-02-04 21:44:52 +00:00
|
|
|
}
|
|
|
|
}
|
2015-02-06 00:24:47 +00:00
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneLogsError(c *check.C) {
|
|
|
|
if err := s.d.StartWithBusybox("--log-driver=none"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2015-02-06 00:24:47 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
out, err := s.d.Cmd("run", "-d", "busybox", "echo", "testline")
|
2015-02-06 00:24:47 +00:00
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(out, err)
|
2015-02-06 00:24:47 +00:00
|
|
|
}
|
|
|
|
id := strings.TrimSpace(out)
|
2015-04-26 02:47:42 +00:00
|
|
|
out, err = s.d.Cmd("logs", id)
|
2015-11-06 19:40:48 +00:00
|
|
|
if err == nil {
|
|
|
|
c.Fatalf("Logs should fail with 'none' driver")
|
2015-02-06 00:24:47 +00:00
|
|
|
}
|
2015-11-06 19:40:48 +00:00
|
|
|
if !strings.Contains(out, `"logs" command is supported only for "json-file" and "journald" logging drivers (got: none)`) {
|
Add log reading to the journald log driver
If a logdriver doesn't register a callback function to validate log
options, it won't be usable. Fix the journald driver by adding a dummy
validator.
Teach the client and the daemon's "logs" logic that the server can also
supply "logs" data via the "journald" driver. Update documentation and
tests that depend on error messages.
Add support for reading log data from the systemd journal to the
journald log driver. The internal logic uses a goroutine to scan the
journal for matching entries after any specified cutoff time, formats
the messages from those entries as JSONLog messages, and stuffs the
results down a pipe whose reading end we hand back to the caller.
If we are missing any of the 'linux', 'cgo', or 'journald' build tags,
however, we don't implement a reader, so the 'logs' endpoint will still
return an error.
Make the necessary changes to the build setup to ensure that support for
reading container logs from the systemd journal is built.
Rename the Jmap member of the journald logdriver's struct to "vars" to
make it non-public, and to make it easier to tell that it's just there
to hold additional variable values that we want journald to record along
with log data that we're sending to it.
In the client, don't assume that we know which logdrivers the server
implements, and remove the check that looks at the server. It's
redundant because the server already knows, and the check also makes
using older clients with newer servers (which may have new logdrivers in
them) unnecessarily hard.
When we try to "logs" and have to report that the container's logdriver
doesn't support reading, send the error message through the
might-be-a-multiplexer so that clients which are expecting multiplexed
data will be able to properly display the error, instead of tripping
over the data and printing a less helpful "Unrecognized input header"
error.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com> (github: nalind)
2015-07-23 15:02:56 +00:00
|
|
|
c.Fatalf("There should be an error about none not being a recognized log driver, got: %s", out)
|
2015-02-06 00:24:47 +00:00
|
|
|
}
|
|
|
|
}
|
2015-03-18 00:27:53 +00:00
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonDots(c *check.C) {
|
|
|
|
if err := s.d.StartWithBusybox(); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2015-03-18 00:27:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Now create 4 containers
|
2015-04-26 02:47:42 +00:00
|
|
|
if _, err := s.d.Cmd("create", "busybox"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Error creating container: %q", err)
|
2015-03-18 00:27:53 +00:00
|
|
|
}
|
2015-04-26 02:47:42 +00:00
|
|
|
if _, err := s.d.Cmd("create", "busybox"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Error creating container: %q", err)
|
2015-03-18 00:27:53 +00:00
|
|
|
}
|
2015-04-26 02:47:42 +00:00
|
|
|
if _, err := s.d.Cmd("create", "busybox"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Error creating container: %q", err)
|
2015-03-18 00:27:53 +00:00
|
|
|
}
|
2015-04-26 02:47:42 +00:00
|
|
|
if _, err := s.d.Cmd("create", "busybox"); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Error creating container: %q", err)
|
2015-03-18 00:27:53 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
s.d.Stop()
|
2015-03-18 00:27:53 +00:00
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
s.d.Start("--log-level=debug")
|
|
|
|
s.d.Stop()
|
|
|
|
content, _ := ioutil.ReadFile(s.d.logFile.Name())
|
2015-03-18 00:27:53 +00:00
|
|
|
if strings.Contains(string(content), "....") {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Debug level should not have ....\n%s", string(content))
|
2015-03-18 00:27:53 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
s.d.Start("--log-level=error")
|
|
|
|
s.d.Stop()
|
|
|
|
content, _ = ioutil.ReadFile(s.d.logFile.Name())
|
2015-03-18 00:27:53 +00:00
|
|
|
if strings.Contains(string(content), "....") {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Error level should not have ....\n%s", string(content))
|
2015-03-18 00:27:53 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
s.d.Start("--log-level=info")
|
|
|
|
s.d.Stop()
|
|
|
|
content, _ = ioutil.ReadFile(s.d.logFile.Name())
|
2015-03-18 00:27:53 +00:00
|
|
|
if !strings.Contains(string(content), "....") {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Info level should have ....\n%s", string(content))
|
2015-03-18 00:27:53 +00:00
|
|
|
}
|
|
|
|
}
|
2015-03-18 21:26:14 +00:00
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonUnixSockCleanedUp(c *check.C) {
|
2015-03-18 21:26:14 +00:00
|
|
|
dir, err := ioutil.TempDir("", "socket-cleanup-test")
|
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2015-03-18 21:26:14 +00:00
|
|
|
}
|
|
|
|
defer os.RemoveAll(dir)
|
|
|
|
|
|
|
|
sockPath := filepath.Join(dir, "docker.sock")
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.Start("--host", "unix://"+sockPath); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2015-03-18 21:26:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := os.Stat(sockPath); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal("socket does not exist")
|
2015-03-18 21:26:14 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.Stop(); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2015-03-18 21:26:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := os.Stat(sockPath); err == nil || !os.IsNotExist(err) {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal("unix socket is not cleaned up")
|
2015-03-18 21:26:14 +00:00
|
|
|
}
|
|
|
|
}
|
2015-04-06 00:57:19 +00:00
|
|
|
|
2015-04-29 11:56:45 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonWithWrongkey(c *check.C) {
|
2015-04-06 00:57:19 +00:00
|
|
|
type Config struct {
|
|
|
|
Crv string `json:"crv"`
|
|
|
|
D string `json:"d"`
|
|
|
|
Kid string `json:"kid"`
|
|
|
|
Kty string `json:"kty"`
|
|
|
|
X string `json:"x"`
|
|
|
|
Y string `json:"y"`
|
|
|
|
}
|
|
|
|
|
|
|
|
os.Remove("/etc/docker/key.json")
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.Start(); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Failed to start daemon: %v", err)
|
2015-04-06 00:57:19 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.Stop(); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not stop daemon: %v", err)
|
2015-04-06 00:57:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
config := &Config{}
|
|
|
|
bytes, err := ioutil.ReadFile("/etc/docker/key.json")
|
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Error reading key.json file: %s", err)
|
2015-04-06 00:57:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// byte[] to Data-Struct
|
|
|
|
if err := json.Unmarshal(bytes, &config); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Error Unmarshal: %s", err)
|
2015-04-06 00:57:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//replace config.Kid with the fake value
|
|
|
|
config.Kid = "VSAJ:FUYR:X3H2:B2VZ:KZ6U:CJD5:K7BX:ZXHY:UZXT:P4FT:MJWG:HRJ4"
|
|
|
|
|
|
|
|
// NEW Data-Struct to byte[]
|
|
|
|
newBytes, err := json.Marshal(&config)
|
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Error Marshal: %s", err)
|
2015-04-06 00:57:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// write back
|
|
|
|
if err := ioutil.WriteFile("/etc/docker/key.json", newBytes, 0400); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Error ioutil.WriteFile: %s", err)
|
2015-04-06 00:57:19 +00:00
|
|
|
}
|
|
|
|
|
2015-04-13 23:31:20 +00:00
|
|
|
defer os.Remove("/etc/docker/key.json")
|
2015-04-06 00:57:19 +00:00
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.Start(); err == nil {
|
2015-04-27 20:33:30 +00:00
|
|
|
c.Fatalf("It should not be successful to start daemon with wrong key: %v", err)
|
2015-04-06 00:57:19 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
content, _ := ioutil.ReadFile(s.d.logFile.Name())
|
2015-04-06 00:57:19 +00:00
|
|
|
|
|
|
|
if !strings.Contains(string(content), "Public Key ID does not match") {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal("Missing KeyID message from daemon logs")
|
2015-04-06 00:57:19 +00:00
|
|
|
}
|
|
|
|
}
|
2015-04-09 21:11:11 +00:00
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonRestartKillWait(c *check.C) {
|
|
|
|
if err := s.d.StartWithBusybox(); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not start daemon with busybox: %v", err)
|
2015-04-09 21:11:11 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
out, err := s.d.Cmd("run", "-id", "busybox", "/bin/cat")
|
2015-04-09 21:11:11 +00:00
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not run /bin/cat: err=%v\n%s", err, out)
|
2015-04-09 21:11:11 +00:00
|
|
|
}
|
|
|
|
containerID := strings.TrimSpace(out)
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if out, err := s.d.Cmd("kill", containerID); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not kill %s: err=%v\n%s", containerID, err, out)
|
2015-04-09 21:11:11 +00:00
|
|
|
}
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.Restart(); err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatalf("Could not restart daemon: %v", err)
|
2015-04-09 21:11:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
errchan := make(chan error)
|
|
|
|
go func() {
|
2015-04-26 02:47:42 +00:00
|
|
|
if out, err := s.d.Cmd("wait", containerID); err != nil {
|
2015-04-09 21:11:11 +00:00
|
|
|
errchan <- fmt.Errorf("%v:\n%s", err, out)
|
|
|
|
}
|
|
|
|
close(errchan)
|
|
|
|
}()
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-time.After(5 * time.Second):
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal("Waiting on a stopped (killed) container timed out")
|
2015-04-09 21:11:11 +00:00
|
|
|
case err := <-errchan:
|
|
|
|
if err != nil {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Fatal(err)
|
2015-04-09 21:11:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-04-20 23:21:46 +00:00
|
|
|
|
|
|
|
// TestHttpsInfo connects via two-way authenticated HTTPS to the info endpoint
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestHttpsInfo(c *check.C) {
|
2015-04-20 23:21:46 +00:00
|
|
|
const (
|
2015-05-01 14:00:43 +00:00
|
|
|
testDaemonHTTPSAddr = "tcp://localhost:4271"
|
2015-04-20 23:21:46 +00:00
|
|
|
)
|
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.Start("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-cert.pem",
|
2015-07-22 12:59:24 +00:00
|
|
|
"--tlskey", "fixtures/https/server-key.pem", "-H", testDaemonHTTPSAddr); err != nil {
|
2015-04-20 23:21:46 +00:00
|
|
|
c.Fatalf("Could not start daemon with busybox: %v", err)
|
|
|
|
}
|
|
|
|
|
2015-05-01 14:00:43 +00:00
|
|
|
daemonArgs := []string{"--host", testDaemonHTTPSAddr, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/client-cert.pem", "--tlskey", "fixtures/https/client-key.pem"}
|
2015-04-26 02:47:42 +00:00
|
|
|
out, err := s.d.CmdWithArgs(daemonArgs, "info")
|
2015-04-20 23:21:46 +00:00
|
|
|
if err != nil {
|
|
|
|
c.Fatalf("Error Occurred: %s and output: %s", err, out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-31 01:38:02 +00:00
|
|
|
// TestTlsVerify verifies that --tlsverify=false turns on tls
|
|
|
|
func (s *DockerDaemonSuite) TestTlsVerify(c *check.C) {
|
|
|
|
out, err := exec.Command(dockerBinary, "daemon", "--tlsverify=false").CombinedOutput()
|
|
|
|
if err == nil || !strings.Contains(string(out), "Could not load X509 key pair") {
|
|
|
|
c.Fatalf("Daemon should not have started due to missing certs: %v\n%s", err, string(out))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-20 23:21:46 +00:00
|
|
|
// TestHttpsInfoRogueCert connects via two-way authenticated HTTPS to the info endpoint
|
|
|
|
// by using a rogue client certificate and checks that it fails with the expected error.
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestHttpsInfoRogueCert(c *check.C) {
|
2015-04-20 23:21:46 +00:00
|
|
|
const (
|
|
|
|
errBadCertificate = "remote error: bad certificate"
|
2015-05-01 14:00:43 +00:00
|
|
|
testDaemonHTTPSAddr = "tcp://localhost:4271"
|
2015-04-20 23:21:46 +00:00
|
|
|
)
|
2015-05-01 14:00:43 +00:00
|
|
|
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.Start("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-cert.pem",
|
2015-07-22 12:59:24 +00:00
|
|
|
"--tlskey", "fixtures/https/server-key.pem", "-H", testDaemonHTTPSAddr); err != nil {
|
2015-04-20 23:21:46 +00:00
|
|
|
c.Fatalf("Could not start daemon with busybox: %v", err)
|
|
|
|
}
|
|
|
|
|
2015-05-01 14:00:43 +00:00
|
|
|
daemonArgs := []string{"--host", testDaemonHTTPSAddr, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/client-rogue-cert.pem", "--tlskey", "fixtures/https/client-rogue-key.pem"}
|
2015-04-26 02:47:42 +00:00
|
|
|
out, err := s.d.CmdWithArgs(daemonArgs, "info")
|
2015-04-20 23:21:46 +00:00
|
|
|
if err == nil || !strings.Contains(out, errBadCertificate) {
|
|
|
|
c.Fatalf("Expected err: %s, got instead: %s and output: %s", errBadCertificate, err, out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestHttpsInfoRogueServerCert connects via two-way authenticated HTTPS to the info endpoint
|
|
|
|
// which provides a rogue server certificate and checks that it fails with the expected error
|
2015-04-26 02:47:42 +00:00
|
|
|
func (s *DockerDaemonSuite) TestHttpsInfoRogueServerCert(c *check.C) {
|
2015-04-20 23:21:46 +00:00
|
|
|
const (
|
|
|
|
errCaUnknown = "x509: certificate signed by unknown authority"
|
2015-05-01 14:00:43 +00:00
|
|
|
testDaemonRogueHTTPSAddr = "tcp://localhost:4272"
|
2015-04-20 23:21:46 +00:00
|
|
|
)
|
2015-04-26 02:47:42 +00:00
|
|
|
if err := s.d.Start("--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-rogue-cert.pem",
|
2015-07-22 12:59:24 +00:00
|
|
|
"--tlskey", "fixtures/https/server-rogue-key.pem", "-H", testDaemonRogueHTTPSAddr); err != nil {
|
2015-04-20 23:21:46 +00:00
|
|
|
c.Fatalf("Could not start daemon with busybox: %v", err)
|
|
|
|
}
|
|
|
|
|
2015-05-01 14:00:43 +00:00
|
|
|
daemonArgs := []string{"--host", testDaemonRogueHTTPSAddr, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/client-rogue-cert.pem", "--tlskey", "fixtures/https/client-rogue-key.pem"}
|
2015-04-26 02:47:42 +00:00
|
|
|
out, err := s.d.CmdWithArgs(daemonArgs, "info")
|
2015-04-20 23:21:46 +00:00
|
|
|
if err == nil || !strings.Contains(out, errCaUnknown) {
|
|
|
|
c.Fatalf("Expected err: %s, got instead: %s and output: %s", errCaUnknown, err, out)
|
|
|
|
}
|
|
|
|
}
|
2015-04-28 03:36:40 +00:00
|
|
|
|
2015-04-28 23:17:00 +00:00
|
|
|
func pingContainers(c *check.C, d *Daemon, expectFailure bool) {
|
|
|
|
var dargs []string
|
|
|
|
if d != nil {
|
|
|
|
dargs = []string{"--host", d.sock()}
|
|
|
|
}
|
|
|
|
|
|
|
|
args := append(dargs, "run", "-d", "--name", "container1", "busybox", "top")
|
2015-07-20 06:55:40 +00:00
|
|
|
dockerCmd(c, args...)
|
2015-04-28 03:36:40 +00:00
|
|
|
|
2015-04-28 23:17:00 +00:00
|
|
|
args = append(dargs, "run", "--rm", "--link", "container1:alias1", "busybox", "sh", "-c")
|
2015-04-28 03:36:40 +00:00
|
|
|
pingCmd := "ping -c 1 %s -W 1"
|
2015-04-28 23:17:00 +00:00
|
|
|
args = append(args, fmt.Sprintf(pingCmd, "alias1"))
|
2015-07-27 18:13:25 +00:00
|
|
|
_, _, err := dockerCmdWithError(args...)
|
2015-04-28 23:17:00 +00:00
|
|
|
|
|
|
|
if expectFailure {
|
|
|
|
c.Assert(err, check.NotNil)
|
|
|
|
} else {
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
}
|
2015-04-28 03:36:40 +00:00
|
|
|
|
2015-04-28 23:17:00 +00:00
|
|
|
args = append(dargs, "rm", "-f", "container1")
|
2015-07-20 06:55:40 +00:00
|
|
|
dockerCmd(c, args...)
|
2015-04-28 03:36:40 +00:00
|
|
|
}
|
2015-05-07 22:35:12 +00:00
|
|
|
|
2015-05-19 16:32:19 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonRestartWithSocketAsVolume(c *check.C) {
|
2015-05-07 22:35:12 +00:00
|
|
|
c.Assert(s.d.StartWithBusybox(), check.IsNil)
|
|
|
|
|
|
|
|
socket := filepath.Join(s.d.folder, "docker.sock")
|
|
|
|
|
2015-10-05 16:32:08 +00:00
|
|
|
out, err := s.d.Cmd("run", "-d", "--restart=always", "-v", socket+":/sock", "busybox")
|
2015-05-07 22:35:12 +00:00
|
|
|
c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
|
|
|
|
c.Assert(s.d.Restart(), check.IsNil)
|
|
|
|
}
|
2015-05-19 16:32:19 +00:00
|
|
|
|
|
|
|
func (s *DockerDaemonSuite) TestCleanupMountsAfterCrash(c *check.C) {
|
|
|
|
c.Assert(s.d.StartWithBusybox(), check.IsNil)
|
|
|
|
|
|
|
|
out, err := s.d.Cmd("run", "-d", "busybox", "top")
|
|
|
|
c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
|
|
|
|
id := strings.TrimSpace(out)
|
|
|
|
c.Assert(s.d.cmd.Process.Signal(os.Kill), check.IsNil)
|
|
|
|
c.Assert(s.d.Start(), check.IsNil)
|
2015-08-26 12:00:01 +00:00
|
|
|
mountOut, err := ioutil.ReadFile("/proc/self/mountinfo")
|
2015-05-19 16:32:19 +00:00
|
|
|
c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut))
|
2015-08-26 12:00:01 +00:00
|
|
|
|
|
|
|
comment := check.Commentf("%s is still mounted from older daemon start:\nDaemon root repository %s\n%s", id, s.d.folder, mountOut)
|
|
|
|
c.Assert(strings.Contains(string(mountOut), id), check.Equals, false, comment)
|
2015-05-19 16:32:19 +00:00
|
|
|
}
|
2015-05-24 15:26:56 +00:00
|
|
|
|
|
|
|
func (s *DockerDaemonSuite) TestRunContainerWithBridgeNone(c *check.C) {
|
2015-11-05 00:40:58 +00:00
|
|
|
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
2015-05-24 15:26:56 +00:00
|
|
|
c.Assert(s.d.StartWithBusybox("-b", "none"), check.IsNil)
|
|
|
|
|
|
|
|
out, err := s.d.Cmd("run", "--rm", "busybox", "ip", "l")
|
|
|
|
c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
|
|
|
|
c.Assert(strings.Contains(out, "eth0"), check.Equals, false,
|
2015-06-30 17:34:15 +00:00
|
|
|
check.Commentf("There shouldn't be eth0 in container in default(bridge) mode when bridge network is disabled: %s", out))
|
|
|
|
|
|
|
|
out, err = s.d.Cmd("run", "--rm", "--net=bridge", "busybox", "ip", "l")
|
|
|
|
c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
|
|
|
|
c.Assert(strings.Contains(out, "eth0"), check.Equals, false,
|
|
|
|
check.Commentf("There shouldn't be eth0 in container in bridge mode when bridge network is disabled: %s", out))
|
2015-10-13 16:39:05 +00:00
|
|
|
// the extra grep and awk clean up the output of `ip` to only list the number and name of
|
|
|
|
// interfaces, allowing for different versions of ip (e.g. inside and outside the container) to
|
|
|
|
// be used while still verifying that the interface list is the exact same
|
|
|
|
cmd := exec.Command("sh", "-c", "ip l | grep -E '^[0-9]+:' | awk -F: ' { print $1\":\"$2 } '")
|
2015-09-19 00:49:36 +00:00
|
|
|
stdout := bytes.NewBuffer(nil)
|
|
|
|
cmd.Stdout = stdout
|
|
|
|
if err := cmd.Run(); err != nil {
|
|
|
|
c.Fatal("Failed to get host network interface")
|
|
|
|
}
|
2015-10-13 16:39:05 +00:00
|
|
|
out, err = s.d.Cmd("run", "--rm", "--net=host", "busybox", "sh", "-c", "ip l | grep -E '^[0-9]+:' | awk -F: ' { print $1\":\"$2 } '")
|
2015-06-30 17:34:15 +00:00
|
|
|
c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
|
2015-09-19 00:49:36 +00:00
|
|
|
c.Assert(out, check.Equals, fmt.Sprintf("%s", stdout),
|
|
|
|
check.Commentf("The network interfaces in container should be the same with host when --net=host when bridge network is disabled: %s", out))
|
2015-05-24 15:26:56 +00:00
|
|
|
}
|
2015-05-26 01:25:34 +00:00
|
|
|
|
|
|
|
func (s *DockerDaemonSuite) TestDaemonRestartWithContainerRunning(t *check.C) {
|
|
|
|
if err := s.d.StartWithBusybox(); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if out, err := s.d.Cmd("run", "-ti", "-d", "--name", "test", "busybox"); err != nil {
|
|
|
|
t.Fatal(out, err)
|
|
|
|
}
|
2015-06-05 22:02:56 +00:00
|
|
|
|
2015-05-26 01:25:34 +00:00
|
|
|
if err := s.d.Restart(); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
// Container 'test' should be removed without error
|
|
|
|
if out, err := s.d.Cmd("rm", "test"); err != nil {
|
|
|
|
t.Fatal(out, err)
|
|
|
|
}
|
|
|
|
}
|
2015-06-05 22:02:56 +00:00
|
|
|
|
|
|
|
func (s *DockerDaemonSuite) TestDaemonRestartCleanupNetns(c *check.C) {
|
|
|
|
if err := s.d.StartWithBusybox(); err != nil {
|
|
|
|
c.Fatal(err)
|
|
|
|
}
|
|
|
|
out, err := s.d.Cmd("run", "--name", "netns", "-d", "busybox", "top")
|
|
|
|
if err != nil {
|
|
|
|
c.Fatal(out, err)
|
|
|
|
}
|
2015-09-02 23:43:28 +00:00
|
|
|
|
|
|
|
// Get sandbox key via inspect
|
|
|
|
out, err = s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.SandboxKey}}'", "netns")
|
|
|
|
if err != nil {
|
|
|
|
c.Fatalf("Error inspecting container: %s, %v", out, err)
|
|
|
|
}
|
|
|
|
fileName := strings.Trim(out, " \r\n'")
|
|
|
|
|
2015-06-05 22:02:56 +00:00
|
|
|
if out, err := s.d.Cmd("stop", "netns"); err != nil {
|
|
|
|
c.Fatal(out, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test if the file still exists
|
2015-09-02 23:43:28 +00:00
|
|
|
out, _, err = runCommandWithOutput(exec.Command("stat", "-c", "%n", fileName))
|
2015-06-05 22:02:56 +00:00
|
|
|
out = strings.TrimSpace(out)
|
|
|
|
c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
|
2015-09-02 23:43:28 +00:00
|
|
|
c.Assert(out, check.Equals, fileName, check.Commentf("Output: %s", out))
|
2015-06-05 22:02:56 +00:00
|
|
|
|
|
|
|
// Remove the container and restart the daemon
|
|
|
|
if out, err := s.d.Cmd("rm", "netns"); err != nil {
|
|
|
|
c.Fatal(out, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := s.d.Restart(); err != nil {
|
|
|
|
c.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test again and see now the netns file does not exist
|
2015-09-02 23:43:28 +00:00
|
|
|
out, _, err = runCommandWithOutput(exec.Command("stat", "-c", "%n", fileName))
|
2015-06-05 22:02:56 +00:00
|
|
|
out = strings.TrimSpace(out)
|
|
|
|
c.Assert(err, check.Not(check.IsNil), check.Commentf("Output: %s", out))
|
|
|
|
}
|
2015-06-16 15:00:54 +00:00
|
|
|
|
|
|
|
// tests regression detailed in #13964 where DOCKER_TLS_VERIFY env is ignored
|
|
|
|
func (s *DockerDaemonSuite) TestDaemonNoTlsCliTlsVerifyWithEnv(c *check.C) {
|
|
|
|
host := "tcp://localhost:4271"
|
|
|
|
c.Assert(s.d.Start("-H", host), check.IsNil)
|
|
|
|
cmd := exec.Command(dockerBinary, "-H", host, "info")
|
|
|
|
cmd.Env = []string{"DOCKER_TLS_VERIFY=1", "DOCKER_CERT_PATH=fixtures/https"}
|
|
|
|
out, _, err := runCommandWithOutput(cmd)
|
|
|
|
c.Assert(err, check.Not(check.IsNil), check.Commentf("%s", out))
|
|
|
|
c.Assert(strings.Contains(out, "error occurred trying to connect"), check.Equals, true)
|
2015-04-28 11:50:20 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func setupV6() error {
|
|
|
|
// Hack to get the right IPv6 address on docker0, which has already been created
|
|
|
|
err := exec.Command("ip", "addr", "add", "fe80::1/64", "dev", "docker0").Run()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func teardownV6() error {
|
|
|
|
err := exec.Command("ip", "addr", "del", "fe80::1/64", "dev", "docker0").Run()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
2015-06-16 15:00:54 +00:00
|
|
|
}
|
2015-08-01 12:52:00 +00:00
|
|
|
|
|
|
|
func (s *DockerDaemonSuite) TestDaemonRestartWithContainerWithRestartPolicyAlways(c *check.C) {
|
|
|
|
c.Assert(s.d.StartWithBusybox(), check.IsNil)
|
|
|
|
|
|
|
|
out, err := s.d.Cmd("run", "-d", "--restart", "always", "busybox", "top")
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
id := strings.TrimSpace(out)
|
|
|
|
|
|
|
|
_, err = s.d.Cmd("stop", id)
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
_, err = s.d.Cmd("wait", id)
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
|
|
|
|
out, err = s.d.Cmd("ps", "-q")
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
c.Assert(out, check.Equals, "")
|
|
|
|
|
|
|
|
c.Assert(s.d.Restart(), check.IsNil)
|
|
|
|
|
|
|
|
out, err = s.d.Cmd("ps", "-q")
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
c.Assert(strings.TrimSpace(out), check.Equals, id[:12])
|
|
|
|
}
|
2015-08-17 18:38:37 +00:00
|
|
|
|
2015-08-17 22:27:44 +00:00
|
|
|
func (s *DockerDaemonSuite) TestDaemonWideLogConfig(c *check.C) {
|
2015-09-19 00:49:36 +00:00
|
|
|
if err := s.d.StartWithBusybox("--log-driver=json-file", "--log-opt=max-size=1k"); err != nil {
|
|
|
|
c.Fatal(err)
|
|
|
|
}
|
2015-08-17 22:27:44 +00:00
|
|
|
out, err := s.d.Cmd("run", "-d", "--name=logtest", "busybox", "top")
|
|
|
|
c.Assert(err, check.IsNil, check.Commentf("Output: %s, err: %v", out, err))
|
|
|
|
out, err = s.d.Cmd("inspect", "-f", "{{ .HostConfig.LogConfig.Config }}", "logtest")
|
|
|
|
c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
|
|
|
|
cfg := strings.TrimSpace(out)
|
|
|
|
if cfg != "map[max-size:1k]" {
|
|
|
|
c.Fatalf("Unexpected log-opt: %s, expected map[max-size:1k]", cfg)
|
|
|
|
}
|
|
|
|
}
|
2015-08-25 01:42:58 +00:00
|
|
|
|
|
|
|
func (s *DockerDaemonSuite) TestDaemonRestartWithPausedContainer(c *check.C) {
|
|
|
|
if err := s.d.StartWithBusybox(); err != nil {
|
|
|
|
c.Fatal(err)
|
|
|
|
}
|
|
|
|
if out, err := s.d.Cmd("run", "-i", "-d", "--name", "test", "busybox", "top"); err != nil {
|
|
|
|
c.Fatal(err, out)
|
|
|
|
}
|
|
|
|
if out, err := s.d.Cmd("pause", "test"); err != nil {
|
|
|
|
c.Fatal(err, out)
|
|
|
|
}
|
|
|
|
if err := s.d.Restart(); err != nil {
|
|
|
|
c.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
errchan := make(chan error)
|
|
|
|
go func() {
|
|
|
|
out, err := s.d.Cmd("start", "test")
|
|
|
|
if err != nil {
|
|
|
|
errchan <- fmt.Errorf("%v:\n%s", err, out)
|
|
|
|
}
|
|
|
|
name := strings.TrimSpace(out)
|
|
|
|
if name != "test" {
|
|
|
|
errchan <- fmt.Errorf("Paused container start error on docker daemon restart, expected 'test' but got '%s'", name)
|
|
|
|
}
|
|
|
|
close(errchan)
|
|
|
|
}()
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-time.After(5 * time.Second):
|
|
|
|
c.Fatal("Waiting on start a container timed out")
|
|
|
|
case err := <-errchan:
|
|
|
|
if err != nil {
|
|
|
|
c.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
2015-06-12 13:25:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *DockerDaemonSuite) TestDaemonRestartRmVolumeInUse(c *check.C) {
|
|
|
|
c.Assert(s.d.StartWithBusybox(), check.IsNil)
|
|
|
|
|
|
|
|
out, err := s.d.Cmd("create", "-v", "test:/foo", "busybox")
|
|
|
|
c.Assert(err, check.IsNil, check.Commentf(out))
|
|
|
|
|
|
|
|
c.Assert(s.d.Restart(), check.IsNil)
|
2015-08-25 01:42:58 +00:00
|
|
|
|
2015-06-12 13:25:32 +00:00
|
|
|
out, err = s.d.Cmd("volume", "rm", "test")
|
|
|
|
c.Assert(err, check.Not(check.IsNil), check.Commentf("should not be able to remove in use volume after daemon restart"))
|
|
|
|
c.Assert(strings.Contains(out, "in use"), check.Equals, true)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *DockerDaemonSuite) TestDaemonRestartLocalVolumes(c *check.C) {
|
|
|
|
c.Assert(s.d.Start(), check.IsNil)
|
|
|
|
|
|
|
|
_, err := s.d.Cmd("volume", "create", "--name", "test")
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
c.Assert(s.d.Restart(), check.IsNil)
|
|
|
|
|
|
|
|
_, err = s.d.Cmd("volume", "inspect", "test")
|
|
|
|
c.Assert(err, check.IsNil)
|
2015-08-25 01:42:58 +00:00
|
|
|
}
|
2015-09-20 11:03:09 +00:00
|
|
|
|
|
|
|
func (s *DockerDaemonSuite) TestDaemonCorruptedLogDriverAddress(c *check.C) {
|
|
|
|
for _, driver := range []string{
|
|
|
|
"syslog",
|
|
|
|
"gelf",
|
|
|
|
} {
|
|
|
|
args := []string{"--log-driver=" + driver, "--log-opt", driver + "-address=corrupted:42"}
|
|
|
|
c.Assert(s.d.Start(args...), check.NotNil, check.Commentf(fmt.Sprintf("Expected daemon not to start with invalid %s-address provided", driver)))
|
|
|
|
expected := fmt.Sprintf("Failed to set log opts: %s-address should be in form proto://address", driver)
|
|
|
|
runCmd := exec.Command("grep", expected, s.d.LogfileName())
|
|
|
|
if out, _, err := runCommandWithOutput(runCmd); err != nil {
|
|
|
|
c.Fatalf("Expected %q message; but doesn't exist in log: %q, err: %v", expected, out, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *DockerDaemonSuite) TestDaemonCorruptedFluentdAddress(c *check.C) {
|
|
|
|
c.Assert(s.d.Start("--log-driver=fluentd", "--log-opt", "fluentd-address=corrupted:c"), check.NotNil)
|
|
|
|
expected := "Failed to set log opts: invalid fluentd-address corrupted:c: "
|
|
|
|
runCmd := exec.Command("grep", expected, s.d.LogfileName())
|
|
|
|
if out, _, err := runCommandWithOutput(runCmd); err != nil {
|
|
|
|
c.Fatalf("Expected %q message; but doesn't exist in log: %q, err: %v", expected, out, err)
|
|
|
|
}
|
|
|
|
}
|
2015-10-12 08:49:25 +00:00
|
|
|
|
|
|
|
func (s *DockerDaemonSuite) TestDaemonStartWithoutHost(c *check.C) {
|
|
|
|
s.d.useDefaultHost = true
|
|
|
|
defer func() {
|
|
|
|
s.d.useDefaultHost = false
|
|
|
|
}()
|
|
|
|
c.Assert(s.d.Start(), check.IsNil)
|
|
|
|
}
|
2015-10-19 13:17:37 +00:00
|
|
|
|
|
|
|
func (s *DockerDaemonSuite) TestDaemonStartWithDefalutTlsHost(c *check.C) {
|
|
|
|
s.d.useDefaultTLSHost = true
|
|
|
|
defer func() {
|
|
|
|
s.d.useDefaultTLSHost = false
|
|
|
|
}()
|
|
|
|
if err := s.d.Start(
|
|
|
|
"--tlsverify",
|
|
|
|
"--tlscacert", "fixtures/https/ca.pem",
|
|
|
|
"--tlscert", "fixtures/https/server-cert.pem",
|
|
|
|
"--tlskey", "fixtures/https/server-key.pem"); err != nil {
|
|
|
|
c.Fatalf("Could not start daemon: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// The client with --tlsverify should also use default host localhost:2376
|
|
|
|
tmpHost := os.Getenv("DOCKER_HOST")
|
|
|
|
defer func() {
|
|
|
|
os.Setenv("DOCKER_HOST", tmpHost)
|
|
|
|
}()
|
|
|
|
|
|
|
|
os.Setenv("DOCKER_HOST", "")
|
|
|
|
|
|
|
|
out, _ := dockerCmd(
|
|
|
|
c,
|
|
|
|
"--tlsverify",
|
|
|
|
"--tlscacert", "fixtures/https/ca.pem",
|
|
|
|
"--tlscert", "fixtures/https/client-cert.pem",
|
|
|
|
"--tlskey", "fixtures/https/client-key.pem",
|
|
|
|
"version",
|
|
|
|
)
|
|
|
|
if !strings.Contains(out, "Server") {
|
|
|
|
c.Fatalf("docker version should return information of server side")
|
|
|
|
}
|
|
|
|
}
|
2015-10-25 08:36:18 +00:00
|
|
|
|
|
|
|
func (s *DockerDaemonSuite) TestBridgeIPIsExcludedFromAllocatorPool(c *check.C) {
|
|
|
|
defaultNetworkBridge := "docker0"
|
|
|
|
deleteInterface(c, defaultNetworkBridge)
|
|
|
|
|
|
|
|
bridgeIP := "192.169.1.1"
|
|
|
|
bridgeRange := bridgeIP + "/30"
|
|
|
|
|
|
|
|
err := s.d.StartWithBusybox("--bip", bridgeRange)
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
defer s.d.Restart()
|
|
|
|
|
|
|
|
var cont int
|
|
|
|
for {
|
|
|
|
contName := fmt.Sprintf("container%d", cont)
|
|
|
|
_, err = s.d.Cmd("run", "--name", contName, "-d", "busybox", "/bin/sleep", "2")
|
|
|
|
if err != nil {
|
|
|
|
// pool exhausted
|
|
|
|
break
|
|
|
|
}
|
|
|
|
ip, err := s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.IPAddress}}'", contName)
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
|
|
|
|
c.Assert(ip, check.Not(check.Equals), bridgeIP)
|
|
|
|
cont++
|
|
|
|
}
|
|
|
|
}
|
2015-11-13 05:53:35 +00:00
|
|
|
|
|
|
|
// Test daemon for no space left on device error
|
|
|
|
func (s *DockerDaemonSuite) TestDaemonNoSpaceleftOnDeviceError(c *check.C) {
|
2015-11-18 13:20:49 +00:00
|
|
|
testRequires(c, SameHostDaemon, DaemonIsLinux)
|
|
|
|
|
2015-11-13 05:53:35 +00:00
|
|
|
// create a 2MiB image and mount it as graph root
|
|
|
|
cmd := exec.Command("dd", "of=/tmp/testfs.img", "bs=1M", "seek=2", "count=0")
|
|
|
|
if err := cmd.Run(); err != nil {
|
|
|
|
c.Fatalf("dd failed: %v", err)
|
|
|
|
}
|
|
|
|
cmd = exec.Command("mkfs.ext4", "-F", "/tmp/testfs.img")
|
|
|
|
if err := cmd.Run(); err != nil {
|
|
|
|
c.Fatalf("mkfs.ext4 failed: %v", err)
|
|
|
|
}
|
|
|
|
cmd = exec.Command("mkdir", "-p", "/tmp/testfs-mount")
|
|
|
|
if err := cmd.Run(); err != nil {
|
|
|
|
c.Fatalf("mkdir failed: %v", err)
|
|
|
|
}
|
|
|
|
cmd = exec.Command("mount", "-t", "ext4", "-no", "loop,rw", "/tmp/testfs.img", "/tmp/testfs-mount")
|
|
|
|
if err := cmd.Run(); err != nil {
|
|
|
|
c.Fatalf("mount failed: %v", err)
|
|
|
|
}
|
|
|
|
err := s.d.Start("--graph", "/tmp/testfs-mount")
|
|
|
|
c.Assert(err, check.IsNil)
|
|
|
|
|
|
|
|
// pull a repository large enough to fill the mount point
|
|
|
|
out, err := s.d.Cmd("pull", "registry:2")
|
|
|
|
c.Assert(out, check.Not(check.Equals), 1, check.Commentf("no space left on device"))
|
|
|
|
}
|