github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/integration/container/daemon_linux_test.go (about) 1 package container // import "github.com/demonoid81/moby/integration/container" 2 3 import ( 4 "context" 5 "fmt" 6 "io/ioutil" 7 "strconv" 8 "strings" 9 "testing" 10 11 "github.com/demonoid81/moby/api/types" 12 "github.com/demonoid81/moby/integration/internal/container" 13 "github.com/demonoid81/moby/testutil/daemon" 14 "golang.org/x/sys/unix" 15 "gotest.tools/v3/assert" 16 is "gotest.tools/v3/assert/cmp" 17 "gotest.tools/v3/skip" 18 ) 19 20 // This is a regression test for #36145 21 // It ensures that a container can be started when the daemon was improperly 22 // shutdown when the daemon is brought back up. 23 // 24 // The regression is due to improper error handling preventing a container from 25 // being restored and as such have the resources cleaned up. 26 // 27 // To test this, we need to kill dockerd, then kill both the containerd-shim and 28 // the container process, then start dockerd back up and attempt to start the 29 // container again. 30 func TestContainerStartOnDaemonRestart(t *testing.T) { 31 skip.If(t, testEnv.IsRemoteDaemon, "cannot start daemon on remote test run") 32 skip.If(t, testEnv.DaemonInfo.OSType == "windows") 33 skip.If(t, testEnv.IsRootless) 34 t.Parallel() 35 36 d := daemon.New(t) 37 d.StartWithBusybox(t, "--iptables=false") 38 defer d.Stop(t) 39 40 c := d.NewClientT(t) 41 42 ctx := context.Background() 43 44 cID := container.Create(ctx, t, c) 45 defer c.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{Force: true}) 46 47 err := c.ContainerStart(ctx, cID, types.ContainerStartOptions{}) 48 assert.Check(t, err, "error starting test container") 49 50 inspect, err := c.ContainerInspect(ctx, cID) 51 assert.Check(t, err, "error getting inspect data") 52 53 ppid := getContainerdShimPid(t, inspect) 54 55 err = d.Kill() 56 assert.Check(t, err, "failed to kill test daemon") 57 58 err = unix.Kill(inspect.State.Pid, unix.SIGKILL) 59 assert.Check(t, err, "failed to kill container process") 60 61 err = unix.Kill(ppid, unix.SIGKILL) 62 assert.Check(t, err, "failed to kill containerd-shim") 63 64 d.Start(t, "--iptables=false") 65 66 err = c.ContainerStart(ctx, cID, types.ContainerStartOptions{}) 67 assert.Check(t, err, "failed to start test container") 68 } 69 70 func getContainerdShimPid(t *testing.T, c types.ContainerJSON) int { 71 statB, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/stat", c.State.Pid)) 72 assert.Check(t, err, "error looking up containerd-shim pid") 73 74 // ppid is the 4th entry in `/proc/pid/stat` 75 ppid, err := strconv.Atoi(strings.Fields(string(statB))[3]) 76 assert.Check(t, err, "error converting ppid field to int") 77 78 assert.Check(t, ppid != 1, "got unexpected ppid") 79 return ppid 80 } 81 82 // TestDaemonRestartIpcMode makes sure a container keeps its ipc mode 83 // (derived from daemon default) even after the daemon is restarted 84 // with a different default ipc mode. 85 func TestDaemonRestartIpcMode(t *testing.T) { 86 skip.If(t, testEnv.IsRemoteDaemon, "cannot start daemon on remote test run") 87 skip.If(t, testEnv.DaemonInfo.OSType == "windows") 88 t.Parallel() 89 90 d := daemon.New(t) 91 d.StartWithBusybox(t, "--iptables=false", "--default-ipc-mode=private") 92 defer d.Stop(t) 93 94 c := d.NewClientT(t) 95 ctx := context.Background() 96 97 // check the container is created with private ipc mode as per daemon default 98 cID := container.Run(ctx, t, c, 99 container.WithCmd("top"), 100 container.WithRestartPolicy("always"), 101 ) 102 defer c.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{Force: true}) 103 104 inspect, err := c.ContainerInspect(ctx, cID) 105 assert.NilError(t, err) 106 assert.Check(t, is.Equal(string(inspect.HostConfig.IpcMode), "private")) 107 108 // restart the daemon with shareable default ipc mode 109 d.Restart(t, "--iptables=false", "--default-ipc-mode=shareable") 110 111 // check the container is still having private ipc mode 112 inspect, err = c.ContainerInspect(ctx, cID) 113 assert.NilError(t, err) 114 assert.Check(t, is.Equal(string(inspect.HostConfig.IpcMode), "private")) 115 116 // check a new container is created with shareable ipc mode as per new daemon default 117 cID = container.Run(ctx, t, c) 118 defer c.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{Force: true}) 119 120 inspect, err = c.ContainerInspect(ctx, cID) 121 assert.NilError(t, err) 122 assert.Check(t, is.Equal(string(inspect.HostConfig.IpcMode), "shareable")) 123 } 124 125 // TestDaemonHostGatewayIP verifies that when a magic string "host-gateway" is passed 126 // to ExtraHosts (--add-host) instead of an IP address, its value is set to 127 // 1. Daemon config flag value specified by host-gateway-ip or 128 // 2. IP of the default bridge network 129 // and is added to the /etc/hosts file 130 func TestDaemonHostGatewayIP(t *testing.T) { 131 skip.If(t, testEnv.IsRemoteDaemon) 132 skip.If(t, testEnv.DaemonInfo.OSType == "windows") 133 skip.If(t, testEnv.IsRootless, "rootless mode has different view of network") 134 t.Parallel() 135 136 // Verify the IP in /etc/hosts is same as host-gateway-ip 137 d := daemon.New(t) 138 // Verify the IP in /etc/hosts is same as the default bridge's IP 139 d.StartWithBusybox(t) 140 c := d.NewClientT(t) 141 ctx := context.Background() 142 cID := container.Run(ctx, t, c, 143 container.WithExtraHost("host.docker.internal:host-gateway"), 144 ) 145 res, err := container.Exec(ctx, c, cID, []string{"cat", "/etc/hosts"}) 146 assert.NilError(t, err) 147 assert.Assert(t, is.Len(res.Stderr(), 0)) 148 assert.Equal(t, 0, res.ExitCode) 149 inspect, err := c.NetworkInspect(ctx, "bridge", types.NetworkInspectOptions{}) 150 assert.NilError(t, err) 151 assert.Check(t, is.Contains(res.Stdout(), inspect.IPAM.Config[0].Gateway)) 152 c.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{Force: true}) 153 d.Stop(t) 154 155 // Verify the IP in /etc/hosts is same as host-gateway-ip 156 d.StartWithBusybox(t, "--host-gateway-ip=6.7.8.9") 157 cID = container.Run(ctx, t, c, 158 container.WithExtraHost("host.docker.internal:host-gateway"), 159 ) 160 res, err = container.Exec(ctx, c, cID, []string{"cat", "/etc/hosts"}) 161 assert.NilError(t, err) 162 assert.Assert(t, is.Len(res.Stderr(), 0)) 163 assert.Equal(t, 0, res.ExitCode) 164 assert.Check(t, is.Contains(res.Stdout(), "6.7.8.9")) 165 c.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{Force: true}) 166 d.Stop(t) 167 168 }