006d58d7 |
// +build linux |
f3ed4228 |
|
a9971a89 |
package main
import ( |
77c725ea |
"bufio" |
0b209113 |
"bytes" |
11cf394e |
"context" |
f23c00d8 |
"crypto/tls"
"crypto/x509" |
9acf7c76 |
"encoding/json" |
7c225333 |
"fmt" |
89859917 |
"io" |
2facc046 |
"io/ioutil" |
f3f5ff9d |
"net" |
9acf7c76 |
"os" |
1262b5f6 |
"os/exec" |
2e3186ab |
"path" |
42612ff6 |
"path/filepath" |
ba11929e |
"regexp" |
0e254411 |
"strconv" |
a9971a89 |
"strings" |
19762da6 |
"sync" |
e25352a4 |
"testing" |
dd6d2cd6 |
"time" |
06af013f |
|
ddd5278b |
"github.com/cloudflare/cfssl/helpers" |
892dbfb8 |
"github.com/creack/pty" |
11cf394e |
"github.com/docker/docker/api/types" |
33968e6c |
"github.com/docker/docker/integration-cli/checker" |
50c4475d |
"github.com/docker/docker/integration-cli/cli" |
5d2afe4f |
"github.com/docker/docker/integration-cli/cli/build" |
48de91a3 |
"github.com/docker/docker/integration-cli/daemon" |
239a8a51 |
testdaemon "github.com/docker/docker/internal/test/daemon" |
ddd5278b |
"github.com/docker/docker/opts" |
59b83d8a |
"github.com/docker/docker/pkg/mount" |
f23c00d8 |
"github.com/docker/go-units" |
d18919e3 |
"github.com/docker/libnetwork/iptables" |
99cd23ce |
"github.com/docker/libtrust" |
069fdc8a |
"golang.org/x/sys/unix" |
6345208b |
"gotest.tools/assert" |
38457285 |
"gotest.tools/icmd" |
9266ff78 |
"gotest.tools/poll" |
a9971a89 |
)
|
52b60f70 |
const containerdSocket = "/var/run/docker/containerd/containerd.sock" |
34eede02 |
|
f87053b9 |
// TestLegacyDaemonCommand test starting docker daemon using "deprecated" docker daemon
// command. Remove this test when we remove this. |
64a928a3 |
func (s *DockerDaemonSuite) TestLegacyDaemonCommand(c *testing.T) { |
f87053b9 |
cmd := exec.Command(dockerBinary, "daemon", "--storage-driver=vfs", "--debug")
err := cmd.Start() |
617f89b9 |
go cmd.Wait() |
6345208b |
assert.NilError(c, err, "could not start daemon using 'docker daemon'")
assert.NilError(c, cmd.Process.Kill()) |
f87053b9 |
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartWithRunningContainersPorts(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c) |
a9971a89 |
|
50c4475d |
cli.Docker( |
eeaa6c96 |
cli.Args("run", "-d", "--name", "top1", "-p", "1234:80", "--restart", "always", "busybox:latest", "top"), |
50c4475d |
cli.Daemon(s.d),
).Assert(c, icmd.Success)
cli.Docker( |
eeaa6c96 |
cli.Args("run", "-d", "--name", "top2", "-p", "80", "busybox:latest", "top"), |
50c4475d |
cli.Daemon(s.d),
).Assert(c, icmd.Success) |
a9971a89 |
testRun := func(m map[string]bool, prefix string) {
var format string |
dc944ea7 |
for cont, shouldRun := range m { |
eeaa6c96 |
out := cli.Docker(cli.Args("ps"), cli.Daemon(s.d)).Assert(c, icmd.Success).Combined() |
a9971a89 |
if shouldRun {
format = "%scontainer %q is not running"
} else {
format = "%scontainer %q is running"
} |
dc944ea7 |
if shouldRun != strings.Contains(out, cont) {
c.Fatalf(format, prefix, cont) |
a9971a89 |
}
}
}
testRun(map[string]bool{"top1": true, "top2": true}, "")
|
c502fb49 |
s.d.Restart(c) |
a9971a89 |
testRun(map[string]bool{"top1": true, "top2": false}, "After daemon restart: ")
} |
9acf7c76 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartWithVolumesRefs(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c) |
9acf7c76 |
|
e4468913 |
if out, err := s.d.Cmd("run", "--name", "volrestarttest1", "-v", "/foo", "busybox"); err != nil { |
dc944ea7 |
c.Fatal(err, out) |
9acf7c76 |
} |
1c3cb2d3 |
|
c502fb49 |
s.d.Restart(c) |
b3b7eb27 |
|
db3576f8 |
if out, err := s.d.Cmd("run", "-d", "--volumes-from", "volrestarttest1", "--name", "volrestarttest2", "busybox", "top"); err != nil {
c.Fatal(err, out) |
9acf7c76 |
} |
1c3cb2d3 |
|
57464c32 |
if out, err := s.d.Cmd("rm", "-fv", "volrestarttest2"); err != nil { |
dc944ea7 |
c.Fatal(err, out) |
9acf7c76 |
} |
1c3cb2d3 |
out, err := s.d.Cmd("inspect", "-f", "{{json .Mounts}}", "volrestarttest1") |
6345208b |
assert.NilError(c, err, out) |
1c3cb2d3 |
if _, err := inspectMountPointJSON(out, "/foo"); err != nil {
c.Fatalf("Expected volume to exist: /foo, error: %v\n", err) |
9acf7c76 |
}
} |
3893e220 |
|
10305dc5 |
// #11008 |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartUnlessStopped(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c) |
10305dc5 |
out, err := s.d.Cmd("run", "-d", "--name", "top1", "--restart", "always", "busybox:latest", "top") |
6345208b |
assert.NilError(c, err, "run top1: %v", out) |
10305dc5 |
out, err = s.d.Cmd("run", "-d", "--name", "top2", "--restart", "unless-stopped", "busybox:latest", "top") |
6345208b |
assert.NilError(c, err, "run top2: %v", out) |
10305dc5 |
|
8e293be4 |
out, err = s.d.Cmd("run", "-d", "--name", "exit", "--restart", "unless-stopped", "busybox:latest", "false") |
6345208b |
assert.NilError(c, err, "run exit: %v", out) |
8e293be4 |
|
10305dc5 |
testRun := func(m map[string]bool, prefix string) {
var format string
for name, shouldRun := range m {
out, err := s.d.Cmd("ps") |
4cf69b99 |
assert.Assert(c, err == nil, "run ps: %v", out) |
10305dc5 |
if shouldRun {
format = "%scontainer %q is not running"
} else {
format = "%scontainer %q is running"
} |
673cf751 |
assert.Equal(c, strings.Contains(out, name), shouldRun, fmt.Sprintf(format, prefix, name)) |
10305dc5 |
}
}
// both running |
8e293be4 |
testRun(map[string]bool{"top1": true, "top2": true, "exit": true}, "")
out, err = s.d.Cmd("stop", "exit") |
6345208b |
assert.NilError(c, err, out) |
10305dc5 |
out, err = s.d.Cmd("stop", "top1") |
6345208b |
assert.NilError(c, err, out) |
10305dc5 |
out, err = s.d.Cmd("stop", "top2") |
6345208b |
assert.NilError(c, err, out) |
10305dc5 |
// both stopped |
8e293be4 |
testRun(map[string]bool{"top1": false, "top2": false, "exit": false}, "") |
10305dc5 |
|
c502fb49 |
s.d.Restart(c) |
10305dc5 |
// restart=always running |
8e293be4 |
testRun(map[string]bool{"top1": true, "top2": false, "exit": false}, "After daemon restart: ") |
10305dc5 |
out, err = s.d.Cmd("start", "top2") |
6345208b |
assert.NilError(c, err, "start top2: %v", out) |
10305dc5 |
|
8e293be4 |
out, err = s.d.Cmd("start", "exit") |
6345208b |
assert.NilError(c, err, "start exit: %v", out) |
8e293be4 |
|
c502fb49 |
s.d.Restart(c) |
10305dc5 |
// both running |
8e293be4 |
testRun(map[string]bool{"top1": true, "top2": true, "exit": true}, "After second daemon restart: ") |
10305dc5 |
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartOnFailure(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c) |
51e42e6e |
out, err := s.d.Cmd("run", "-d", "--name", "test1", "--restart", "on-failure:3", "busybox:latest", "false") |
6345208b |
assert.NilError(c, err, "run top1: %v", out) |
51e42e6e |
// wait test1 to stop |
48de91a3 |
hostArgs := []string{"--host", s.d.Sock()} |
51e42e6e |
err = waitInspectWithArgs("test1", "{{.State.Running}} {{.State.Restarting}}", "false false", 10*time.Second, hostArgs...) |
6345208b |
assert.NilError(c, err, "test1 should exit but not") |
51e42e6e |
// record last start time
out, err = s.d.Cmd("inspect", "-f={{.State.StartedAt}}", "test1") |
6345208b |
assert.NilError(c, err, "out: %v", out) |
51e42e6e |
lastStartTime := out
|
c502fb49 |
s.d.Restart(c) |
51e42e6e |
// test1 shouldn't restart at all
err = waitInspectWithArgs("test1", "{{.State.Running}} {{.State.Restarting}}", "false false", 0, hostArgs...) |
6345208b |
assert.NilError(c, err, "test1 should exit but not") |
51e42e6e |
// make sure test1 isn't restarted when daemon restart
// if "StartAt" time updates, means test1 was once restarted.
out, err = s.d.Cmd("inspect", "-f={{.State.StartedAt}}", "test1") |
6345208b |
assert.NilError(c, err, "out: %v", out)
assert.Equal(c, out, lastStartTime, "test1 shouldn't start after daemon restarts") |
51e42e6e |
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonStartIptablesFalse(c *testing.T) { |
c502fb49 |
s.d.Start(c, "--iptables=false") |
3893e220 |
} |
1262b5f6 |
|
07184599 |
// Make sure we cannot shrink base device at daemon restart. |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartWithInvalidBasesize(c *testing.T) { |
07184599 |
testRequires(c, Devicemapper) |
c502fb49 |
s.d.Start(c) |
07184599 |
|
e885af2a |
oldBasesizeBytes := getBaseDeviceSize(c, s.d) |
07184599 |
var newBasesizeBytes int64 = 1073741824 //1GB in bytes
if newBasesizeBytes < oldBasesizeBytes { |
c502fb49 |
err := s.d.RestartWithError("--storage-opt", fmt.Sprintf("dm.basesize=%d", newBasesizeBytes)) |
4cf69b99 |
assert.Assert(c, err != nil, "daemon should not have started as new base device size is less than existing base device size: %v", err) |
1d74b4f6 |
// 'err != nil' is expected behaviour, no new daemon started,
// so no need to stop daemon.
if err != nil {
return
} |
07184599 |
} |
c502fb49 |
s.d.Stop(c) |
07184599 |
}
// Make sure we can grow base device at daemon restart. |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartWithIncreasedBasesize(c *testing.T) { |
07184599 |
testRequires(c, Devicemapper) |
c502fb49 |
s.d.Start(c) |
07184599 |
|
e885af2a |
oldBasesizeBytes := getBaseDeviceSize(c, s.d) |
07184599 |
var newBasesizeBytes int64 = 53687091200 //50GB in bytes
if newBasesizeBytes < oldBasesizeBytes {
c.Skip(fmt.Sprintf("New base device size (%v) must be greater than (%s)", units.HumanSize(float64(newBasesizeBytes)), units.HumanSize(float64(oldBasesizeBytes))))
}
|
c502fb49 |
err := s.d.RestartWithError("--storage-opt", fmt.Sprintf("dm.basesize=%d", newBasesizeBytes)) |
4cf69b99 |
assert.Assert(c, err == nil, "we should have been able to start the daemon with increased base device size: %v", err) |
07184599 |
|
e885af2a |
basesizeAfterRestart := getBaseDeviceSize(c, s.d) |
07184599 |
newBasesize, err := convertBasesize(newBasesizeBytes) |
4cf69b99 |
assert.Assert(c, err == nil, "Error in converting base device size: %v", err) |
2f069fa3 |
assert.Equal(c, newBasesize, basesizeAfterRestart, "Basesize passed is not equal to Basesize set") |
c502fb49 |
s.d.Stop(c) |
07184599 |
}
|
64a928a3 |
func getBaseDeviceSize(c *testing.T, d *daemon.Daemon) int64 { |
e885af2a |
info := d.Info(c)
for _, statusLine := range info.DriverStatus {
key, value := statusLine[0], statusLine[1]
if key == "Base Device Size" {
return parseDeviceSize(c, value)
}
}
c.Fatal("failed to parse Base Device Size from info")
return int64(0)
}
|
64a928a3 |
func parseDeviceSize(c *testing.T, raw string) int64 { |
e885af2a |
size, err := units.RAMInBytes(strings.TrimSpace(raw)) |
6345208b |
assert.NilError(c, err) |
e885af2a |
return size
}
|
b2320d12 |
func convertBasesize(basesizeBytes int64) (int64, error) {
basesize := units.HumanSize(float64(basesizeBytes))
basesize = strings.Trim(basesize, " ")[:len(basesize)-3]
basesizeFloat, err := strconv.ParseFloat(strings.Trim(basesize, " "), 64)
if err != nil {
return 0, err
}
return int64(basesizeFloat) * 1024 * 1024 * 1024, nil
} |
07184599 |
|
1262b5f6 |
// 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 |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonStartBridgeWithoutIPAssociation(c *testing.T) { |
1262b5f6 |
// 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 |
c502fb49 |
s.d.Start(c)
s.d.Stop(c) |
1262b5f6 |
// now we will remove the ip from docker0 and then try starting the daemon |
def13fa2 |
icmd.RunCommand("ip", "addr", "flush", "dev", "docker0").Assert(c, icmd.Success) |
1262b5f6 |
|
c502fb49 |
if err := s.d.StartWithError(); err != nil { |
1262b5f6 |
warning := "**WARNING: Docker bridge network in bad state--delete docker0 bridge interface to fix" |
dc944ea7 |
c.Fatalf("Could not start daemon when docker0 has no IP address: %v\n%s", err, warning) |
1262b5f6 |
}
} |
d98b1179 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonIptablesClean(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c) |
d98b1179 |
|
57464c32 |
if out, err := s.d.Cmd("run", "-d", "--name", "top", "-p", "80", "busybox:latest", "top"); err != nil { |
dc944ea7 |
c.Fatalf("Could not run top: %s, %v", out, err) |
d98b1179 |
}
ipTablesSearchString := "tcp dpt:80"
|
87e3fcfe |
// get output from iptables with container running
verifyIPTablesContains(c, ipTablesSearchString) |
d98b1179 |
|
c502fb49 |
s.d.Stop(c) |
d98b1179 |
// get output from iptables after restart |
87e3fcfe |
verifyIPTablesDoesNotContains(c, ipTablesSearchString) |
d98b1179 |
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonIptablesCreate(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c) |
d98b1179 |
|
57464c32 |
if out, err := s.d.Cmd("run", "-d", "--name", "top", "--restart=always", "-p", "80", "busybox:latest", "top"); err != nil { |
dc944ea7 |
c.Fatalf("Could not run top: %s, %v", out, err) |
d98b1179 |
}
// get output from iptables with container running
ipTablesSearchString := "tcp dpt:80" |
87e3fcfe |
verifyIPTablesContains(c, ipTablesSearchString) |
d98b1179 |
|
c502fb49 |
s.d.Restart(c) |
d98b1179 |
// make sure the container is not running |
fab2a3dc |
runningOut, err := s.d.Cmd("inspect", "--format={{.State.Running}}", "top") |
d98b1179 |
if err != nil { |
87e3fcfe |
c.Fatalf("Could not inspect on container: %s, %v", runningOut, err) |
d98b1179 |
}
if strings.TrimSpace(runningOut) != "true" { |
dc944ea7 |
c.Fatalf("Container should have been restarted after daemon restart. Status running should have been true but was: %q", strings.TrimSpace(runningOut)) |
d98b1179 |
}
// get output from iptables after restart |
87e3fcfe |
verifyIPTablesContains(c, ipTablesSearchString)
}
|
64a928a3 |
func verifyIPTablesContains(c *testing.T, ipTablesSearchString string) { |
87e3fcfe |
result := icmd.RunCommand("iptables", "-nvL")
result.Assert(c, icmd.Success)
if !strings.Contains(result.Combined(), ipTablesSearchString) {
c.Fatalf("iptables output should have contained %q, but was %q", ipTablesSearchString, result.Combined()) |
d98b1179 |
} |
87e3fcfe |
} |
d98b1179 |
|
64a928a3 |
func verifyIPTablesDoesNotContains(c *testing.T, ipTablesSearchString string) { |
87e3fcfe |
result := icmd.RunCommand("iptables", "-nvL")
result.Assert(c, icmd.Success)
if strings.Contains(result.Combined(), ipTablesSearchString) {
c.Fatalf("iptables output should not have contained %q, but was %q", ipTablesSearchString, result.Combined()) |
d98b1179 |
}
} |
2facc046 |
|
2dfb7f3b |
// 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 |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonIPv6Enabled(c *testing.T) { |
2dfb7f3b |
testRequires(c, IPv6)
|
6e7405eb |
setupV6(c)
defer teardownV6(c) |
2dfb7f3b |
|
c502fb49 |
s.d.StartWithBusybox(c, "--ipv6") |
2dfb7f3b |
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 |
8928677e |
break |
2dfb7f3b |
}
}
if !found {
c.Fatalf("Bridge does not have an IPv6 Address")
}
|
5c0fd2d0 |
if out, err := s.d.Cmd("run", "-itd", "--name=ipv6test", "busybox:latest"); err != nil { |
2dfb7f3b |
c.Fatalf("Could not run container: %s, %v", out, err)
}
|
5c0fd2d0 |
out, err := s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.LinkLocalIPv6Address}}'", "ipv6test") |
2dfb7f3b |
if err != nil {
c.Fatalf("Error inspecting container: %s, %v", out, err)
} |
ac038eab |
out = strings.Trim(out, " \r\n'") |
2dfb7f3b |
if ip := net.ParseIP(out); ip == nil {
c.Fatalf("Container should have a link-local IPv6 address")
}
|
5c0fd2d0 |
out, err = s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.Networks.bridge.GlobalIPv6Address}}'", "ipv6test") |
2dfb7f3b |
if err != nil {
c.Fatalf("Error inspecting container: %s, %v", out, err)
} |
ac038eab |
out = strings.Trim(out, " \r\n'") |
2dfb7f3b |
if ip := net.ParseIP(out); ip != nil {
c.Fatalf("Container should not have a global IPv6 address: %v", out)
}
}
// 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 |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonIPv6FixedCIDR(c *testing.T) { |
a943c401 |
// IPv6 setup is messing with local bridge address. |
43b15e92 |
testRequires(c, testEnv.IsLocalDaemon) |
d5e8d8e1 |
// Delete the docker0 bridge if its left around from previous daemon. It has to be recreated with
// ipv6 enabled
deleteInterface(c, "docker0") |
2dfb7f3b |
|
c502fb49 |
s.d.StartWithBusybox(c, "--ipv6", "--fixed-cidr-v6=2001:db8:2::/64", "--default-gateway-v6=2001:db8:2::100") |
2dfb7f3b |
|
4076c57b |
out, err := s.d.Cmd("run", "-d", "--name=ipv6test", "busybox:latest", "top") |
6345208b |
assert.NilError(c, err, "Could not run container: %s, %v", out, err) |
2dfb7f3b |
|
6e7405eb |
out, err = s.d.Cmd("inspect", "--format", "{{.NetworkSettings.Networks.bridge.GlobalIPv6Address}}", "ipv6test") |
6345208b |
assert.NilError(c, err, out) |
ac038eab |
out = strings.Trim(out, " \r\n'") |
2dfb7f3b |
|
73849a5c |
ip := net.ParseIP(out) |
2f069fa3 |
assert.Assert(c, ip != nil, "Container should have a global IPv6 address") |
aa97eee1 |
|
6e7405eb |
out, err = s.d.Cmd("inspect", "--format", "{{.NetworkSettings.Networks.bridge.IPv6Gateway}}", "ipv6test") |
6345208b |
assert.NilError(c, err, out) |
73849a5c |
|
2f069fa3 |
assert.Equal(c, strings.Trim(out, " \r\n'"), "2001:db8:2::100", "Container should have a global IPv6 gateway") |
2dfb7f3b |
}
|
095a8ac5 |
// TestDaemonIPv6FixedCIDRAndMac checks that when the daemon is started with ipv6 fixed CIDR |
c1be45fa |
// the running containers are given an IPv6 address derived from the MAC address and the ipv6 fixed CIDR |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonIPv6FixedCIDRAndMac(c *testing.T) { |
a943c401 |
// IPv6 setup is messing with local bridge address. |
43b15e92 |
testRequires(c, testEnv.IsLocalDaemon) |
d5e8d8e1 |
// Delete the docker0 bridge if its left around from previous daemon. It has to be recreated with
// ipv6 enabled
deleteInterface(c, "docker0") |
095a8ac5 |
|
c502fb49 |
s.d.StartWithBusybox(c, "--ipv6", "--fixed-cidr-v6=2001:db8:1::/64") |
095a8ac5 |
|
4076c57b |
out, err := s.d.Cmd("run", "-d", "--name=ipv6test", "--mac-address", "AA:BB:CC:DD:EE:FF", "busybox", "top") |
6345208b |
assert.NilError(c, err, out) |
095a8ac5 |
|
ac038eab |
out, err = s.d.Cmd("inspect", "--format", "{{.NetworkSettings.Networks.bridge.GlobalIPv6Address}}", "ipv6test") |
6345208b |
assert.NilError(c, err, out) |
6dc7846d |
assert.Equal(c, strings.Trim(out, " \r\n'"), "2001:db8:1::aabb:ccdd:eeff") |
095a8ac5 |
}
|
010e5a22 |
// TestDaemonIPv6HostMode checks that when the running a container with
// network=host the host ipv6 addresses are not removed |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonIPv6HostMode(c *testing.T) { |
43b15e92 |
testRequires(c, testEnv.IsLocalDaemon) |
010e5a22 |
deleteInterface(c, "docker0")
s.d.StartWithBusybox(c, "--ipv6", "--fixed-cidr-v6=2001:db8:2::/64") |
4076c57b |
out, err := s.d.Cmd("run", "-d", "--name=hostcnt", "--network=host", "busybox:latest", "top") |
6345208b |
assert.NilError(c, err, "Could not run container: %s, %v", out, err) |
010e5a22 |
out, err = s.d.Cmd("exec", "hostcnt", "ip", "-6", "addr", "show", "docker0") |
6345208b |
assert.NilError(c, err, out) |
ed9449a4 |
assert.Assert(c, strings.Contains(strings.Trim(out, " \r\n'"), "2001:db8:2::1")) |
010e5a22 |
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonLogLevelWrong(c *testing.T) { |
2f069fa3 |
assert.Assert(c, s.d.StartWithError("--log-level=bogus") != nil, "Daemon shouldn't start with wrong log level") |
57464c32 |
} |
2facc046 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonLogLevelDebug(c *testing.T) { |
c502fb49 |
s.d.Start(c, "--log-level=debug") |
48de91a3 |
content, err := s.d.ReadLogFile() |
6345208b |
assert.NilError(c, err) |
89e2e5fc |
if !strings.Contains(string(content), `level=debug`) { |
dc944ea7 |
c.Fatalf(`Missing level="debug" in log file:\n%s`, string(content)) |
2facc046 |
} |
57464c32 |
} |
2facc046 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonLogLevelFatal(c *testing.T) { |
57464c32 |
// we creating new daemons to create new logFile |
c502fb49 |
s.d.Start(c, "--log-level=fatal") |
48de91a3 |
content, err := s.d.ReadLogFile() |
6345208b |
assert.NilError(c, err) |
89e2e5fc |
if strings.Contains(string(content), `level=debug`) { |
dc944ea7 |
c.Fatalf(`Should not have level="debug" in log file:\n%s`, string(content)) |
2facc046 |
} |
57464c32 |
} |
2facc046 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonFlagD(c *testing.T) { |
c502fb49 |
s.d.Start(c, "-D") |
48de91a3 |
content, err := s.d.ReadLogFile() |
6345208b |
assert.NilError(c, err) |
a85ca8b7 |
if !strings.Contains(string(content), `level=debug`) {
c.Fatalf(`Should have level="debug" in log file using -D:\n%s`, string(content)) |
2facc046 |
} |
57464c32 |
} |
2facc046 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonFlagDebug(c *testing.T) { |
c502fb49 |
s.d.Start(c, "--debug") |
48de91a3 |
content, err := s.d.ReadLogFile() |
6345208b |
assert.NilError(c, err) |
a85ca8b7 |
if !strings.Contains(string(content), `level=debug`) {
c.Fatalf(`Should have level="debug" in log file using --debug:\n%s`, string(content)) |
2facc046 |
} |
57464c32 |
} |
2facc046 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonFlagDebugLogLevelFatal(c *testing.T) { |
c502fb49 |
s.d.Start(c, "--debug", "--log-level=fatal") |
48de91a3 |
content, err := s.d.ReadLogFile() |
6345208b |
assert.NilError(c, err) |
a85ca8b7 |
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)) |
2facc046 |
}
} |
7c225333 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonAllocatesListeningPort(c *testing.T) { |
7c225333 |
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"},
}
|
e7fc6321 |
cmdArgs := make([]string, 0, len(listeningPorts)*2) |
7c225333 |
for _, hostDirective := range listeningPorts {
cmdArgs = append(cmdArgs, "--host", fmt.Sprintf("tcp://%s:%s", hostDirective[0], hostDirective[2]))
}
|
c502fb49 |
s.d.StartWithBusybox(c, cmdArgs...) |
7c225333 |
for _, hostDirective := range listeningPorts { |
57464c32 |
output, err := s.d.Cmd("run", "-p", fmt.Sprintf("%s:%s:80", hostDirective[1], hostDirective[2]), "busybox", "true") |
7c225333 |
if err == nil { |
dc944ea7 |
c.Fatalf("Container should not start, expected port already allocated error: %q", output) |
7c225333 |
} else if !strings.Contains(output, "port is already allocated") { |
dc944ea7 |
c.Fatalf("Expected port is already allocated error: %q", output) |
7c225333 |
}
}
} |
e744b0dc |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonKeyGeneration(c *testing.T) { |
99cd23ce |
// TODO: skip or update for Windows daemon
os.Remove("/etc/docker/key.json") |
21ae66c6 |
s.d.Start(c)
s.d.Stop(c)
|
99cd23ce |
k, err := libtrust.LoadKeyFile("/etc/docker/key.json") |
21ae66c6 |
if err != nil { |
99cd23ce |
c.Fatalf("Error opening key file") |
21ae66c6 |
} |
99cd23ce |
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 {
c.Fatalf("Bad key ID: %s", kid) |
21ae66c6 |
}
}
|
459e58ff |
// 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 |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonExitOnFailure(c *testing.T) { |
459e58ff |
//attempt to start daemon with incorrect flags (we know -b and --bip conflict) |
c502fb49 |
if err := s.d.StartWithError("--bridge", "nosuchbridge", "--bip", "1.1.1.1"); err != nil { |
459e58ff |
//verify we got the right error |
0f217cea |
if !strings.Contains(err.Error(), "Daemon exited") { |
dc944ea7 |
c.Fatalf("Expected daemon not to start, got %v", err) |
459e58ff |
}
// look in the log and make sure we got the message that daemon is shutting down |
bf95fbc5 |
icmd.RunCommand("grep", "failed to start daemon", s.d.LogFileName()).Assert(c, icmd.Success) |
459e58ff |
} else {
//if we didn't get an error and the daemon is running, this is a failure |
dc944ea7 |
c.Fatal("Conflicting options should cause the daemon to error out with a failure") |
459e58ff |
}
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonBridgeExternal(c *testing.T) { |
f3f5ff9d |
d := s.d |
c502fb49 |
err := d.StartWithError("--bridge", "nosuchbridge") |
6345208b |
assert.ErrorContains(c, err, "", `--bridge option with an invalid bridge should cause the daemon to fail`) |
c502fb49 |
defer d.Restart(c) |
f3f5ff9d |
bridgeName := "external-bridge" |
6b3c9281 |
bridgeIP := "192.169.1.1/24"
_, bridgeIPNet, _ := net.ParseCIDR(bridgeIP) |
f3f5ff9d |
|
87e3fcfe |
createInterface(c, "bridge", bridgeName, bridgeIP) |
1c073ec1 |
defer deleteInterface(c, bridgeName) |
f3f5ff9d |
|
c502fb49 |
d.StartWithBusybox(c, "--bridge", bridgeName) |
f3f5ff9d |
ipTablesSearchString := bridgeIPNet.String() |
87e3fcfe |
icmd.RunCommand("iptables", "-t", "nat", "-nvL").Assert(c, icmd.Expected{
Out: ipTablesSearchString,
}) |
f3f5ff9d |
|
ac038eab |
out, err := d.Cmd("run", "-d", "--name", "ExtContainer", "busybox", "top") |
6345208b |
assert.NilError(c, err, out) |
f3f5ff9d |
|
9722214c |
containerIP := d.FindContainerIP(c, "ExtContainer") |
6b3c9281 |
ip := net.ParseIP(containerIP) |
6345208b |
assert.Assert(c, bridgeIPNet.Contains(ip), "Container IP-Address must be in the same subnet range : %s", containerIP) |
f3f5ff9d |
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonBridgeNone(c *testing.T) { |
a0af884d |
// start with bridge none
d := s.d |
c502fb49 |
d.StartWithBusybox(c, "--bridge", "none")
defer d.Restart(c) |
a0af884d |
// verify docker0 iface is not there |
87e3fcfe |
icmd.RunCommand("ifconfig", "docker0").Assert(c, icmd.Expected{
ExitCode: 1,
Error: "exit status 1",
Err: "Device not found",
}) |
a0af884d |
// verify default "bridge" network is not there |
87e3fcfe |
out, err := d.Cmd("network", "inspect", "bridge") |
6345208b |
assert.ErrorContains(c, err, "", `"bridge" network should not be present if daemon started with --bridge=none`)
assert.Assert(c, strings.Contains(out, "No such network")) |
a0af884d |
}
|
64a928a3 |
func createInterface(c *testing.T, ifType string, ifName string, ipNet string) { |
87e3fcfe |
icmd.RunCommand("ip", "link", "add", "name", ifName, "type", ifType).Assert(c, icmd.Success)
icmd.RunCommand("ifconfig", ifName, ipNet, "up").Assert(c, icmd.Success) |
dd0666e6 |
}
|
64a928a3 |
func deleteInterface(c *testing.T, ifName string) { |
87e3fcfe |
icmd.RunCommand("ip", "link", "delete", ifName).Assert(c, icmd.Success)
icmd.RunCommand("iptables", "-t", "nat", "--flush").Assert(c, icmd.Success)
icmd.RunCommand("iptables", "--flush").Assert(c, icmd.Success) |
9c325c3f |
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonBridgeIP(c *testing.T) { |
9c325c3f |
// 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 |
51462327 |
// 6. Restart the Docker Daemon (via deferred action) |
9c325c3f |
// This Restart takes care of bringing docker0 interface back to auto-assigned IP
defaultNetworkBridge := "docker0" |
ba11929e |
deleteInterface(c, defaultNetworkBridge) |
9c325c3f |
d := s.d
|
6b3c9281 |
bridgeIP := "192.169.1.1/24"
ip, bridgeIPNet, _ := net.ParseCIDR(bridgeIP) |
9c325c3f |
|
c502fb49 |
d.StartWithBusybox(c, "--bip", bridgeIP)
defer d.Restart(c) |
9c325c3f |
ifconfigSearchString := ip.String() |
def13fa2 |
icmd.RunCommand("ifconfig", defaultNetworkBridge).Assert(c, icmd.Expected{
Out: ifconfigSearchString,
}) |
9c325c3f |
ipTablesSearchString := bridgeIPNet.String() |
def13fa2 |
icmd.RunCommand("iptables", "-t", "nat", "-nvL").Assert(c, icmd.Expected{
Out: ipTablesSearchString,
}) |
9c325c3f |
|
ac038eab |
out, err := d.Cmd("run", "-d", "--name", "test", "busybox", "top") |
6345208b |
assert.NilError(c, err, out) |
9c325c3f |
|
9722214c |
containerIP := d.FindContainerIP(c, "test") |
6b3c9281 |
ip = net.ParseIP(containerIP) |
673cf751 |
assert.Equal(c, bridgeIPNet.Contains(ip), true, fmt.Sprintf("Container IP-Address must be in the same subnet range : %s", containerIP)) |
ba11929e |
deleteInterface(c, defaultNetworkBridge) |
9c325c3f |
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartWithBridgeIPChange(c *testing.T) { |
c502fb49 |
s.d.Start(c)
defer s.d.Restart(c)
s.d.Stop(c) |
3ab7ceb5 |
// now we will change the docker0's IP and then try starting the daemon
bridgeIP := "192.169.100.1/24"
_, bridgeIPNet, _ := net.ParseCIDR(bridgeIP)
|
def13fa2 |
icmd.RunCommand("ifconfig", "docker0", bridgeIP).Assert(c, icmd.Success) |
3ab7ceb5 |
|
c502fb49 |
s.d.Start(c, "--bip", bridgeIP) |
3ab7ceb5 |
//check if the iptables contains new bridgeIP MASQUERADE rule
ipTablesSearchString := bridgeIPNet.String() |
def13fa2 |
icmd.RunCommand("iptables", "-t", "nat", "-nvL").Assert(c, icmd.Expected{
Out: ipTablesSearchString,
}) |
3ab7ceb5 |
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr(c *testing.T) { |
0e254411 |
d := s.d
bridgeName := "external-bridge" |
6b3c9281 |
bridgeIP := "192.169.1.1/24" |
0e254411 |
|
87e3fcfe |
createInterface(c, "bridge", bridgeName, bridgeIP) |
1c073ec1 |
defer deleteInterface(c, bridgeName) |
0e254411 |
|
dd0666e6 |
args := []string{"--bridge", bridgeName, "--fixed-cidr", "192.169.1.0/30"} |
c502fb49 |
d.StartWithBusybox(c, args...)
defer d.Restart(c) |
0e254411 |
for i := 0; i < 4; i++ {
cName := "Container" + strconv.Itoa(i)
out, err := d.Cmd("run", "-d", "--name", cName, "busybox", "top")
if err != nil { |
6345208b |
assert.Assert(c, strings.Contains(out, "no available IPv4 addresses"), "Could not run a Container : %s %s", err.Error(), out) |
0e254411 |
}
} |
ba11929e |
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr2(c *testing.T) { |
c7cd6596 |
d := s.d
bridgeName := "external-bridge"
bridgeIP := "10.2.2.1/16"
|
87e3fcfe |
createInterface(c, "bridge", bridgeName, bridgeIP) |
c7cd6596 |
defer deleteInterface(c, bridgeName)
|
c502fb49 |
d.StartWithBusybox(c, "--bip", bridgeIP, "--fixed-cidr", "10.2.2.0/24")
defer s.d.Restart(c) |
c7cd6596 |
|
87e3fcfe |
out, err := d.Cmd("run", "-d", "--name", "bb", "busybox", "top") |
6345208b |
assert.NilError(c, err, out) |
c7cd6596 |
defer d.Cmd("stop", "bb")
out, err = d.Cmd("exec", "bb", "/bin/sh", "-c", "ifconfig eth0 | awk '/inet addr/{print substr($2,6)}'") |
6345208b |
assert.NilError(c, err)
assert.Equal(c, out, "10.2.2.0\n") |
c7cd6596 |
out, err = d.Cmd("run", "--rm", "busybox", "/bin/sh", "-c", "ifconfig eth0 | awk '/inet addr/{print substr($2,6)}'") |
6345208b |
assert.NilError(c, err, out)
assert.Equal(c, out, "10.2.2.2\n") |
c7cd6596 |
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonBridgeFixedCIDREqualBridgeNetwork(c *testing.T) { |
5b538393 |
d := s.d
bridgeName := "external-bridge"
bridgeIP := "172.27.42.1/16"
|
87e3fcfe |
createInterface(c, "bridge", bridgeName, bridgeIP) |
5b538393 |
defer deleteInterface(c, bridgeName)
|
c502fb49 |
d.StartWithBusybox(c, "--bridge", bridgeName, "--fixed-cidr", bridgeIP)
defer s.d.Restart(c) |
5b538393 |
|
87e3fcfe |
out, err := d.Cmd("run", "-d", "busybox", "top") |
6345208b |
assert.NilError(c, err, out) |
5b538393 |
cid1 := strings.TrimSpace(out)
defer d.Cmd("stop", cid1)
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4Implicit(c *testing.T) { |
5fa60149 |
defaultNetworkBridge := "docker0"
deleteInterface(c, defaultNetworkBridge)
d := s.d
|
6b3c9281 |
bridgeIP := "192.169.1.1"
bridgeIPNet := fmt.Sprintf("%s/24", bridgeIP) |
5fa60149 |
|
c502fb49 |
d.StartWithBusybox(c, "--bip", bridgeIPNet)
defer d.Restart(c) |
5fa60149 |
|
6b3c9281 |
expectedMessage := fmt.Sprintf("default via %s dev", bridgeIP) |
5fa60149 |
out, err := d.Cmd("run", "busybox", "ip", "-4", "route", "list", "0/0") |
6345208b |
assert.NilError(c, err, out) |
673cf751 |
assert.Equal(c, strings.Contains(out, expectedMessage), true, fmt.Sprintf("Implicit default gateway should be bridge IP %s, but default route was '%s'", bridgeIP, strings.TrimSpace(out))) |
5fa60149 |
deleteInterface(c, defaultNetworkBridge)
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4Explicit(c *testing.T) { |
5fa60149 |
defaultNetworkBridge := "docker0"
deleteInterface(c, defaultNetworkBridge)
d := s.d
|
6b3c9281 |
bridgeIP := "192.169.1.1"
bridgeIPNet := fmt.Sprintf("%s/24", bridgeIP)
gatewayIP := "192.169.1.254" |
5fa60149 |
|
c502fb49 |
d.StartWithBusybox(c, "--bip", bridgeIPNet, "--default-gateway", gatewayIP)
defer d.Restart(c) |
5fa60149 |
|
6b3c9281 |
expectedMessage := fmt.Sprintf("default via %s dev", gatewayIP) |
5fa60149 |
out, err := d.Cmd("run", "busybox", "ip", "-4", "route", "list", "0/0") |
6345208b |
assert.NilError(c, err, out) |
673cf751 |
assert.Equal(c, strings.Contains(out, expectedMessage), true, fmt.Sprintf("Explicit default gateway should be %s, but default route was '%s'", gatewayIP, strings.TrimSpace(out))) |
5fa60149 |
deleteInterface(c, defaultNetworkBridge)
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonDefaultGatewayIPv4ExplicitOutsideContainerSubnet(c *testing.T) { |
4964ab08 |
defaultNetworkBridge := "docker0"
deleteInterface(c, defaultNetworkBridge)
// Program a custom default gateway outside of the container subnet, daemon should accept it and start |
c502fb49 |
s.d.StartWithBusybox(c, "--bip", "172.16.0.10/16", "--fixed-cidr", "172.16.1.0/24", "--default-gateway", "172.16.0.254") |
4964ab08 |
deleteInterface(c, defaultNetworkBridge) |
c502fb49 |
s.d.Restart(c) |
4964ab08 |
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonDefaultNetworkInvalidClusterConfig(c *testing.T) { |
37627427 |
// Start daemon without docker0 bridge
defaultNetworkBridge := "docker0"
deleteInterface(c, defaultNetworkBridge)
discoveryBackend := "consul://consuladdr:consulport/some/path" |
c502fb49 |
s.d.Start(c, fmt.Sprintf("--cluster-store=%s", discoveryBackend)) |
37627427 |
// Start daemon with docker0 bridge |
d7022f2b |
result := icmd.RunCommand("ifconfig", defaultNetworkBridge) |
92427b3a |
result.Assert(c, icmd.Success) |
37627427 |
|
c502fb49 |
s.d.Restart(c, fmt.Sprintf("--cluster-store=%s", discoveryBackend)) |
37627427 |
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonIP(c *testing.T) { |
ba11929e |
d := s.d
ipStr := "192.170.1.1/24"
ip, _, _ := net.ParseCIDR(ipStr)
args := []string{"--ip", ip.String()} |
c502fb49 |
d.StartWithBusybox(c, args...)
defer d.Restart(c) |
ba11929e |
out, err := d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top") |
2f069fa3 |
assert.Assert(c, err != nil, "Running a container must fail with an invalid --ip option") |
6dc7846d |
assert.Equal(c, strings.Contains(out, "Error starting userland proxy"), true) |
ba11929e |
ifName := "dummy" |
87e3fcfe |
createInterface(c, "dummy", ifName, ipStr) |
1c073ec1 |
defer deleteInterface(c, ifName) |
ba11929e |
_, err = d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top") |
6345208b |
assert.NilError(c, err, out) |
ba11929e |
|
87e3fcfe |
result := icmd.RunCommand("iptables", "-t", "nat", "-nvL")
result.Assert(c, icmd.Success) |
ba11929e |
regex := fmt.Sprintf("DNAT.*%s.*dpt:8000", ip.String()) |
87e3fcfe |
matched, _ := regexp.MatchString(regex, result.Combined()) |
673cf751 |
assert.Equal(c, matched, true, fmt.Sprintf("iptables output should have contained %q, but was %q", regex, result.Combined())) |
0e254411 |
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonICCPing(c *testing.T) { |
79843b72 |
testRequires(c, bridgeNfIptables) |
dd0666e6 |
d := s.d
bridgeName := "external-bridge" |
6b3c9281 |
bridgeIP := "192.169.1.1/24" |
dd0666e6 |
|
87e3fcfe |
createInterface(c, "bridge", bridgeName, bridgeIP) |
1c073ec1 |
defer deleteInterface(c, bridgeName) |
dd0666e6 |
|
87e3fcfe |
d.StartWithBusybox(c, "--bridge", bridgeName, "--icc=false") |
c502fb49 |
defer d.Restart(c) |
dd0666e6 |
|
87e3fcfe |
result := icmd.RunCommand("iptables", "-nvL", "FORWARD")
result.Assert(c, icmd.Success) |
dd0666e6 |
regex := fmt.Sprintf("DROP.*all.*%s.*%s", bridgeName, bridgeName) |
87e3fcfe |
matched, _ := regexp.MatchString(regex, result.Combined()) |
673cf751 |
assert.Equal(c, matched, true, fmt.Sprintf("iptables output should have contained %q, but was %q", regex, result.Combined())) |
dd0666e6 |
// 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()) |
c0d2f7b3 |
runArgs := []string{"run", "--rm", "busybox", "sh", "-c", pingCmd} |
ac038eab |
out, err := d.Cmd(runArgs...) |
6345208b |
assert.NilError(c, err, out) |
dd0666e6 |
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonICCLinkExpose(c *testing.T) { |
dd0666e6 |
d := s.d
bridgeName := "external-bridge" |
6b3c9281 |
bridgeIP := "192.169.1.1/24" |
dd0666e6 |
|
87e3fcfe |
createInterface(c, "bridge", bridgeName, bridgeIP) |
1c073ec1 |
defer deleteInterface(c, bridgeName) |
dd0666e6 |
|
87e3fcfe |
d.StartWithBusybox(c, "--bridge", bridgeName, "--icc=false") |
c502fb49 |
defer d.Restart(c) |
dd0666e6 |
|
87e3fcfe |
result := icmd.RunCommand("iptables", "-nvL", "FORWARD")
result.Assert(c, icmd.Success) |
dd0666e6 |
regex := fmt.Sprintf("DROP.*all.*%s.*%s", bridgeName, bridgeName) |
87e3fcfe |
matched, _ := regexp.MatchString(regex, result.Combined()) |
673cf751 |
assert.Equal(c, matched, true, fmt.Sprintf("iptables output should have contained %q, but was %q", regex, result.Combined())) |
87e3fcfe |
out, err := d.Cmd("run", "-d", "--expose", "4567", "--name", "icc1", "busybox", "nc", "-l", "-p", "4567") |
6345208b |
assert.NilError(c, err, out) |
dd0666e6 |
out, err = d.Cmd("run", "--link", "icc1:icc1", "busybox", "nc", "icc1", "4567") |
6345208b |
assert.NilError(c, err, out) |
dd0666e6 |
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonLinksIpTablesRulesWhenLinkAndUnlink(c *testing.T) { |
d18919e3 |
bridgeName := "external-bridge" |
6b3c9281 |
bridgeIP := "192.169.1.1/24" |
d18919e3 |
|
87e3fcfe |
createInterface(c, "bridge", bridgeName, bridgeIP) |
d18919e3 |
defer deleteInterface(c, bridgeName)
|
c502fb49 |
s.d.StartWithBusybox(c, "--bridge", bridgeName, "--icc=false")
defer s.d.Restart(c) |
d18919e3 |
|
ac038eab |
out, err := s.d.Cmd("run", "-d", "--name", "child", "--publish", "8080:80", "busybox", "top") |
6345208b |
assert.NilError(c, err, out) |
ac038eab |
out, err = s.d.Cmd("run", "-d", "--name", "parent", "--link", "child:http", "busybox", "top") |
6345208b |
assert.NilError(c, err, out) |
d18919e3 |
|
9722214c |
childIP := s.d.FindContainerIP(c, "child")
parentIP := s.d.FindContainerIP(c, "parent") |
d18919e3 |
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")
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonUlimitDefaults(c *testing.T) { |
3f390506 |
|
c502fb49 |
s.d.StartWithBusybox(c, "--default-ulimit", "nofile=42:42", "--default-ulimit", "nproc=1024:1024") |
3f390506 |
|
57464c32 |
out, err := s.d.Cmd("run", "--ulimit", "nproc=2048", "--name=test", "busybox", "/bin/sh", "-c", "echo $(ulimit -n); echo $(ulimit -p)") |
3f390506 |
if err != nil { |
ac038eab |
c.Fatal(err, out) |
3f390506 |
}
outArr := strings.Split(out, "\n")
if len(outArr) < 2 { |
dc944ea7 |
c.Fatalf("got unexpected output: %s", out) |
3f390506 |
}
nofile := strings.TrimSpace(outArr[0])
nproc := strings.TrimSpace(outArr[1])
if nofile != "42" { |
dc944ea7 |
c.Fatalf("expected `ulimit -n` to be `42`, got: %s", nofile) |
3f390506 |
}
if nproc != "2048" { |
39bcaee4 |
c.Fatalf("expected `ulimit -p` to be 2048, got: %s", nproc) |
3f390506 |
}
// Now restart daemon with a new default |
c502fb49 |
s.d.Restart(c, "--default-ulimit", "nofile=43") |
3f390506 |
|
57464c32 |
out, err = s.d.Cmd("start", "-a", "test") |
3f390506 |
if err != nil { |
ac038eab |
c.Fatal(err, out) |
3f390506 |
}
outArr = strings.Split(out, "\n")
if len(outArr) < 2 { |
dc944ea7 |
c.Fatalf("got unexpected output: %s", out) |
3f390506 |
}
nofile = strings.TrimSpace(outArr[0])
nproc = strings.TrimSpace(outArr[1])
if nofile != "43" { |
dc944ea7 |
c.Fatalf("expected `ulimit -n` to be `43`, got: %s", nofile) |
3f390506 |
}
if nproc != "2048" { |
39bcaee4 |
c.Fatalf("expected `ulimit -p` to be 2048, got: %s", nproc) |
3f390506 |
}
} |
c5c72cf1 |
// #11315 |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartRenameContainer(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c) |
c5c72cf1 |
|
57464c32 |
if out, err := s.d.Cmd("run", "--name=test", "busybox"); err != nil { |
dc944ea7 |
c.Fatal(err, out) |
c5c72cf1 |
}
|
57464c32 |
if out, err := s.d.Cmd("rename", "test", "test2"); err != nil { |
dc944ea7 |
c.Fatal(err, out) |
c5c72cf1 |
}
|
c502fb49 |
s.d.Restart(c) |
c5c72cf1 |
|
57464c32 |
if out, err := s.d.Cmd("start", "test2"); err != nil { |
dc944ea7 |
c.Fatal(err, out) |
c5c72cf1 |
}
} |
dd6d2cd6 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefault(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c) |
dd6d2cd6 |
|
e4468913 |
out, err := s.d.Cmd("run", "--name=test", "busybox", "echo", "testline") |
6345208b |
assert.NilError(c, err, out) |
48de91a3 |
id, err := s.d.GetIDByName("test") |
6345208b |
assert.NilError(c, err) |
dd6d2cd6 |
|
48de91a3 |
logPath := filepath.Join(s.d.Root, "containers", id, id+"-json.log") |
dd6d2cd6 |
if _, err := os.Stat(logPath); err != nil { |
dc944ea7 |
c.Fatal(err) |
dd6d2cd6 |
}
f, err := os.Open(logPath)
if err != nil { |
dc944ea7 |
c.Fatal(err) |
dd6d2cd6 |
} |
0ead6244 |
defer f.Close()
|
dd6d2cd6 |
var res struct { |
c5bf2145 |
Log string `json:"log"`
Stream string `json:"stream"`
Time time.Time `json:"time"` |
dd6d2cd6 |
}
if err := json.NewDecoder(f).Decode(&res); err != nil { |
dc944ea7 |
c.Fatal(err) |
dd6d2cd6 |
}
if res.Log != "testline\n" { |
dc944ea7 |
c.Fatalf("Unexpected log line: %q, expected: %q", res.Log, "testline\n") |
dd6d2cd6 |
}
if res.Stream != "stdout" { |
dc944ea7 |
c.Fatalf("Unexpected stream: %q, expected: %q", res.Stream, "stdout") |
dd6d2cd6 |
}
if !time.Now().After(res.Time) { |
dc944ea7 |
c.Fatalf("Log time %v in future", res.Time) |
dd6d2cd6 |
}
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonLoggingDriverDefaultOverride(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c) |
dd6d2cd6 |
|
e4468913 |
out, err := s.d.Cmd("run", "--name=test", "--log-driver=none", "busybox", "echo", "testline") |
dd6d2cd6 |
if err != nil { |
dc944ea7 |
c.Fatal(out, err) |
dd6d2cd6 |
} |
48de91a3 |
id, err := s.d.GetIDByName("test") |
6345208b |
assert.NilError(c, err) |
dd6d2cd6 |
|
48de91a3 |
logPath := filepath.Join(s.d.Root, "containers", id, id+"-json.log") |
dd6d2cd6 |
if _, err := os.Stat(logPath); err == nil || !os.IsNotExist(err) { |
dc944ea7 |
c.Fatalf("%s shouldn't exits, error on Stat: %s", logPath, err) |
dd6d2cd6 |
}
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonLoggingDriverNone(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c, "--log-driver=none") |
dd6d2cd6 |
|
e4468913 |
out, err := s.d.Cmd("run", "--name=test", "busybox", "echo", "testline") |
dd6d2cd6 |
if err != nil { |
dc944ea7 |
c.Fatal(out, err) |
dd6d2cd6 |
} |
48de91a3 |
id, err := s.d.GetIDByName("test") |
6345208b |
assert.NilError(c, err) |
dd6d2cd6 |
|
48de91a3 |
logPath := filepath.Join(s.d.Root, "containers", id, id+"-json.log") |
dd6d2cd6 |
if _, err := os.Stat(logPath); err == nil || !os.IsNotExist(err) { |
dc944ea7 |
c.Fatalf("%s shouldn't exits, error on Stat: %s", logPath, err) |
dd6d2cd6 |
}
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneOverride(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c, "--log-driver=none") |
dd6d2cd6 |
|
e4468913 |
out, err := s.d.Cmd("run", "--name=test", "--log-driver=json-file", "busybox", "echo", "testline") |
dd6d2cd6 |
if err != nil { |
dc944ea7 |
c.Fatal(out, err) |
dd6d2cd6 |
} |
48de91a3 |
id, err := s.d.GetIDByName("test") |
6345208b |
assert.NilError(c, err) |
dd6d2cd6 |
|
48de91a3 |
logPath := filepath.Join(s.d.Root, "containers", id, id+"-json.log") |
dd6d2cd6 |
if _, err := os.Stat(logPath); err != nil { |
dc944ea7 |
c.Fatal(err) |
dd6d2cd6 |
}
f, err := os.Open(logPath)
if err != nil { |
dc944ea7 |
c.Fatal(err) |
dd6d2cd6 |
} |
0ead6244 |
defer f.Close()
|
dd6d2cd6 |
var res struct { |
c5bf2145 |
Log string `json:"log"`
Stream string `json:"stream"`
Time time.Time `json:"time"` |
dd6d2cd6 |
}
if err := json.NewDecoder(f).Decode(&res); err != nil { |
dc944ea7 |
c.Fatal(err) |
dd6d2cd6 |
}
if res.Log != "testline\n" { |
dc944ea7 |
c.Fatalf("Unexpected log line: %q, expected: %q", res.Log, "testline\n") |
dd6d2cd6 |
}
if res.Stream != "stdout" { |
dc944ea7 |
c.Fatalf("Unexpected stream: %q, expected: %q", res.Stream, "stdout") |
dd6d2cd6 |
}
if !time.Now().After(res.Time) { |
dc944ea7 |
c.Fatalf("Log time %v in future", res.Time) |
dd6d2cd6 |
}
} |
bdf3a029 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonLoggingDriverNoneLogsError(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c, "--log-driver=none") |
bdf3a029 |
|
faf4604d |
out, err := s.d.Cmd("run", "--name=test", "busybox", "echo", "testline") |
6345208b |
assert.NilError(c, err, out) |
faf4604d |
out, err = s.d.Cmd("logs", "test") |
2f069fa3 |
assert.Assert(c, err != nil, "Logs should fail with 'none' driver") |
05dc9846 |
expected := `configured logging driver does not support reading` |
6345208b |
assert.Assert(c, strings.Contains(out, expected)) |
bdf3a029 |
} |
88dc6cc2 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonLoggingDriverShouldBeIgnoredForBuild(c *testing.T) { |
80b642ff |
s.d.StartWithBusybox(c, "--log-driver=splunk")
|
5d2afe4f |
result := cli.BuildCmd(c, "busyboxs", cli.Daemon(s.d),
build.WithDockerfile(` |
80b642ff |
FROM busybox |
5d2afe4f |
RUN echo foo`),
build.WithoutCache,
) |
673cf751 |
comment := fmt.Sprintf("Failed to build image. output %s, exitCode %d, err %v", result.Combined(), result.ExitCode, result.Error) |
ef4c63ac |
assert.Assert(c, result.Error == nil, comment) |
6dc7846d |
assert.Equal(c, result.ExitCode, 0, comment) |
ed9449a4 |
assert.Assert(c, strings.Contains(result.Combined(), "foo"), comment) |
80b642ff |
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonUnixSockCleanedUp(c *testing.T) { |
16309bef |
dir, err := ioutil.TempDir("", "socket-cleanup-test")
if err != nil { |
dc944ea7 |
c.Fatal(err) |
16309bef |
}
defer os.RemoveAll(dir)
sockPath := filepath.Join(dir, "docker.sock") |
c502fb49 |
s.d.Start(c, "--host", "unix://"+sockPath) |
16309bef |
if _, err := os.Stat(sockPath); err != nil { |
dc944ea7 |
c.Fatal("socket does not exist") |
16309bef |
}
|
c502fb49 |
s.d.Stop(c) |
16309bef |
if _, err := os.Stat(sockPath); err == nil || !os.IsNotExist(err) { |
dc944ea7 |
c.Fatal("unix socket is not cleaned up") |
16309bef |
}
} |
ef13dcd4 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonWithWrongkey(c *testing.T) { |
21ae66c6 |
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")
s.d.Start(c)
s.d.Stop(c)
config := &Config{}
bytes, err := ioutil.ReadFile("/etc/docker/key.json")
if err != nil {
c.Fatalf("Error reading key.json file: %s", err)
}
// byte[] to Data-Struct
if err := json.Unmarshal(bytes, &config); err != nil {
c.Fatalf("Error Unmarshal: %s", err)
}
//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 {
c.Fatalf("Error Marshal: %s", err)
}
// write back
if err := ioutil.WriteFile("/etc/docker/key.json", newBytes, 0400); err != nil {
c.Fatalf("Error ioutil.WriteFile: %s", err)
}
defer os.Remove("/etc/docker/key.json")
if err := s.d.StartWithError(); err == nil {
c.Fatalf("It should not be successful to start daemon with wrong key: %v", err)
}
content, err := s.d.ReadLogFile() |
ef4c63ac |
assert.Assert(c, err == nil) |
21ae66c6 |
if !strings.Contains(string(content), "Public Key ID does not match") {
c.Fatalf("Missing KeyID message from daemon logs: %s", string(content))
}
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartKillWait(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c) |
db0ffba3 |
|
57464c32 |
out, err := s.d.Cmd("run", "-id", "busybox", "/bin/cat") |
db0ffba3 |
if err != nil { |
dc944ea7 |
c.Fatalf("Could not run /bin/cat: err=%v\n%s", err, out) |
db0ffba3 |
}
containerID := strings.TrimSpace(out)
|
57464c32 |
if out, err := s.d.Cmd("kill", containerID); err != nil { |
dc944ea7 |
c.Fatalf("Could not kill %s: err=%v\n%s", containerID, err, out) |
db0ffba3 |
}
|
c502fb49 |
s.d.Restart(c) |
db0ffba3 |
errchan := make(chan error)
go func() { |
57464c32 |
if out, err := s.d.Cmd("wait", containerID); err != nil { |
db0ffba3 |
errchan <- fmt.Errorf("%v:\n%s", err, out)
}
close(errchan)
}()
select {
case <-time.After(5 * time.Second): |
dc944ea7 |
c.Fatal("Waiting on a stopped (killed) container timed out") |
db0ffba3 |
case err := <-errchan:
if err != nil { |
dc944ea7 |
c.Fatal(err) |
db0ffba3 |
}
}
} |
05013f12 |
|
7fb7a477 |
// TestHTTPSInfo connects via two-way authenticated HTTPS to the info endpoint |
64a928a3 |
func (s *DockerDaemonSuite) TestHTTPSInfo(c *testing.T) { |
05013f12 |
const ( |
e7fc6321 |
testDaemonHTTPSAddr = "tcp://localhost:4271" |
05013f12 |
)
|
c502fb49 |
s.d.Start(c,
"--tlsverify",
"--tlscacert", "fixtures/https/ca.pem",
"--tlscert", "fixtures/https/server-cert.pem",
"--tlskey", "fixtures/https/server-key.pem",
"-H", testDaemonHTTPSAddr) |
05013f12 |
|
c0d2f7b3 |
args := []string{
"--host", testDaemonHTTPSAddr, |
c502fb49 |
"--tlsverify",
"--tlscacert", "fixtures/https/ca.pem", |
c0d2f7b3 |
"--tlscert", "fixtures/https/client-cert.pem",
"--tlskey", "fixtures/https/client-key.pem",
"info",
}
out, err := s.d.Cmd(args...) |
05013f12 |
if err != nil {
c.Fatalf("Error Occurred: %s and output: %s", err, out)
}
}
|
7fb7a477 |
// TestHTTPSRun connects via two-way authenticated HTTPS to the create, attach, start, and wait endpoints. |
db1d5f7e |
// https://github.com/docker/docker/issues/19280 |
64a928a3 |
func (s *DockerDaemonSuite) TestHTTPSRun(c *testing.T) { |
db1d5f7e |
const (
testDaemonHTTPSAddr = "tcp://localhost:4271"
)
|
c502fb49 |
s.d.StartWithBusybox(c, "--tlsverify", "--tlscacert", "fixtures/https/ca.pem", "--tlscert", "fixtures/https/server-cert.pem",
"--tlskey", "fixtures/https/server-key.pem", "-H", testDaemonHTTPSAddr) |
db1d5f7e |
|
c0d2f7b3 |
args := []string{
"--host", testDaemonHTTPSAddr,
"--tlsverify", "--tlscacert", "fixtures/https/ca.pem",
"--tlscert", "fixtures/https/client-cert.pem",
"--tlskey", "fixtures/https/client-key.pem",
"run", "busybox", "echo", "TLS response",
}
out, err := s.d.Cmd(args...) |
db1d5f7e |
if err != nil {
c.Fatalf("Error Occurred: %s and output: %s", err, out)
}
if !strings.Contains(out, "TLS response") {
c.Fatalf("expected output to include `TLS response`, got %v", out)
}
}
|
7fb7a477 |
// TestTLSVerify verifies that --tlsverify=false turns on tls |
64a928a3 |
func (s *DockerDaemonSuite) TestTLSVerify(c *testing.T) { |
f87053b9 |
out, err := exec.Command(dockerdBinary, "--tlsverify=false").CombinedOutput() |
5ced3ab3 |
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))
}
}
|
7fb7a477 |
// TestHTTPSInfoRogueCert connects via two-way authenticated HTTPS to the info endpoint |
05013f12 |
// by using a rogue client certificate and checks that it fails with the expected error. |
64a928a3 |
func (s *DockerDaemonSuite) TestHTTPSInfoRogueCert(c *testing.T) { |
05013f12 |
const ( |
496adadc |
errBadCertificate = "bad certificate" |
e7fc6321 |
testDaemonHTTPSAddr = "tcp://localhost:4271" |
05013f12 |
) |
e7fc6321 |
|
c502fb49 |
s.d.Start(c,
"--tlsverify",
"--tlscacert", "fixtures/https/ca.pem",
"--tlscert", "fixtures/https/server-cert.pem",
"--tlskey", "fixtures/https/server-key.pem",
"-H", testDaemonHTTPSAddr) |
05013f12 |
|
c0d2f7b3 |
args := []string{
"--host", testDaemonHTTPSAddr, |
c502fb49 |
"--tlsverify",
"--tlscacert", "fixtures/https/ca.pem", |
c0d2f7b3 |
"--tlscert", "fixtures/https/client-rogue-cert.pem",
"--tlskey", "fixtures/https/client-rogue-key.pem",
"info",
}
out, err := s.d.Cmd(args...) |
05013f12 |
if err == nil || !strings.Contains(out, errBadCertificate) {
c.Fatalf("Expected err: %s, got instead: %s and output: %s", errBadCertificate, err, out)
}
}
|
7fb7a477 |
// TestHTTPSInfoRogueServerCert connects via two-way authenticated HTTPS to the info endpoint |
05013f12 |
// which provides a rogue server certificate and checks that it fails with the expected error |
64a928a3 |
func (s *DockerDaemonSuite) TestHTTPSInfoRogueServerCert(c *testing.T) { |
05013f12 |
const (
errCaUnknown = "x509: certificate signed by unknown authority" |
e7fc6321 |
testDaemonRogueHTTPSAddr = "tcp://localhost:4272" |
05013f12 |
) |
c502fb49 |
s.d.Start(c,
"--tlsverify",
"--tlscacert", "fixtures/https/ca.pem",
"--tlscert", "fixtures/https/server-rogue-cert.pem",
"--tlskey", "fixtures/https/server-rogue-key.pem",
"-H", testDaemonRogueHTTPSAddr) |
05013f12 |
|
c0d2f7b3 |
args := []string{
"--host", testDaemonRogueHTTPSAddr, |
c502fb49 |
"--tlsverify",
"--tlscacert", "fixtures/https/ca.pem", |
c0d2f7b3 |
"--tlscert", "fixtures/https/client-rogue-cert.pem",
"--tlskey", "fixtures/https/client-rogue-key.pem",
"info",
}
out, err := s.d.Cmd(args...) |
05013f12 |
if err == nil || !strings.Contains(out, errCaUnknown) {
c.Fatalf("Expected err: %s, got instead: %s and output: %s", errCaUnknown, err, out)
}
} |
9c325c3f |
|
64a928a3 |
func pingContainers(c *testing.T, d *daemon.Daemon, expectFailure bool) { |
dd0666e6 |
var dargs []string
if d != nil { |
48de91a3 |
dargs = []string{"--host", d.Sock()} |
dd0666e6 |
}
args := append(dargs, "run", "-d", "--name", "container1", "busybox", "top") |
668e2369 |
dockerCmd(c, args...) |
9c325c3f |
|
dd0666e6 |
args = append(dargs, "run", "--rm", "--link", "container1:alias1", "busybox", "sh", "-c") |
9c325c3f |
pingCmd := "ping -c 1 %s -W 1" |
dd0666e6 |
args = append(args, fmt.Sprintf(pingCmd, "alias1")) |
693ba98c |
_, _, err := dockerCmdWithError(args...) |
dd0666e6 |
if expectFailure { |
6345208b |
assert.ErrorContains(c, err, "") |
dd0666e6 |
} else { |
6345208b |
assert.NilError(c, err) |
dd0666e6 |
} |
9c325c3f |
|
dd0666e6 |
args = append(dargs, "rm", "-f", "container1") |
668e2369 |
dockerCmd(c, args...) |
9c325c3f |
} |
08230703 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartWithSocketAsVolume(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c) |
08230703 |
|
f4a34a1f |
socket := filepath.Join(s.d.Folder, "docker.sock") |
08230703 |
|
e4468913 |
out, err := s.d.Cmd("run", "--restart=always", "-v", socket+":/sock", "busybox") |
6345208b |
assert.NilError(c, err, "Output: %s", out) |
c502fb49 |
s.d.Restart(c) |
08230703 |
} |
39165616 |
|
511a7058 |
// os.Kill should kill daemon ungracefully, leaving behind container mounts. |
39bcaee4 |
// A subsequent daemon restart should clean up said mounts. |
64a928a3 |
func (s *DockerDaemonSuite) TestCleanupMountsAfterDaemonAndContainerKill(c *testing.T) { |
239a8a51 |
d := daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) |
c502fb49 |
d.StartWithBusybox(c) |
39165616 |
|
c502fb49 |
out, err := d.Cmd("run", "-d", "busybox", "top") |
6345208b |
assert.NilError(c, err, "Output: %s", out)
|
39165616 |
id := strings.TrimSpace(out) |
f5e01452 |
// If there are no mounts with container id visible from the host
// (as those are in container's own mount ns), there is nothing
// to check here and the test should be skipped. |
511a7058 |
mountOut, err := ioutil.ReadFile("/proc/self/mountinfo") |
6345208b |
assert.NilError(c, err, "Output: %s", mountOut) |
f5e01452 |
if !strings.Contains(string(mountOut), id) {
d.Stop(c)
c.Skip("no container mounts visible in host ns")
} |
511a7058 |
|
f5e01452 |
// kill the daemon |
6345208b |
assert.NilError(c, d.Kill()) |
9c4570a9 |
// kill the container |
34eede02 |
icmd.RunCommand(ctrBinary, "--address", containerdSocket, |
34418110 |
"--namespace", d.ContainersNamespace(), "tasks", "kill", id).Assert(c, icmd.Success) |
511a7058 |
// restart daemon. |
c502fb49 |
d.Restart(c) |
9c4570a9 |
|
511a7058 |
// Now, container mounts should be gone.
mountOut, err = ioutil.ReadFile("/proc/self/mountinfo") |
6345208b |
assert.NilError(c, err, "Output: %s", mountOut)
assert.Assert(c, !strings.Contains(string(mountOut), id), "%s is still mounted from older daemon start:\nDaemon root repository %s\n%s", id, d.Root, mountOut) |
c502fb49 |
d.Stop(c) |
511a7058 |
}
// os.Interrupt should perform a graceful daemon shutdown and hence cleanup mounts. |
64a928a3 |
func (s *DockerDaemonSuite) TestCleanupMountsAfterGracefulShutdown(c *testing.T) { |
239a8a51 |
d := daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) |
c502fb49 |
d.StartWithBusybox(c) |
511a7058 |
|
c502fb49 |
out, err := d.Cmd("run", "-d", "busybox", "top") |
6345208b |
assert.NilError(c, err, "Output: %s", out) |
511a7058 |
id := strings.TrimSpace(out)
// Send SIGINT and daemon should clean up |
6345208b |
assert.NilError(c, d.Signal(os.Interrupt)) |
9c52b11e |
// Wait for the daemon to stop. |
6345208b |
assert.NilError(c, <-d.Wait) |
9c4570a9 |
|
b1d2f52b |
mountOut, err := ioutil.ReadFile("/proc/self/mountinfo") |
6345208b |
assert.NilError(c, err, "Output: %s", mountOut) |
b1d2f52b |
|
6345208b |
assert.Assert(c, !strings.Contains(string(mountOut), id), "%s is still mounted from older daemon start:\nDaemon root repository %s\n%s", id, d.Root, mountOut) |
39165616 |
} |
3cb14df6 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartWithContainerRunning(t *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(t) |
c983996e |
if out, err := s.d.Cmd("run", "-d", "--name", "test", "busybox", "top"); err != nil { |
bdb77078 |
t.Fatal(out, err)
} |
c68e7f96 |
|
c502fb49 |
s.d.Restart(t) |
bdb77078 |
// Container 'test' should be removed without error
if out, err := s.d.Cmd("rm", "test"); err != nil {
t.Fatal(out, err)
}
} |
c68e7f96 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartCleanupNetns(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c) |
c68e7f96 |
out, err := s.d.Cmd("run", "--name", "netns", "-d", "busybox", "top")
if err != nil {
c.Fatal(out, err)
} |
56fdb052 |
// 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'")
|
c68e7f96 |
if out, err := s.d.Cmd("stop", "netns"); err != nil {
c.Fatal(out, err)
}
// Test if the file still exists |
87e3fcfe |
icmd.RunCommand("stat", "-c", "%n", fileName).Assert(c, icmd.Expected{
Out: fileName,
}) |
c68e7f96 |
// Remove the container and restart the daemon
if out, err := s.d.Cmd("rm", "netns"); err != nil {
c.Fatal(out, err)
}
|
c502fb49 |
s.d.Restart(c) |
c68e7f96 |
// Test again and see now the netns file does not exist |
87e3fcfe |
icmd.RunCommand("stat", "-c", "%n", fileName).Assert(c, icmd.Expected{
Err: "No such file or directory",
ExitCode: 1,
}) |
c68e7f96 |
} |
5a6a33f7 |
// tests regression detailed in #13964 where DOCKER_TLS_VERIFY env is ignored |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonTLSVerifyIssue13964(c *testing.T) { |
5a6a33f7 |
host := "tcp://localhost:4271" |
c502fb49 |
s.d.Start(c, "-H", host) |
87e3fcfe |
icmd.RunCmd(icmd.Cmd{
Command: []string{dockerBinary, "-H", host, "info"},
Env: []string{"DOCKER_TLS_VERIFY=1", "DOCKER_CERT_PATH=fixtures/https"},
}).Assert(c, icmd.Expected{
ExitCode: 1,
Err: "error during connect",
}) |
2dfb7f3b |
}
|
64a928a3 |
func setupV6(c *testing.T) { |
2dfb7f3b |
// Hack to get the right IPv6 address on docker0, which has already been created |
6e7405eb |
result := icmd.RunCommand("ip", "addr", "add", "fe80::1/64", "dev", "docker0") |
87e3fcfe |
result.Assert(c, icmd.Success) |
2dfb7f3b |
}
|
64a928a3 |
func teardownV6(c *testing.T) { |
6e7405eb |
result := icmd.RunCommand("ip", "addr", "del", "fe80::1/64", "dev", "docker0") |
87e3fcfe |
result.Assert(c, icmd.Success) |
5a6a33f7 |
} |
af59c80b |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartWithContainerWithRestartPolicyAlways(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c) |
af59c80b |
out, err := s.d.Cmd("run", "-d", "--restart", "always", "busybox", "top") |
6345208b |
assert.NilError(c, err, out) |
af59c80b |
id := strings.TrimSpace(out)
|
ac038eab |
out, err = s.d.Cmd("stop", id) |
6345208b |
assert.NilError(c, err, out) |
ac038eab |
out, err = s.d.Cmd("wait", id) |
6345208b |
assert.NilError(c, err, out) |
af59c80b |
out, err = s.d.Cmd("ps", "-q") |
6345208b |
assert.NilError(c, err, out)
assert.Equal(c, out, "") |
af59c80b |
|
c502fb49 |
s.d.Restart(c) |
af59c80b |
out, err = s.d.Cmd("ps", "-q") |
6345208b |
assert.NilError(c, err, out) |
6dc7846d |
assert.Equal(c, strings.TrimSpace(out), id[:12]) |
af59c80b |
} |
960791ba |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonWideLogConfig(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c, "--log-opt=max-size=1k") |
1790980e |
name := "logtest"
out, err := s.d.Cmd("run", "-d", "--log-opt=max-file=5", "--name", name, "busybox", "top") |
6345208b |
assert.NilError(c, err, "Output: %s, err: %v", out, err) |
1790980e |
out, err = s.d.Cmd("inspect", "-f", "{{ .HostConfig.LogConfig.Config }}", name) |
6345208b |
assert.NilError(c, err, "Output: %s", out)
assert.Assert(c, strings.Contains(out, "max-size:1k"))
assert.Assert(c, strings.Contains(out, "max-file:5")) |
1790980e |
out, err = s.d.Cmd("inspect", "-f", "{{ .HostConfig.LogConfig.Type }}", name) |
6345208b |
assert.NilError(c, err, "Output: %s", out)
assert.Equal(c, strings.TrimSpace(out), "json-file") |
3f61002b |
} |
9a9724ad |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartWithPausedContainer(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c) |
9a9724ad |
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)
} |
c502fb49 |
s.d.Restart(c) |
9a9724ad |
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)
}
} |
b3b7eb27 |
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartRmVolumeInUse(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c) |
b3b7eb27 |
out, err := s.d.Cmd("create", "-v", "test:/foo", "busybox") |
6345208b |
assert.NilError(c, err, out) |
b3b7eb27 |
|
c502fb49 |
s.d.Restart(c) |
9a9724ad |
|
b3b7eb27 |
out, err = s.d.Cmd("volume", "rm", "test") |
2f069fa3 |
assert.Assert(c, err != nil, "should not be able to remove in use volume after daemon restart") |
ed9449a4 |
assert.Assert(c, strings.Contains(out, "in use")) |
b3b7eb27 |
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartLocalVolumes(c *testing.T) { |
c502fb49 |
s.d.Start(c) |
b3b7eb27 |
|
ac038eab |
out, err := s.d.Cmd("volume", "create", "test") |
6345208b |
assert.NilError(c, err, out) |
c502fb49 |
s.d.Restart(c) |
b3b7eb27 |
|
ac038eab |
out, err = s.d.Cmd("volume", "inspect", "test") |
6345208b |
assert.NilError(c, err, out) |
9a9724ad |
} |
e3c47242 |
|
c502fb49 |
// FIXME(vdemeester) should be a unit test |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonCorruptedLogDriverAddress(c *testing.T) { |
239a8a51 |
d := daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) |
e49237dc |
assert.Assert(c, d.StartWithError("--log-driver=syslog", "--log-opt", "syslog-address=corrupted:42") != nil) |
b0b9a25e |
expected := "syslog-address should be in form proto://address" |
87e3fcfe |
icmd.RunCommand("grep", expected, d.LogFileName()).Assert(c, icmd.Success) |
e3c47242 |
}
|
c502fb49 |
// FIXME(vdemeester) should be a unit test |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonCorruptedFluentdAddress(c *testing.T) { |
239a8a51 |
d := daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) |
e49237dc |
assert.Assert(c, d.StartWithError("--log-driver=fluentd", "--log-opt", "fluentd-address=corrupted:c") != nil) |
b0b9a25e |
expected := "invalid fluentd-address corrupted:c: " |
87e3fcfe |
icmd.RunCommand("grep", expected, d.LogFileName()).Assert(c, icmd.Success) |
e3c47242 |
} |
e38767e1 |
|
48de91a3 |
// FIXME(vdemeester) Use a new daemon instance instead of the Suite one |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonStartWithoutHost(c *testing.T) { |
48de91a3 |
s.d.UseDefaultHost = true |
e38767e1 |
defer func() { |
48de91a3 |
s.d.UseDefaultHost = false |
e38767e1 |
}() |
c502fb49 |
s.d.Start(c) |
e38767e1 |
} |
fbb01b81 |
|
48de91a3 |
// FIXME(vdemeester) Use a new daemon instance instead of the Suite one |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonStartWithDefaultTLSHost(c *testing.T) { |
48de91a3 |
s.d.UseDefaultTLSHost = true |
fbb01b81 |
defer func() { |
48de91a3 |
s.d.UseDefaultTLSHost = false |
fbb01b81 |
}() |
c502fb49 |
s.d.Start(c, |
fbb01b81 |
"--tlsverify",
"--tlscacert", "fixtures/https/ca.pem",
"--tlscert", "fixtures/https/server-cert.pem", |
c502fb49 |
"--tlskey", "fixtures/https/server-key.pem") |
fbb01b81 |
// 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")
} |
ddd5278b |
// ensure when connecting to the server that only a single acceptable CA is requested
contents, err := ioutil.ReadFile("fixtures/https/ca.pem") |
6345208b |
assert.NilError(c, err) |
ddd5278b |
rootCert, err := helpers.ParseCertificatePEM(contents) |
6345208b |
assert.NilError(c, err) |
ddd5278b |
rootPool := x509.NewCertPool()
rootPool.AddCert(rootCert)
var certRequestInfo *tls.CertificateRequestInfo
conn, err := tls.Dial("tcp", fmt.Sprintf("%s:%d", opts.DefaultHTTPHost, opts.DefaultTLSHTTPPort), &tls.Config{
RootCAs: rootPool,
GetClientCertificate: func(cri *tls.CertificateRequestInfo) (*tls.Certificate, error) {
certRequestInfo = cri
cert, err := tls.LoadX509KeyPair("fixtures/https/client-cert.pem", "fixtures/https/client-key.pem")
if err != nil {
return nil, err
}
return &cert, nil
},
}) |
6345208b |
assert.NilError(c, err) |
ddd5278b |
conn.Close()
|
e49237dc |
assert.Assert(c, certRequestInfo != nil) |
7b91af80 |
assert.Equal(c, len(certRequestInfo.AcceptableCAs), 1) |
17e04aa6 |
assert.DeepEqual(c, certRequestInfo.AcceptableCAs[0], rootCert.RawSubject) |
fbb01b81 |
} |
e8da75d4 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestBridgeIPIsExcludedFromAllocatorPool(c *testing.T) { |
e8da75d4 |
defaultNetworkBridge := "docker0"
deleteInterface(c, defaultNetworkBridge)
bridgeIP := "192.169.1.1"
bridgeRange := bridgeIP + "/30"
|
c502fb49 |
s.d.StartWithBusybox(c, "--bip", bridgeRange)
defer s.d.Restart(c) |
e8da75d4 |
var cont int
for {
contName := fmt.Sprintf("container%d", cont) |
c502fb49 |
_, err := s.d.Cmd("run", "--name", contName, "-d", "busybox", "/bin/sleep", "2") |
e8da75d4 |
if err != nil {
// pool exhausted
break
}
ip, err := s.d.Cmd("inspect", "--format", "'{{.NetworkSettings.IPAddress}}'", contName) |
4cf69b99 |
assert.Assert(c, err == nil, "%s", ip) |
e8da75d4 |
|
819baeb4 |
assert.Assert(c, ip != bridgeIP) |
e8da75d4 |
cont++
}
} |
4699ef8f |
// Test daemon for no space left on device error |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonNoSpaceLeftOnDeviceError(c *testing.T) { |
43b15e92 |
testRequires(c, testEnv.IsLocalDaemon, DaemonIsLinux, Network) |
44d3f2f7 |
|
59b83d8a |
testDir, err := ioutil.TempDir("", "no-space-left-on-device-test") |
6345208b |
assert.NilError(c, err) |
59b83d8a |
defer os.RemoveAll(testDir) |
ef4c63ac |
assert.Assert(c, mount.MakeRShared(testDir) == nil) |
59b83d8a |
defer mount.Unmount(testDir) |
5106c516 |
|
a978fd22 |
// create a 3MiB image (with a 2MiB ext4 fs) and mount it as graph root |
59b83d8a |
// Why in a container? Because `mount` sometimes behaves weirdly and often fails outright on this test in debian:jessie (which is what the test suite runs under if run from the Makefile) |
5c3d2d55 |
dockerCmd(c, "run", "--rm", "-v", testDir+":/test", "busybox", "sh", "-c", "dd of=/test/testfs.img bs=1M seek=3 count=0") |
87e3fcfe |
icmd.RunCommand("mkfs.ext4", "-F", filepath.Join(testDir, "testfs.img")).Assert(c, icmd.Success) |
47c353eb |
|
11319732 |
dockerCmd(c, "run", "--privileged", "--rm", "-v", testDir+":/test:shared", "busybox", "sh", "-c", "mkdir -p /test/test-mount/vfs && mount -n -t ext4 /test/testfs.img /test/test-mount/vfs") |
47c353eb |
defer mount.Unmount(filepath.Join(testDir, "test-mount")) |
5106c516 |
|
754aeb28 |
s.d.Start(c, "--storage-driver", "vfs", "--data-root", filepath.Join(testDir, "test-mount")) |
c502fb49 |
defer s.d.Stop(c) |
4699ef8f |
|
a978fd22 |
// pull a repository large enough to overfill the mounted filesystem |
5739ba1b |
pullOut, err := s.d.Cmd("pull", "debian:stretch") |
4cf69b99 |
assert.Assert(c, err != nil, "%s", pullOut) |
ed9449a4 |
assert.Assert(c, strings.Contains(pullOut, "no space left on device")) |
4699ef8f |
} |
19762da6 |
// Test daemon restart with container links + auto restart |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartContainerLinksRestart(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c) |
19762da6 |
|
f23c00d8 |
var parent1Args []string
var parent2Args []string |
19762da6 |
wg := sync.WaitGroup{}
maxChildren := 10
chErr := make(chan error, maxChildren)
for i := 0; i < maxChildren; i++ {
wg.Add(1)
name := fmt.Sprintf("test%d", i)
if i < maxChildren/2 {
parent1Args = append(parent1Args, []string{"--link", name}...)
} else {
parent2Args = append(parent2Args, []string{"--link", name}...)
}
go func() { |
c502fb49 |
_, err := s.d.Cmd("run", "-d", "--name", name, "--restart=always", "busybox", "top") |
19762da6 |
chErr <- err
wg.Done()
}()
}
wg.Wait()
close(chErr)
for err := range chErr { |
6345208b |
assert.NilError(c, err) |
19762da6 |
}
parent1Args = append([]string{"run", "-d"}, parent1Args...)
parent1Args = append(parent1Args, []string{"--name=parent1", "--restart=always", "busybox", "top"}...)
parent2Args = append([]string{"run", "-d"}, parent2Args...)
parent2Args = append(parent2Args, []string{"--name=parent2", "--restart=always", "busybox", "top"}...)
|
c502fb49 |
_, err := s.d.Cmd(parent1Args...) |
6345208b |
assert.NilError(c, err) |
5c0fd2d0 |
_, err = s.d.Cmd(parent2Args...) |
6345208b |
assert.NilError(c, err) |
19762da6 |
|
c502fb49 |
s.d.Stop(c) |
19762da6 |
// clear the log file -- we don't need any of it but may for the next part
// can ignore the error here, this is just a cleanup |
5c0fd2d0 |
os.Truncate(s.d.LogFileName(), 0) |
c502fb49 |
s.d.Start(c) |
19762da6 |
for _, num := range []string{"1", "2"} { |
5c0fd2d0 |
out, err := s.d.Cmd("inspect", "-f", "{{ .State.Running }}", "parent"+num) |
6345208b |
assert.NilError(c, err) |
19762da6 |
if strings.TrimSpace(out) != "true" { |
5c0fd2d0 |
log, _ := ioutil.ReadFile(s.d.LogFileName()) |
19762da6 |
c.Fatalf("parent container is not running\n%s", string(log))
}
}
} |
2e3186ab |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonCgroupParent(c *testing.T) { |
2e3186ab |
testRequires(c, DaemonIsLinux)
cgroupParent := "test"
name := "cgroup-test"
|
c502fb49 |
s.d.StartWithBusybox(c, "--cgroup-parent", cgroupParent)
defer s.d.Restart(c) |
2e3186ab |
out, err := s.d.Cmd("run", "--name", name, "busybox", "cat", "/proc/self/cgroup") |
6345208b |
assert.NilError(c, err) |
3fca5878 |
cgroupPaths := ParseCgroupPaths(out)
assert.Assert(c, len(cgroupPaths) != 0, "unexpected output - %q", out) |
2e3186ab |
out, err = s.d.Cmd("inspect", "-f", "{{.Id}}", name) |
6345208b |
assert.NilError(c, err) |
3fca5878 |
id := strings.TrimSpace(out) |
2e3186ab |
expectedCgroup := path.Join(cgroupParent, id)
found := false
for _, path := range cgroupPaths {
if strings.HasSuffix(path, expectedCgroup) {
found = true
break
}
} |
4cf69b99 |
assert.Assert(c, found, "Cgroup path for container (%s) doesn't found in cgroups file: %s", expectedCgroup, cgroupPaths) |
2e3186ab |
} |
0f9f9950 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartWithLinks(c *testing.T) { |
0f9f9950 |
testRequires(c, DaemonIsLinux) // Windows does not support links |
c502fb49 |
s.d.StartWithBusybox(c) |
0f9f9950 |
out, err := s.d.Cmd("run", "-d", "--name=test", "busybox", "top") |
6345208b |
assert.NilError(c, err, out) |
0f9f9950 |
out, err = s.d.Cmd("run", "--name=test2", "--link", "test:abc", "busybox", "sh", "-c", "ping -c 1 -w 1 abc") |
6345208b |
assert.NilError(c, err, out) |
0f9f9950 |
|
c502fb49 |
s.d.Restart(c) |
0f9f9950 |
// should fail since test is not running yet
out, err = s.d.Cmd("start", "test2") |
6345208b |
assert.ErrorContains(c, err, "", out) |
0f9f9950 |
out, err = s.d.Cmd("start", "test") |
6345208b |
assert.NilError(c, err, out) |
0f9f9950 |
out, err = s.d.Cmd("start", "-a", "test2") |
6345208b |
assert.NilError(c, err, out) |
673cf751 |
assert.Equal(c, strings.Contains(out, "1 packets transmitted, 1 packets received"), true, fmt.Sprintf("%s", out)) |
0f9f9950 |
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartWithNames(c *testing.T) { |
0f9f9950 |
testRequires(c, DaemonIsLinux) // Windows does not support links |
c502fb49 |
s.d.StartWithBusybox(c) |
0f9f9950 |
out, err := s.d.Cmd("create", "--name=test", "busybox") |
6345208b |
assert.NilError(c, err, out) |
0f9f9950 |
out, err = s.d.Cmd("run", "-d", "--name=test2", "busybox", "top") |
6345208b |
assert.NilError(c, err, out) |
0f9f9950 |
test2ID := strings.TrimSpace(out)
out, err = s.d.Cmd("run", "-d", "--name=test3", "--link", "test2:abc", "busybox", "top") |
6345208b |
assert.NilError(c, err) |
0f9f9950 |
test3ID := strings.TrimSpace(out)
|
c502fb49 |
s.d.Restart(c) |
0f9f9950 |
|
ddd8a657 |
_, err = s.d.Cmd("create", "--name=test", "busybox") |
6345208b |
assert.ErrorContains(c, err, "", "expected error trying to create container with duplicate name") |
0f9f9950 |
// this one is no longer needed, removing simplifies the remainder of the test
out, err = s.d.Cmd("rm", "-f", "test") |
6345208b |
assert.NilError(c, err, out) |
0f9f9950 |
out, err = s.d.Cmd("ps", "-a", "--no-trunc") |
6345208b |
assert.NilError(c, err, out) |
0f9f9950 |
lines := strings.Split(strings.TrimSpace(out), "\n")[1:]
test2validated := false
test3validated := false
for _, line := range lines {
fields := strings.Fields(line)
names := fields[len(fields)-1]
switch fields[0] {
case test2ID: |
6345208b |
assert.Equal(c, names, "test2,test3/abc") |
0f9f9950 |
test2validated = true
case test3ID: |
6345208b |
assert.Equal(c, names, "test3") |
0f9f9950 |
test3validated = true
}
}
|
6345208b |
assert.Assert(c, test2validated)
assert.Assert(c, test3validated) |
0f9f9950 |
}
|
006d58d7 |
// TestDaemonRestartWithKilledRunningContainer requires live restore of running containers |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartWithKilledRunningContainer(t *testing.T) { |
006d58d7 |
testRequires(t, DaemonIsLinux) |
c502fb49 |
s.d.StartWithBusybox(t) |
006d58d7 |
cid, err := s.d.Cmd("run", "-d", "--name", "test", "busybox", "top") |
c502fb49 |
defer s.d.Stop(t) |
006d58d7 |
if err != nil {
t.Fatal(cid, err)
}
cid = strings.TrimSpace(cid)
|
6d36431e |
pid, err := s.d.Cmd("inspect", "-f", "{{.State.Pid}}", cid) |
6345208b |
assert.NilError(t, err) |
6d36431e |
pid = strings.TrimSpace(pid)
|
006d58d7 |
// Kill the daemon
if err := s.d.Kill(); err != nil {
t.Fatal(err)
}
// kill the container |
34eede02 |
icmd.RunCommand(ctrBinary, "--address", containerdSocket, |
34418110 |
"--namespace", s.d.ContainersNamespace(), "tasks", "kill", cid).Assert(t, icmd.Success) |
006d58d7 |
// Give time to containerd to process the command if we don't
// the exit event might be received after we do the inspect |
ecbb0e62 |
result := icmd.RunCommand("kill", "-0", pid)
for result.ExitCode == 0 { |
6d36431e |
time.Sleep(1 * time.Second) |
ecbb0e62 |
// FIXME(vdemeester) should we check it doesn't error out ?
result = icmd.RunCommand("kill", "-0", pid) |
006d58d7 |
}
// restart the daemon |
c502fb49 |
s.d.Start(t) |
006d58d7 |
// Check that we've got the correct exit code
out, err := s.d.Cmd("inspect", "-f", "{{.State.ExitCode}}", cid) |
6345208b |
assert.NilError(t, err) |
006d58d7 |
out = strings.TrimSpace(out)
if out != "143" {
t.Fatalf("Expected exit code '%s' got '%s' for container '%s'\n", "143", out, cid)
}
}
// os.Kill should kill daemon ungracefully, leaving behind live containers.
// The live containers should be known to the restarted daemon. Stopping
// them now, should remove the mounts. |
64a928a3 |
func (s *DockerDaemonSuite) TestCleanupMountsAfterDaemonCrash(c *testing.T) { |
006d58d7 |
testRequires(c, DaemonIsLinux) |
c502fb49 |
s.d.StartWithBusybox(c, "--live-restore") |
006d58d7 |
out, err := s.d.Cmd("run", "-d", "busybox", "top") |
6345208b |
assert.NilError(c, err, "Output: %s", out) |
006d58d7 |
id := strings.TrimSpace(out)
|
f5e01452 |
// kill the daemon |
ef4c63ac |
assert.Assert(c, s.d.Kill() == nil) |
f5e01452 |
// Check if there are mounts with container id visible from the host.
// If not, those mounts exist in container's own mount ns, and so
// the following check for mounts being cleared is pointless.
skipMountCheck := false |
006d58d7 |
mountOut, err := ioutil.ReadFile("/proc/self/mountinfo") |
4cf69b99 |
assert.Assert(c, err == nil, "Output: %s", mountOut) |
f5e01452 |
if !strings.Contains(string(mountOut), id) {
skipMountCheck = true
} |
006d58d7 |
// restart daemon. |
c502fb49 |
s.d.Start(c, "--live-restore") |
006d58d7 |
// container should be running. |
fab2a3dc |
out, err = s.d.Cmd("inspect", "--format={{.State.Running}}", id) |
6345208b |
assert.NilError(c, err, "Output: %s", out) |
006d58d7 |
out = strings.TrimSpace(out)
if out != "true" {
c.Fatalf("Container %s expected to stay alive after daemon restart", id)
}
// 'docker stop' should work.
out, err = s.d.Cmd("stop", id) |
6345208b |
assert.NilError(c, err, "Output: %s", out) |
006d58d7 |
|
f5e01452 |
if skipMountCheck {
return
} |
006d58d7 |
// Now, container mounts should be gone.
mountOut, err = ioutil.ReadFile("/proc/self/mountinfo") |
4cf69b99 |
assert.Assert(c, err == nil, "Output: %s", mountOut) |
673cf751 |
comment := fmt.Sprintf("%s is still mounted from older daemon start:\nDaemon root repository %s\n%s", id, s.d.Root, mountOut) |
6dc7846d |
assert.Equal(c, strings.Contains(string(mountOut), id), false, comment) |
006d58d7 |
}
// TestDaemonRestartWithUnpausedRunningContainer requires live restore of running containers. |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartWithUnpausedRunningContainer(t *testing.T) { |
006d58d7 |
testRequires(t, DaemonIsLinux) |
c502fb49 |
s.d.StartWithBusybox(t, "--live-restore") |
006d58d7 |
cid, err := s.d.Cmd("run", "-d", "--name", "test", "busybox", "top") |
c502fb49 |
defer s.d.Stop(t) |
006d58d7 |
if err != nil {
t.Fatal(cid, err)
}
cid = strings.TrimSpace(cid)
|
6d36431e |
pid, err := s.d.Cmd("inspect", "-f", "{{.State.Pid}}", cid) |
6345208b |
assert.NilError(t, err) |
6d36431e |
|
006d58d7 |
// pause the container
if _, err := s.d.Cmd("pause", cid); err != nil {
t.Fatal(cid, err)
}
// Kill the daemon
if err := s.d.Kill(); err != nil {
t.Fatal(err)
}
// resume the container |
d7022f2b |
result := icmd.RunCommand(
ctrBinary, |
34eede02 |
"--address", containerdSocket, |
34418110 |
"--namespace", s.d.ContainersNamespace(), |
ddae20c0 |
"tasks", "resume", cid) |
92427b3a |
result.Assert(t, icmd.Success) |
006d58d7 |
// Give time to containerd to process the command if we don't
// the resume event might be received after we do the inspect |
9266ff78 |
poll.WaitOn(t, pollCheck(t, func(*testing.T) (interface{}, string) { |
d7022f2b |
result := icmd.RunCommand("kill", "-0", strings.TrimSpace(pid)) |
be66788e |
return result.ExitCode, "" |
9266ff78 |
}, checker.Equals(0)), poll.WithTimeout(defaultReconciliationTimeout)) |
006d58d7 |
// restart the daemon |
c502fb49 |
s.d.Start(t, "--live-restore") |
006d58d7 |
// Check that we've got the correct status
out, err := s.d.Cmd("inspect", "-f", "{{.State.Status}}", cid) |
6345208b |
assert.NilError(t, err) |
006d58d7 |
out = strings.TrimSpace(out)
if out != "running" {
t.Fatalf("Expected exit code '%s' got '%s' for container '%s'\n", "running", out, cid)
}
if _, err := s.d.Cmd("kill", cid); err != nil {
t.Fatal(err)
} |
0f9f9950 |
}
// TestRunLinksChanged checks that creating a new container with the same name does not update links
// this ensures that the old, pre gh#16032 functionality continues on |
64a928a3 |
func (s *DockerDaemonSuite) TestRunLinksChanged(c *testing.T) { |
0f9f9950 |
testRequires(c, DaemonIsLinux) // Windows does not support links |
c502fb49 |
s.d.StartWithBusybox(c) |
0f9f9950 |
out, err := s.d.Cmd("run", "-d", "--name=test", "busybox", "top") |
6345208b |
assert.NilError(c, err, out) |
0f9f9950 |
out, err = s.d.Cmd("run", "--name=test2", "--link=test:abc", "busybox", "sh", "-c", "ping -c 1 abc") |
6345208b |
assert.NilError(c, err, out) |
ed9449a4 |
assert.Assert(c, strings.Contains(out, "1 packets transmitted, 1 packets received")) |
0f9f9950 |
out, err = s.d.Cmd("rm", "-f", "test") |
6345208b |
assert.NilError(c, err, out) |
0f9f9950 |
out, err = s.d.Cmd("run", "-d", "--name=test", "busybox", "top") |
6345208b |
assert.NilError(c, err, out) |
0f9f9950 |
out, err = s.d.Cmd("start", "-a", "test2") |
6345208b |
assert.ErrorContains(c, err, "", out) |
07b24365 |
assert.Assert(c, !strings.Contains(out, "1 packets transmitted, 1 packets received")) |
c502fb49 |
s.d.Restart(c) |
0f9f9950 |
out, err = s.d.Cmd("start", "-a", "test2") |
6345208b |
assert.ErrorContains(c, err, "", out) |
07b24365 |
assert.Assert(c, !strings.Contains(out, "1 packets transmitted, 1 packets received")) |
0f9f9950 |
} |
89859917 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonStartWithoutColors(c *testing.T) { |
008b2178 |
testRequires(c, DaemonIsLinux) |
89859917 |
|
008b2178 |
infoLog := "\x1b[36mINFO\x1b" |
89859917 |
|
c9e0d923 |
b := bytes.NewBuffer(nil)
done := make(chan bool)
|
89859917 |
p, tty, err := pty.Open() |
6345208b |
assert.NilError(c, err) |
89859917 |
defer func() {
tty.Close()
p.Close()
}()
|
c9e0d923 |
go func() {
io.Copy(b, p)
done <- true
}() |
89859917 |
// Enable coloring explicitly |
5c0fd2d0 |
s.d.StartWithLogFile(tty, "--raw-logs=false") |
c502fb49 |
s.d.Stop(c) |
c9e0d923 |
// Wait for io.Copy() before checking output
<-done |
ed9449a4 |
assert.Assert(c, strings.Contains(b.String(), infoLog)) |
89859917 |
b.Reset()
|
c9e0d923 |
// "tty" is already closed in prev s.d.Stop(),
// we have to close the other side "p" and open another pair of
// pty for the next test.
p.Close()
p, tty, err = pty.Open() |
6345208b |
assert.NilError(c, err) |
c9e0d923 |
go func() {
io.Copy(b, p)
done <- true
}()
|
89859917 |
// Disable coloring explicitly |
5c0fd2d0 |
s.d.StartWithLogFile(tty, "--raw-logs=true") |
c502fb49 |
s.d.Stop(c) |
c9e0d923 |
// Wait for io.Copy() before checking output
<-done |
819baeb4 |
assert.Assert(c, b.String() != "") |
07b24365 |
assert.Assert(c, !strings.Contains(b.String(), infoLog)) |
89859917 |
} |
9f315dd3 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonDebugLog(c *testing.T) { |
008b2178 |
testRequires(c, DaemonIsLinux) |
9f315dd3 |
debugLog := "\x1b[37mDEBU\x1b"
p, tty, err := pty.Open() |
6345208b |
assert.NilError(c, err) |
9f315dd3 |
defer func() {
tty.Close()
p.Close()
}()
b := bytes.NewBuffer(nil)
go io.Copy(b, p)
|
5c0fd2d0 |
s.d.StartWithLogFile(tty, "--debug") |
c502fb49 |
s.d.Stop(c) |
ed9449a4 |
assert.Assert(c, strings.Contains(b.String(), debugLog)) |
9f315dd3 |
} |
c9bec2be |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonDiscoveryBackendConfigReload(c *testing.T) { |
43b15e92 |
testRequires(c, testEnv.IsLocalDaemon, DaemonIsLinux) |
c9bec2be |
// daemon config file |
20f99a86 |
daemonConfig := `{ "debug" : false }`
configFile, err := ioutil.TempFile("", "test-daemon-discovery-backend-config-reload-config") |
2f069fa3 |
assert.Assert(c, err == nil, "could not create temp file for config reload") |
20f99a86 |
configFilePath := configFile.Name()
defer func() {
configFile.Close()
os.RemoveAll(configFile.Name())
}()
_, err = configFile.Write([]byte(daemonConfig)) |
6345208b |
assert.NilError(c, err) |
c9bec2be |
|
6e7405eb |
// --log-level needs to be set so that d.Start() doesn't add --debug causing
// a conflict with the config |
c502fb49 |
s.d.Start(c, "--config-file", configFilePath, "--log-level=info") |
c9bec2be |
// daemon config file |
20f99a86 |
daemonConfig = `{ |
c9bec2be |
"cluster-store": "consul://consuladdr:consulport/some/path",
"cluster-advertise": "192.168.56.100:0",
"debug" : false
}`
|
20f99a86 |
err = configFile.Truncate(0) |
6345208b |
assert.NilError(c, err) |
20f99a86 |
_, err = configFile.Seek(0, os.SEEK_SET) |
6345208b |
assert.NilError(c, err) |
c9bec2be |
|
20f99a86 |
_, err = configFile.Write([]byte(daemonConfig)) |
6345208b |
assert.NilError(c, err) |
c9bec2be |
|
48de91a3 |
err = s.d.ReloadConfig() |
2f069fa3 |
assert.Assert(c, err == nil, "error reloading daemon config") |
c9bec2be |
|
5c0fd2d0 |
out, err := s.d.Cmd("info") |
6345208b |
assert.NilError(c, err) |
6e7405eb |
|
4cf69b99 |
assert.Assert(c, strings.Contains(out, "Cluster Store: consul://consuladdr:consulport/some/path"))
assert.Assert(c, strings.Contains(out, "Cluster Advertise: 192.168.56.100:0")) |
c9bec2be |
} |
4b5404f1 |
// Test for #21956 |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonLogOptions(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c, "--log-driver=syslog", "--log-opt=syslog-address=udp://127.0.0.1:514") |
4b5404f1 |
out, err := s.d.Cmd("run", "-d", "--log-driver=json-file", "busybox", "top") |
6345208b |
assert.NilError(c, err, out) |
4b5404f1 |
id := strings.TrimSpace(out)
out, err = s.d.Cmd("inspect", "--format='{{.HostConfig.LogConfig}}'", id) |
6345208b |
assert.NilError(c, err, out) |
ed9449a4 |
assert.Assert(c, strings.Contains(out, "{json-file map[]}")) |
4b5404f1 |
} |
7368e41c |
// Test case for #20936, #22443 |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonMaxConcurrency(c *testing.T) { |
c502fb49 |
s.d.Start(c, "--max-concurrent-uploads=6", "--max-concurrent-downloads=8") |
7368e41c |
expectedMaxConcurrentUploads := `level=debug msg="Max Concurrent Uploads: 6"`
expectedMaxConcurrentDownloads := `level=debug msg="Max Concurrent Downloads: 8"` |
48de91a3 |
content, err := s.d.ReadLogFile() |
6345208b |
assert.NilError(c, err) |
ed9449a4 |
assert.Assert(c, strings.Contains(string(content), expectedMaxConcurrentUploads))
assert.Assert(c, strings.Contains(string(content), expectedMaxConcurrentDownloads)) |
7368e41c |
}
// Test case for #20936, #22443 |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonMaxConcurrencyWithConfigFile(c *testing.T) { |
43b15e92 |
testRequires(c, testEnv.IsLocalDaemon, DaemonIsLinux) |
7368e41c |
// daemon config file
configFilePath := "test.json"
configFile, err := os.Create(configFilePath) |
6345208b |
assert.NilError(c, err) |
7368e41c |
defer os.Remove(configFilePath)
daemonConfig := `{ "max-concurrent-downloads" : 8 }`
fmt.Fprintf(configFile, "%s", daemonConfig)
configFile.Close() |
c502fb49 |
s.d.Start(c, fmt.Sprintf("--config-file=%s", configFilePath)) |
7368e41c |
expectedMaxConcurrentUploads := `level=debug msg="Max Concurrent Uploads: 5"`
expectedMaxConcurrentDownloads := `level=debug msg="Max Concurrent Downloads: 8"` |
48de91a3 |
content, err := s.d.ReadLogFile() |
6345208b |
assert.NilError(c, err) |
ed9449a4 |
assert.Assert(c, strings.Contains(string(content), expectedMaxConcurrentUploads))
assert.Assert(c, strings.Contains(string(content), expectedMaxConcurrentDownloads)) |
7368e41c |
configFile, err = os.Create(configFilePath) |
6345208b |
assert.NilError(c, err) |
7368e41c |
daemonConfig = `{ "max-concurrent-uploads" : 7, "max-concurrent-downloads" : 9 }`
fmt.Fprintf(configFile, "%s", daemonConfig)
configFile.Close()
|
ef4c63ac |
assert.Assert(c, s.d.Signal(unix.SIGHUP) == nil) |
069fdc8a |
// unix.Kill(s.d.cmd.Process.Pid, unix.SIGHUP) |
7368e41c |
time.Sleep(3 * time.Second)
expectedMaxConcurrentUploads = `level=debug msg="Reset Max Concurrent Uploads: 7"`
expectedMaxConcurrentDownloads = `level=debug msg="Reset Max Concurrent Downloads: 9"` |
48de91a3 |
content, err = s.d.ReadLogFile() |
6345208b |
assert.NilError(c, err) |
ed9449a4 |
assert.Assert(c, strings.Contains(string(content), expectedMaxConcurrentUploads))
assert.Assert(c, strings.Contains(string(content), expectedMaxConcurrentDownloads)) |
7368e41c |
}
// Test case for #20936, #22443 |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonMaxConcurrencyWithConfigFileReload(c *testing.T) { |
43b15e92 |
testRequires(c, testEnv.IsLocalDaemon, DaemonIsLinux) |
7368e41c |
// daemon config file
configFilePath := "test.json"
configFile, err := os.Create(configFilePath) |
6345208b |
assert.NilError(c, err) |
7368e41c |
defer os.Remove(configFilePath)
daemonConfig := `{ "max-concurrent-uploads" : null }`
fmt.Fprintf(configFile, "%s", daemonConfig)
configFile.Close() |
c502fb49 |
s.d.Start(c, fmt.Sprintf("--config-file=%s", configFilePath)) |
7368e41c |
expectedMaxConcurrentUploads := `level=debug msg="Max Concurrent Uploads: 5"`
expectedMaxConcurrentDownloads := `level=debug msg="Max Concurrent Downloads: 3"` |
48de91a3 |
content, err := s.d.ReadLogFile() |
6345208b |
assert.NilError(c, err) |
ed9449a4 |
assert.Assert(c, strings.Contains(string(content), expectedMaxConcurrentUploads))
assert.Assert(c, strings.Contains(string(content), expectedMaxConcurrentDownloads)) |
7368e41c |
configFile, err = os.Create(configFilePath) |
6345208b |
assert.NilError(c, err) |
7368e41c |
daemonConfig = `{ "max-concurrent-uploads" : 1, "max-concurrent-downloads" : null }`
fmt.Fprintf(configFile, "%s", daemonConfig)
configFile.Close()
|
ef4c63ac |
assert.Assert(c, s.d.Signal(unix.SIGHUP) == nil) |
069fdc8a |
// unix.Kill(s.d.cmd.Process.Pid, unix.SIGHUP) |
7368e41c |
time.Sleep(3 * time.Second)
expectedMaxConcurrentUploads = `level=debug msg="Reset Max Concurrent Uploads: 1"`
expectedMaxConcurrentDownloads = `level=debug msg="Reset Max Concurrent Downloads: 3"` |
48de91a3 |
content, err = s.d.ReadLogFile() |
6345208b |
assert.NilError(c, err) |
ed9449a4 |
assert.Assert(c, strings.Contains(string(content), expectedMaxConcurrentUploads))
assert.Assert(c, strings.Contains(string(content), expectedMaxConcurrentDownloads)) |
7368e41c |
configFile, err = os.Create(configFilePath) |
6345208b |
assert.NilError(c, err) |
7368e41c |
daemonConfig = `{ "labels":["foo=bar"] }`
fmt.Fprintf(configFile, "%s", daemonConfig)
configFile.Close()
|
ef4c63ac |
assert.Assert(c, s.d.Signal(unix.SIGHUP) == nil) |
7368e41c |
time.Sleep(3 * time.Second)
expectedMaxConcurrentUploads = `level=debug msg="Reset Max Concurrent Uploads: 5"`
expectedMaxConcurrentDownloads = `level=debug msg="Reset Max Concurrent Downloads: 3"` |
48de91a3 |
content, err = s.d.ReadLogFile() |
6345208b |
assert.NilError(c, err) |
ed9449a4 |
assert.Assert(c, strings.Contains(string(content), expectedMaxConcurrentUploads))
assert.Assert(c, strings.Contains(string(content), expectedMaxConcurrentDownloads)) |
7368e41c |
} |
a8d01349 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestBuildOnDisabledBridgeNetworkDaemon(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c, "-b=none", "--iptables=false") |
5d2afe4f |
result := cli.BuildCmd(c, "busyboxs", cli.Daemon(s.d),
build.WithDockerfile(`
FROM busybox
RUN cat /etc/hosts`),
build.WithoutCache,
) |
673cf751 |
comment := fmt.Sprintf("Failed to build image. output %s, exitCode %d, err %v", result.Combined(), result.ExitCode, result.Error) |
ef4c63ac |
assert.Assert(c, result.Error == nil, comment) |
6dc7846d |
assert.Equal(c, result.ExitCode, 0, comment) |
a8d01349 |
} |
23821fe5 |
// Test case for #21976 |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonDNSFlagsInHostMode(c *testing.T) { |
43b15e92 |
testRequires(c, testEnv.IsLocalDaemon, DaemonIsLinux) |
23821fe5 |
|
9af5d7c3 |
s.d.StartWithBusybox(c, "--dns", "1.2.3.4", "--dns-search", "example.com", "--dns-opt", "timeout:3") |
23821fe5 |
expectedOutput := "nameserver 1.2.3.4"
out, _ := s.d.Cmd("run", "--net=host", "busybox", "cat", "/etc/resolv.conf") |
4cf69b99 |
assert.Assert(c, strings.Contains(out, expectedOutput), "Expected '%s', but got %q", expectedOutput, out) |
9af5d7c3 |
expectedOutput = "search example.com" |
4cf69b99 |
assert.Assert(c, strings.Contains(out, expectedOutput), "Expected '%s', but got %q", expectedOutput, out) |
9af5d7c3 |
expectedOutput = "options timeout:3" |
4cf69b99 |
assert.Assert(c, strings.Contains(out, expectedOutput), "Expected '%s', but got %q", expectedOutput, out) |
23821fe5 |
} |
7b2e5216 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestRunWithRuntimeFromConfigFile(c *testing.T) { |
7b2e5216 |
conf, err := ioutil.TempFile("", "config-file-") |
6345208b |
assert.NilError(c, err) |
7b2e5216 |
configName := conf.Name()
conf.Close()
defer os.Remove(configName)
config := `
{
"runtimes": {
"oci": { |
52b60f70 |
"path": "runc" |
7b2e5216 |
},
"vm": {
"path": "/usr/local/bin/vm-manager",
"runtimeArgs": [
"--debug"
]
}
}
}
`
ioutil.WriteFile(configName, []byte(config), 0644) |
c502fb49 |
s.d.StartWithBusybox(c, "--config-file", configName) |
7b2e5216 |
// Run with default runtime
out, err := s.d.Cmd("run", "--rm", "busybox", "ls") |
6345208b |
assert.NilError(c, err, out) |
7b2e5216 |
|
7135afa7 |
// Run with default runtime explicitly |
69af7d0d |
out, err = s.d.Cmd("run", "--rm", "--runtime=runc", "busybox", "ls") |
6345208b |
assert.NilError(c, err, out) |
7b2e5216 |
// Run with oci (same path as default) but keep it around
out, err = s.d.Cmd("run", "--name", "oci-runtime-ls", "--runtime=oci", "busybox", "ls") |
6345208b |
assert.NilError(c, err, out) |
7b2e5216 |
// Run with "vm"
out, err = s.d.Cmd("run", "--rm", "--runtime=vm", "busybox", "ls") |
6345208b |
assert.ErrorContains(c, err, "", out) |
ed9449a4 |
assert.Assert(c, strings.Contains(out, "/usr/local/bin/vm-manager: no such file or directory")) |
7b2e5216 |
// Reset config to only have the default
config = `
{
"runtimes": {
}
}
`
ioutil.WriteFile(configName, []byte(config), 0644) |
ef4c63ac |
assert.Assert(c, s.d.Signal(unix.SIGHUP) == nil) |
7b2e5216 |
// Give daemon time to reload config
<-time.After(1 * time.Second)
// Run with default runtime |
69af7d0d |
out, err = s.d.Cmd("run", "--rm", "--runtime=runc", "busybox", "ls") |
6345208b |
assert.NilError(c, err, out) |
7b2e5216 |
// Run with "oci"
out, err = s.d.Cmd("run", "--rm", "--runtime=oci", "busybox", "ls") |
6345208b |
assert.ErrorContains(c, err, "", out) |
ed9449a4 |
assert.Assert(c, strings.Contains(out, "Unknown runtime specified oci")) |
7b2e5216 |
// Start previously created container with oci
out, err = s.d.Cmd("start", "oci-runtime-ls") |
6345208b |
assert.ErrorContains(c, err, "", out) |
ed9449a4 |
assert.Assert(c, strings.Contains(out, "Unknown runtime specified oci")) |
7b2e5216 |
// Check that we can't override the default runtime
config = `
{
"runtimes": { |
69af7d0d |
"runc": {
"path": "my-runc" |
7b2e5216 |
}
}
}
`
ioutil.WriteFile(configName, []byte(config), 0644) |
ef4c63ac |
assert.Assert(c, s.d.Signal(unix.SIGHUP) == nil) |
7b2e5216 |
// Give daemon time to reload config
<-time.After(1 * time.Second)
|
48de91a3 |
content, err := s.d.ReadLogFile() |
6345208b |
assert.NilError(c, err) |
ed9449a4 |
assert.Assert(c, strings.Contains(string(content), `file configuration validation failed: runtime name 'runc' is reserved`)) |
7b2e5216 |
// Check that we can select a default runtime
config = `
{
"default-runtime": "vm",
"runtimes": {
"oci": { |
52b60f70 |
"path": "runc" |
7b2e5216 |
},
"vm": {
"path": "/usr/local/bin/vm-manager",
"runtimeArgs": [
"--debug"
]
}
}
}
`
ioutil.WriteFile(configName, []byte(config), 0644) |
ef4c63ac |
assert.Assert(c, s.d.Signal(unix.SIGHUP) == nil) |
7b2e5216 |
// Give daemon time to reload config
<-time.After(1 * time.Second)
out, err = s.d.Cmd("run", "--rm", "busybox", "ls") |
6345208b |
assert.ErrorContains(c, err, "", out) |
ed9449a4 |
assert.Assert(c, strings.Contains(out, "/usr/local/bin/vm-manager: no such file or directory")) |
7135afa7 |
// Run with default runtime explicitly |
69af7d0d |
out, err = s.d.Cmd("run", "--rm", "--runtime=runc", "busybox", "ls") |
6345208b |
assert.NilError(c, err, out) |
7b2e5216 |
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestRunWithRuntimeFromCommandLine(c *testing.T) { |
52b60f70 |
s.d.StartWithBusybox(c, "--add-runtime", "oci=runc", "--add-runtime", "vm=/usr/local/bin/vm-manager") |
7b2e5216 |
// Run with default runtime
out, err := s.d.Cmd("run", "--rm", "busybox", "ls") |
6345208b |
assert.NilError(c, err, out) |
7b2e5216 |
|
7135afa7 |
// Run with default runtime explicitly |
69af7d0d |
out, err = s.d.Cmd("run", "--rm", "--runtime=runc", "busybox", "ls") |
6345208b |
assert.NilError(c, err, out) |
7b2e5216 |
// Run with oci (same path as default) but keep it around
out, err = s.d.Cmd("run", "--name", "oci-runtime-ls", "--runtime=oci", "busybox", "ls") |
6345208b |
assert.NilError(c, err, out) |
7b2e5216 |
// Run with "vm"
out, err = s.d.Cmd("run", "--rm", "--runtime=vm", "busybox", "ls") |
6345208b |
assert.ErrorContains(c, err, "", out) |
ed9449a4 |
assert.Assert(c, strings.Contains(out, "/usr/local/bin/vm-manager: no such file or directory")) |
7b2e5216 |
// Start a daemon without any extra runtimes |
c502fb49 |
s.d.Stop(c)
s.d.StartWithBusybox(c) |
7b2e5216 |
// Run with default runtime |
69af7d0d |
out, err = s.d.Cmd("run", "--rm", "--runtime=runc", "busybox", "ls") |
6345208b |
assert.NilError(c, err, out) |
7b2e5216 |
// Run with "oci"
out, err = s.d.Cmd("run", "--rm", "--runtime=oci", "busybox", "ls") |
6345208b |
assert.ErrorContains(c, err, "", out) |
ed9449a4 |
assert.Assert(c, strings.Contains(out, "Unknown runtime specified oci")) |
7b2e5216 |
// Start previously created container with oci
out, err = s.d.Cmd("start", "oci-runtime-ls") |
6345208b |
assert.ErrorContains(c, err, "", out) |
ed9449a4 |
assert.Assert(c, strings.Contains(out, "Unknown runtime specified oci")) |
7b2e5216 |
// Check that we can't override the default runtime |
c502fb49 |
s.d.Stop(c) |
e49237dc |
assert.Assert(c, s.d.StartWithError("--add-runtime", "runc=my-runc") != nil) |
7b2e5216 |
|
48de91a3 |
content, err := s.d.ReadLogFile() |
6345208b |
assert.NilError(c, err) |
ed9449a4 |
assert.Assert(c, strings.Contains(string(content), `runtime name 'runc' is reserved`)) |
7b2e5216 |
// Check that we can select a default runtime |
c502fb49 |
s.d.Stop(c) |
52b60f70 |
s.d.StartWithBusybox(c, "--default-runtime=vm", "--add-runtime", "oci=runc", "--add-runtime", "vm=/usr/local/bin/vm-manager") |
7b2e5216 |
out, err = s.d.Cmd("run", "--rm", "busybox", "ls") |
6345208b |
assert.ErrorContains(c, err, "", out) |
ed9449a4 |
assert.Assert(c, strings.Contains(out, "/usr/local/bin/vm-manager: no such file or directory")) |
7135afa7 |
// Run with default runtime explicitly |
69af7d0d |
out, err = s.d.Cmd("run", "--rm", "--runtime=runc", "busybox", "ls") |
6345208b |
assert.NilError(c, err, out) |
7b2e5216 |
} |
3c2886d8 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartWithAutoRemoveContainer(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c) |
3c2886d8 |
// top1 will exist after daemon restarts
out, err := s.d.Cmd("run", "-d", "--name", "top1", "busybox:latest", "top") |
4cf69b99 |
assert.Assert(c, err == nil, "run top1: %v", out) |
3c2886d8 |
// top2 will be removed after daemon restarts
out, err = s.d.Cmd("run", "-d", "--rm", "--name", "top2", "busybox:latest", "top") |
4cf69b99 |
assert.Assert(c, err == nil, "run top2: %v", out) |
3c2886d8 |
out, err = s.d.Cmd("ps") |
6345208b |
assert.NilError(c, err) |
2f069fa3 |
assert.Assert(c, strings.Contains(out, "top1"), "top1 should be running")
assert.Assert(c, strings.Contains(out, "top2"), "top2 should be running") |
3c2886d8 |
// now restart daemon gracefully |
c502fb49 |
s.d.Restart(c) |
3c2886d8 |
out, err = s.d.Cmd("ps", "-a") |
6345208b |
assert.NilError(c, err, "out: %v", out) |
2f069fa3 |
assert.Assert(c, strings.Contains(out, "top1"), "top1 should exist after daemon restarts")
assert.Assert(c, !strings.Contains(out, "top2"), "top2 should be removed after daemon restarts") |
3c2886d8 |
} |
88bfa6ed |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonRestartSaveContainerExitCode(c *testing.T) { |
c502fb49 |
s.d.StartWithBusybox(c) |
88bfa6ed |
containerName := "error-values"
// Make a container with both a non 0 exit code and an error message |
ba0afd70 |
// We explicitly disable `--init` for this test, because `--init` is enabled by default
// on "experimental". Enabling `--init` results in a different behavior; because the "init"
// process itself is PID1, the container does not fail on _startup_ (i.e., `docker-init` starting),
// but directly after. The exit code of the container is still 127, but the Error Message is not
// captured, so `.State.Error` is empty.
// See the discussion on https://github.com/docker/docker/pull/30227#issuecomment-274161426,
// and https://github.com/docker/docker/pull/26061#r78054578 for more information. |
ddd8a657 |
_, err := s.d.Cmd("run", "--name", containerName, "--init=false", "busybox", "toto") |
6345208b |
assert.ErrorContains(c, err, "") |
88bfa6ed |
// Check that those values were saved on disk |
ddd8a657 |
out, err := s.d.Cmd("inspect", "-f", "{{.State.ExitCode}}", containerName) |
88bfa6ed |
out = strings.TrimSpace(out) |
6345208b |
assert.NilError(c, err)
assert.Equal(c, out, "127") |
88bfa6ed |
|
ba0afd70 |
errMsg1, err := s.d.Cmd("inspect", "-f", "{{.State.Error}}", containerName)
errMsg1 = strings.TrimSpace(errMsg1) |
6345208b |
assert.NilError(c, err) |
ed9449a4 |
assert.Assert(c, strings.Contains(errMsg1, "executable file not found")) |
88bfa6ed |
// now restart daemon |
c502fb49 |
s.d.Restart(c) |
88bfa6ed |
// Check that those values are still around
out, err = s.d.Cmd("inspect", "-f", "{{.State.ExitCode}}", containerName)
out = strings.TrimSpace(out) |
6345208b |
assert.NilError(c, err)
assert.Equal(c, out, "127") |
88bfa6ed |
out, err = s.d.Cmd("inspect", "-f", "{{.State.Error}}", containerName)
out = strings.TrimSpace(out) |
6345208b |
assert.NilError(c, err)
assert.Equal(c, out, errMsg1) |
88bfa6ed |
} |
dc712b92 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonWithUserlandProxyPath(c *testing.T) { |
43b15e92 |
testRequires(c, testEnv.IsLocalDaemon, DaemonIsLinux) |
dd2e1947 |
dockerProxyPath, err := exec.LookPath("docker-proxy") |
6345208b |
assert.NilError(c, err) |
dd2e1947 |
tmpDir, err := ioutil.TempDir("", "test-docker-proxy") |
6345208b |
assert.NilError(c, err) |
dd2e1947 |
newProxyPath := filepath.Join(tmpDir, "docker-proxy")
cmd := exec.Command("cp", dockerProxyPath, newProxyPath) |
6345208b |
assert.NilError(c, cmd.Run()) |
dd2e1947 |
// custom one |
c502fb49 |
s.d.StartWithBusybox(c, "--userland-proxy-path", newProxyPath) |
dd2e1947 |
out, err := s.d.Cmd("run", "-p", "5000:5000", "busybox:latest", "true") |
6345208b |
assert.NilError(c, err, out) |
dd2e1947 |
// try with the original one |
c502fb49 |
s.d.Restart(c, "--userland-proxy-path", dockerProxyPath) |
dd2e1947 |
out, err = s.d.Cmd("run", "-p", "5000:5000", "busybox:latest", "true") |
6345208b |
assert.NilError(c, err, out) |
dd2e1947 |
// not exist |
c502fb49 |
s.d.Restart(c, "--userland-proxy-path", "/does/not/exist") |
dd2e1947 |
out, err = s.d.Cmd("run", "-p", "5000:5000", "busybox:latest", "true") |
6345208b |
assert.ErrorContains(c, err, "", out) |
ed9449a4 |
assert.Assert(c, strings.Contains(out, "driver failed programming external connectivity on endpoint"))
assert.Assert(c, strings.Contains(out, "/does/not/exist: no such file or directory")) |
dd2e1947 |
} |
d7be6b2d |
// Test case for #22471 |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonShutdownTimeout(c *testing.T) { |
43b15e92 |
testRequires(c, testEnv.IsLocalDaemon) |
c502fb49 |
s.d.StartWithBusybox(c, "--shutdown-timeout=3") |
d7be6b2d |
_, err := s.d.Cmd("run", "-d", "busybox", "top") |
6345208b |
assert.NilError(c, err) |
d7be6b2d |
|
ef4c63ac |
assert.Assert(c, s.d.Signal(unix.SIGINT) == nil) |
d7be6b2d |
select { |
48de91a3 |
case <-s.d.Wait: |
d7be6b2d |
case <-time.After(5 * time.Second):
}
|
ed74ee12 |
expectedMessage := `level=debug msg="daemon configured with a 3 seconds minimum shutdown timeout"` |
48de91a3 |
content, err := s.d.ReadLogFile() |
6345208b |
assert.NilError(c, err) |
ed9449a4 |
assert.Assert(c, strings.Contains(string(content), expectedMessage)) |
d7be6b2d |
}
// Test case for #22471 |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonShutdownTimeoutWithConfigFile(c *testing.T) { |
43b15e92 |
testRequires(c, testEnv.IsLocalDaemon) |
d7be6b2d |
// daemon config file
configFilePath := "test.json"
configFile, err := os.Create(configFilePath) |
6345208b |
assert.NilError(c, err) |
d7be6b2d |
defer os.Remove(configFilePath)
daemonConfig := `{ "shutdown-timeout" : 8 }`
fmt.Fprintf(configFile, "%s", daemonConfig)
configFile.Close() |
c502fb49 |
s.d.Start(c, fmt.Sprintf("--config-file=%s", configFilePath)) |
d7be6b2d |
configFile, err = os.Create(configFilePath) |
6345208b |
assert.NilError(c, err) |
d7be6b2d |
daemonConfig = `{ "shutdown-timeout" : 5 }`
fmt.Fprintf(configFile, "%s", daemonConfig)
configFile.Close()
|
ef4c63ac |
assert.Assert(c, s.d.Signal(unix.SIGHUP) == nil) |
d7be6b2d |
select { |
48de91a3 |
case <-s.d.Wait: |
d7be6b2d |
case <-time.After(3 * time.Second):
}
expectedMessage := `level=debug msg="Reset Shutdown Timeout: 5"` |
48de91a3 |
content, err := s.d.ReadLogFile() |
6345208b |
assert.NilError(c, err) |
ed9449a4 |
assert.Assert(c, strings.Contains(string(content), expectedMessage)) |
d7be6b2d |
} |
7feb2a17 |
// Test case for 29342 |
64a928a3 |
func (s *DockerDaemonSuite) TestExecWithUserAfterLiveRestore(c *testing.T) { |
7feb2a17 |
testRequires(c, DaemonIsLinux)
s.d.StartWithBusybox(c, "--live-restore")
|
4076c57b |
out, err := s.d.Cmd("run", "--init", "-d", "--name=top", "busybox", "sh", "-c", "addgroup -S test && adduser -S -G test test -D -s /bin/sh && touch /adduser_end && exec top") |
6345208b |
assert.NilError(c, err, "Output: %s", out) |
7feb2a17 |
|
77c725ea |
s.d.WaitRun("top") |
7feb2a17 |
|
c7c6167b |
// Wait for shell command to be completed
_, err = s.d.Cmd("exec", "top", "sh", "-c", `for i in $(seq 1 5); do if [ -e /adduser_end ]; then rm -f /adduser_end && break; else sleep 1 && false; fi; done`) |
2f069fa3 |
assert.Assert(c, err == nil, "Timeout waiting for shell command to be completed") |
c7c6167b |
|
7feb2a17 |
out1, err := s.d.Cmd("exec", "-u", "test", "top", "id")
// uid=100(test) gid=101(test) groups=101(test) |
4cf69b99 |
assert.Assert(c, err == nil, "Output: %s", out1) |
7feb2a17 |
// restart daemon.
s.d.Restart(c, "--live-restore")
out2, err := s.d.Cmd("exec", "-u", "test", "top", "id") |
4cf69b99 |
assert.Assert(c, err == nil, "Output: %s", out2) |
673cf751 |
assert.Equal(c, out2, out1, fmt.Sprintf("Output: before restart '%s', after restart '%s'", out1, out2)) |
7feb2a17 |
out, err = s.d.Cmd("stop", "top") |
6345208b |
assert.NilError(c, err, "Output: %s", out) |
7feb2a17 |
} |
77c725ea |
|
64a928a3 |
func (s *DockerDaemonSuite) TestRemoveContainerAfterLiveRestore(c *testing.T) { |
43b15e92 |
testRequires(c, DaemonIsLinux, overlayFSSupported, testEnv.IsLocalDaemon) |
77c725ea |
s.d.StartWithBusybox(c, "--live-restore", "--storage-driver", "overlay")
out, err := s.d.Cmd("run", "-d", "--name=top", "busybox", "top") |
6345208b |
assert.NilError(c, err, "Output: %s", out) |
77c725ea |
s.d.WaitRun("top")
// restart daemon.
s.d.Restart(c, "--live-restore", "--storage-driver", "overlay")
out, err = s.d.Cmd("stop", "top") |
6345208b |
assert.NilError(c, err, "Output: %s", out) |
77c725ea |
// test if the rootfs mountpoint still exist
mountpoint, err := s.d.InspectField("top", ".GraphDriver.Data.MergedDir") |
6345208b |
assert.NilError(c, err) |
77c725ea |
f, err := os.Open("/proc/self/mountinfo") |
6345208b |
assert.NilError(c, err) |
77c725ea |
defer f.Close()
sc := bufio.NewScanner(f)
for sc.Scan() {
line := sc.Text()
if strings.Contains(line, mountpoint) {
c.Fatalf("mountinfo should not include the mountpoint of stop container")
}
}
out, err = s.d.Cmd("rm", "top") |
6345208b |
assert.NilError(c, err, "Output: %s", out) |
89f03409 |
}
// #29598 |
64a928a3 |
func (s *DockerDaemonSuite) TestRestartPolicyWithLiveRestore(c *testing.T) { |
43b15e92 |
testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) |
89f03409 |
s.d.StartWithBusybox(c, "--live-restore")
out, err := s.d.Cmd("run", "-d", "--restart", "always", "busybox", "top") |
6345208b |
assert.NilError(c, err, "Output: %s", out) |
89f03409 |
id := strings.TrimSpace(out) |
77c725ea |
|
89f03409 |
type state struct {
Running bool
StartedAt time.Time
}
out, err = s.d.Cmd("inspect", "-f", "{{json .State}}", id) |
4cf69b99 |
assert.Assert(c, err == nil, "output: %s", out) |
89f03409 |
var origState state
err = json.Unmarshal([]byte(strings.TrimSpace(out)), &origState) |
6345208b |
assert.NilError(c, err) |
89f03409 |
s.d.Restart(c, "--live-restore")
pid, err := s.d.Cmd("inspect", "-f", "{{.State.Pid}}", id) |
6345208b |
assert.NilError(c, err) |
89f03409 |
pidint, err := strconv.Atoi(strings.TrimSpace(pid)) |
6345208b |
assert.NilError(c, err)
assert.Assert(c, pidint > 0)
assert.NilError(c, unix.Kill(pidint, unix.SIGKILL)) |
89f03409 |
ticker := time.NewTicker(50 * time.Millisecond)
timeout := time.After(10 * time.Second)
for range ticker.C {
select {
case <-timeout:
c.Fatal("timeout waiting for container restart")
default:
}
out, err := s.d.Cmd("inspect", "-f", "{{json .State}}", id) |
4cf69b99 |
assert.Assert(c, err == nil, "output: %s", out) |
89f03409 |
var newState state
err = json.Unmarshal([]byte(strings.TrimSpace(out)), &newState) |
6345208b |
assert.NilError(c, err) |
89f03409 |
if !newState.Running {
continue
}
if newState.StartedAt.After(origState.StartedAt) {
break
}
}
out, err = s.d.Cmd("stop", id) |
6345208b |
assert.NilError(c, err, "Output: %s", out) |
77c725ea |
} |
db575ef6 |
|
64a928a3 |
func (s *DockerDaemonSuite) TestShmSize(c *testing.T) { |
db575ef6 |
testRequires(c, DaemonIsLinux)
size := 67108864 * 2
pattern := regexp.MustCompile(fmt.Sprintf("shm on /dev/shm type tmpfs(.*)size=%dk", size/1024))
s.d.StartWithBusybox(c, "--default-shm-size", fmt.Sprintf("%v", size))
name := "shm1"
out, err := s.d.Cmd("run", "--name", name, "busybox", "mount") |
6345208b |
assert.NilError(c, err, "Output: %s", out) |
7696045c |
assert.Assert(c, pattern.MatchString(out)) |
db575ef6 |
out, err = s.d.Cmd("inspect", "--format", "{{.HostConfig.ShmSize}}", name) |
6345208b |
assert.NilError(c, err, "Output: %s", out) |
6dc7846d |
assert.Equal(c, strings.TrimSpace(out), fmt.Sprintf("%v", size)) |
db575ef6 |
}
|
64a928a3 |
func (s *DockerDaemonSuite) TestShmSizeReload(c *testing.T) { |
db575ef6 |
testRequires(c, DaemonIsLinux)
configPath, err := ioutil.TempDir("", "test-daemon-shm-size-reload-config") |
2f069fa3 |
assert.Assert(c, err == nil, "could not create temp file for config reload") |
db575ef6 |
defer os.RemoveAll(configPath) // clean up
configFile := filepath.Join(configPath, "config.json")
size := 67108864 * 2
configData := []byte(fmt.Sprintf(`{"default-shm-size": "%dM"}`, size/1024/1024)) |
2f069fa3 |
assert.Assert(c, ioutil.WriteFile(configFile, configData, 0666) == nil, "could not write temp file for config reload") |
db575ef6 |
pattern := regexp.MustCompile(fmt.Sprintf("shm on /dev/shm type tmpfs(.*)size=%dk", size/1024))
s.d.StartWithBusybox(c, "--config-file", configFile)
name := "shm1"
out, err := s.d.Cmd("run", "--name", name, "busybox", "mount") |
6345208b |
assert.NilError(c, err, "Output: %s", out) |
7696045c |
assert.Assert(c, pattern.MatchString(out)) |
db575ef6 |
out, err = s.d.Cmd("inspect", "--format", "{{.HostConfig.ShmSize}}", name) |
6345208b |
assert.NilError(c, err, "Output: %s", out) |
6dc7846d |
assert.Equal(c, strings.TrimSpace(out), fmt.Sprintf("%v", size)) |
db575ef6 |
size = 67108864 * 3
configData = []byte(fmt.Sprintf(`{"default-shm-size": "%dM"}`, size/1024/1024)) |
2f069fa3 |
assert.Assert(c, ioutil.WriteFile(configFile, configData, 0666) == nil, "could not write temp file for config reload") |
db575ef6 |
pattern = regexp.MustCompile(fmt.Sprintf("shm on /dev/shm type tmpfs(.*)size=%dk", size/1024))
err = s.d.ReloadConfig() |
2f069fa3 |
assert.Assert(c, err == nil, "error reloading daemon config") |
db575ef6 |
name = "shm2"
out, err = s.d.Cmd("run", "--name", name, "busybox", "mount") |
6345208b |
assert.NilError(c, err, "Output: %s", out) |
7696045c |
assert.Assert(c, pattern.MatchString(out)) |
db575ef6 |
out, err = s.d.Cmd("inspect", "--format", "{{.HostConfig.ShmSize}}", name) |
6345208b |
assert.NilError(c, err, "Output: %s", out) |
6dc7846d |
assert.Equal(c, strings.TrimSpace(out), fmt.Sprintf("%v", size)) |
db575ef6 |
} |
11cf394e |
|
64a928a3 |
func testDaemonStartIpcMode(c *testing.T, from, mode string, valid bool) { |
239a8a51 |
d := daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) |
9a60e1cc |
c.Logf("Checking IpcMode %s set from %s\n", mode, from)
var serr error
switch from {
case "config":
f, err := ioutil.TempFile("", "test-daemon-ipc-config") |
6345208b |
assert.NilError(c, err) |
9a60e1cc |
defer os.Remove(f.Name())
config := `{"default-ipc-mode": "` + mode + `"}`
_, err = f.WriteString(config) |
6345208b |
assert.NilError(c, f.Close())
assert.NilError(c, err) |
9a60e1cc |
serr = d.StartWithError("--config-file", f.Name())
case "cli":
serr = d.StartWithError("--default-ipc-mode", mode)
default:
c.Fatalf("testDaemonStartIpcMode: invalid 'from' argument")
}
if serr == nil {
d.Stop(c)
}
if valid { |
6345208b |
assert.NilError(c, serr) |
9a60e1cc |
} else { |
6345208b |
assert.ErrorContains(c, serr, "") |
9a60e1cc |
icmd.RunCommand("grep", "-E", "IPC .* is (invalid|not supported)", d.LogFileName()).Assert(c, icmd.Success)
}
}
// TestDaemonStartWithIpcModes checks that daemon starts fine given correct
// arguments for default IPC mode, and bails out with incorrect ones.
// Both CLI option (--default-ipc-mode) and config parameter are tested. |
64a928a3 |
func (s *DockerDaemonSuite) TestDaemonStartWithIpcModes(c *testing.T) { |
43b15e92 |
testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon) |
8a987808 |
|
9a60e1cc |
ipcModes := []struct {
mode string
valid bool
}{
{"private", true},
{"shareable", true},
{"host", false},
{"container:123", false},
{"nosuchmode", false},
}
for _, from := range []string{"config", "cli"} {
for _, m := range ipcModes {
testDaemonStartIpcMode(c, from, m.mode, m.valid)
}
}
}
|
11cf394e |
// TestFailedPluginRemove makes sure that a failed plugin remove does not block
// the daemon from starting |
64a928a3 |
func (s *DockerDaemonSuite) TestFailedPluginRemove(c *testing.T) { |
43b15e92 |
testRequires(c, DaemonIsLinux, IsAmd64, testEnv.IsLocalDaemon) |
239a8a51 |
d := daemon.New(c, dockerBinary, dockerdBinary) |
11cf394e |
d.Start(c) |
3a4bb96a |
cli := d.NewClientT(c) |
11cf394e |
ctx, cancel := context.WithTimeout(context.Background(), 300*time.Second)
defer cancel()
name := "test-plugin-rm-fail"
out, err := cli.PluginInstall(ctx, name, types.PluginInstallOptions{
Disabled: true,
AcceptAllPermissions: true,
RemoteRef: "cpuguy83/docker-logdriver-test",
}) |
6345208b |
assert.NilError(c, err) |
11cf394e |
defer out.Close()
io.Copy(ioutil.Discard, out)
ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
p, _, err := cli.PluginInspectWithRaw(ctx, name) |
6345208b |
assert.NilError(c, err) |
11cf394e |
// simulate a bad/partial removal by removing the plugin config.
configPath := filepath.Join(d.Root, "plugins", p.ID, "config.json") |
6345208b |
assert.NilError(c, os.Remove(configPath)) |
11cf394e |
d.Restart(c)
ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
_, err = cli.Ping(ctx) |
6345208b |
assert.NilError(c, err) |
11cf394e |
_, _, err = cli.PluginInspectWithRaw(ctx, name)
// plugin should be gone since the config.json is gone |
6345208b |
assert.ErrorContains(c, err, "") |
11cf394e |
} |