github.com/adityamillind98/moby@v23.0.0-rc.4+incompatible/integration-cli/docker_cli_restart_test.go (about) 1 package main 2 3 import ( 4 "os" 5 "strconv" 6 "strings" 7 "testing" 8 "time" 9 10 "github.com/docker/docker/integration-cli/checker" 11 "gotest.tools/v3/assert" 12 is "gotest.tools/v3/assert/cmp" 13 "gotest.tools/v3/poll" 14 "gotest.tools/v3/skip" 15 ) 16 17 type DockerCLIRestartSuite struct { 18 ds *DockerSuite 19 } 20 21 func (s *DockerCLIRestartSuite) TearDownTest(c *testing.T) { 22 s.ds.TearDownTest(c) 23 } 24 25 func (s *DockerCLIRestartSuite) OnTimeout(c *testing.T) { 26 s.ds.OnTimeout(c) 27 } 28 29 func (s *DockerCLIRestartSuite) TestRestartStoppedContainer(c *testing.T) { 30 dockerCmd(c, "run", "--name=test", "busybox", "echo", "foobar") 31 cleanedContainerID := getIDByName(c, "test") 32 33 out, _ := dockerCmd(c, "logs", cleanedContainerID) 34 assert.Equal(c, out, "foobar\n") 35 36 dockerCmd(c, "restart", cleanedContainerID) 37 38 // Wait until the container has stopped 39 err := waitInspect(cleanedContainerID, "{{.State.Running}}", "false", 20*time.Second) 40 assert.NilError(c, err) 41 42 out, _ = dockerCmd(c, "logs", cleanedContainerID) 43 assert.Equal(c, out, "foobar\nfoobar\n") 44 } 45 46 func (s *DockerCLIRestartSuite) TestRestartRunningContainer(c *testing.T) { 47 out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", "echo foobar && sleep 30 && echo 'should not print this'") 48 49 cleanedContainerID := strings.TrimSpace(out) 50 51 assert.NilError(c, waitRun(cleanedContainerID)) 52 53 getLogs := func(c *testing.T) (interface{}, string) { 54 out, _ := dockerCmd(c, "logs", cleanedContainerID) 55 return out, "" 56 } 57 58 // Wait 10 seconds for the 'echo' to appear in the logs 59 poll.WaitOn(c, pollCheck(c, getLogs, checker.Equals("foobar\n")), poll.WithTimeout(10*time.Second)) 60 61 dockerCmd(c, "restart", "-t", "1", cleanedContainerID) 62 assert.NilError(c, waitRun(cleanedContainerID)) 63 64 // Wait 10 seconds for first 'echo' appear (again) in the logs 65 poll.WaitOn(c, pollCheck(c, getLogs, checker.Equals("foobar\nfoobar\n")), poll.WithTimeout(10*time.Second)) 66 } 67 68 // Test that restarting a container with a volume does not create a new volume on restart. Regression test for #819. 69 func (s *DockerCLIRestartSuite) TestRestartWithVolumes(c *testing.T) { 70 prefix, slash := getPrefixAndSlashFromDaemonPlatform() 71 out := runSleepingContainer(c, "-d", "-v", prefix+slash+"test") 72 73 cleanedContainerID := strings.TrimSpace(out) 74 out, err := inspectFilter(cleanedContainerID, "len .Mounts") 75 assert.NilError(c, err, "failed to inspect %s: %s", cleanedContainerID, out) 76 out = strings.Trim(out, " \n\r") 77 assert.Equal(c, out, "1") 78 79 source, err := inspectMountSourceField(cleanedContainerID, prefix+slash+"test") 80 assert.NilError(c, err) 81 82 dockerCmd(c, "restart", cleanedContainerID) 83 84 out, err = inspectFilter(cleanedContainerID, "len .Mounts") 85 assert.NilError(c, err, "failed to inspect %s: %s", cleanedContainerID, out) 86 out = strings.Trim(out, " \n\r") 87 assert.Equal(c, out, "1") 88 89 sourceAfterRestart, err := inspectMountSourceField(cleanedContainerID, prefix+slash+"test") 90 assert.NilError(c, err) 91 assert.Equal(c, source, sourceAfterRestart) 92 } 93 94 func (s *DockerCLIRestartSuite) TestRestartDisconnectedContainer(c *testing.T) { 95 testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon, NotUserNamespace, NotArm) 96 97 // Run a container on the default bridge network 98 out, _ := dockerCmd(c, "run", "-d", "--name", "c0", "busybox", "top") 99 cleanedContainerID := strings.TrimSpace(out) 100 assert.NilError(c, waitRun(cleanedContainerID)) 101 102 // Disconnect the container from the network 103 out, exitCode := dockerCmd(c, "network", "disconnect", "bridge", "c0") 104 assert.Assert(c, exitCode == 0, out) 105 106 // Restart the container 107 out, exitCode = dockerCmd(c, "restart", "c0") 108 assert.Assert(c, exitCode == 0, out) 109 } 110 111 func (s *DockerCLIRestartSuite) TestRestartPolicyNO(c *testing.T) { 112 out, _ := dockerCmd(c, "create", "--restart=no", "busybox") 113 114 id := strings.TrimSpace(out) 115 name := inspectField(c, id, "HostConfig.RestartPolicy.Name") 116 assert.Equal(c, name, "no") 117 } 118 119 func (s *DockerCLIRestartSuite) TestRestartPolicyAlways(c *testing.T) { 120 out, _ := dockerCmd(c, "create", "--restart=always", "busybox") 121 122 id := strings.TrimSpace(out) 123 name := inspectField(c, id, "HostConfig.RestartPolicy.Name") 124 assert.Equal(c, name, "always") 125 126 MaximumRetryCount := inspectField(c, id, "HostConfig.RestartPolicy.MaximumRetryCount") 127 128 // MaximumRetryCount=0 if the restart policy is always 129 assert.Equal(c, MaximumRetryCount, "0") 130 } 131 132 func (s *DockerCLIRestartSuite) TestRestartPolicyOnFailure(c *testing.T) { 133 out, _, err := dockerCmdWithError("create", "--restart=on-failure:-1", "busybox") 134 assert.ErrorContains(c, err, "", out) 135 assert.Assert(c, strings.Contains(out, "maximum retry count cannot be negative")) 136 137 out, _ = dockerCmd(c, "create", "--restart=on-failure:1", "busybox") 138 139 id := strings.TrimSpace(out) 140 name := inspectField(c, id, "HostConfig.RestartPolicy.Name") 141 maxRetry := inspectField(c, id, "HostConfig.RestartPolicy.MaximumRetryCount") 142 143 assert.Equal(c, name, "on-failure") 144 assert.Equal(c, maxRetry, "1") 145 146 out, _ = dockerCmd(c, "create", "--restart=on-failure:0", "busybox") 147 148 id = strings.TrimSpace(out) 149 name = inspectField(c, id, "HostConfig.RestartPolicy.Name") 150 maxRetry = inspectField(c, id, "HostConfig.RestartPolicy.MaximumRetryCount") 151 152 assert.Equal(c, name, "on-failure") 153 assert.Equal(c, maxRetry, "0") 154 155 out, _ = dockerCmd(c, "create", "--restart=on-failure", "busybox") 156 157 id = strings.TrimSpace(out) 158 name = inspectField(c, id, "HostConfig.RestartPolicy.Name") 159 maxRetry = inspectField(c, id, "HostConfig.RestartPolicy.MaximumRetryCount") 160 161 assert.Equal(c, name, "on-failure") 162 assert.Equal(c, maxRetry, "0") 163 } 164 165 // a good container with --restart=on-failure:3 166 // MaximumRetryCount!=0; RestartCount=0 167 func (s *DockerCLIRestartSuite) TestRestartContainerwithGoodContainer(c *testing.T) { 168 out, _ := dockerCmd(c, "run", "-d", "--restart=on-failure:3", "busybox", "true") 169 170 id := strings.TrimSpace(out) 171 err := waitInspect(id, "{{ .State.Restarting }} {{ .State.Running }}", "false false", 30*time.Second) 172 assert.NilError(c, err) 173 174 count := inspectField(c, id, "RestartCount") 175 assert.Equal(c, count, "0") 176 177 MaximumRetryCount := inspectField(c, id, "HostConfig.RestartPolicy.MaximumRetryCount") 178 assert.Equal(c, MaximumRetryCount, "3") 179 } 180 181 func (s *DockerCLIRestartSuite) TestRestartContainerSuccess(c *testing.T) { 182 testRequires(c, testEnv.IsLocalDaemon) 183 // Skipped for Hyper-V isolated containers. Test is currently written 184 // such that it assumes there is a host process to kill. In Hyper-V 185 // containers, the process is inside the utility VM, not on the host. 186 if DaemonIsWindows() { 187 skip.If(c, testEnv.GitHubActions()) 188 testRequires(c, testEnv.DaemonInfo.Isolation.IsProcess) 189 } 190 191 out := runSleepingContainer(c, "-d", "--restart=always") 192 id := strings.TrimSpace(out) 193 assert.NilError(c, waitRun(id)) 194 195 pidStr := inspectField(c, id, "State.Pid") 196 197 pid, err := strconv.Atoi(pidStr) 198 assert.NilError(c, err) 199 200 p, err := os.FindProcess(pid) 201 assert.NilError(c, err) 202 assert.Assert(c, p != nil) 203 204 err = p.Kill() 205 assert.NilError(c, err) 206 207 err = waitInspect(id, "{{.RestartCount}}", "1", 30*time.Second) 208 assert.NilError(c, err) 209 210 err = waitInspect(id, "{{.State.Status}}", "running", 30*time.Second) 211 assert.NilError(c, err) 212 } 213 214 func (s *DockerCLIRestartSuite) TestRestartWithPolicyUserDefinedNetwork(c *testing.T) { 215 // TODO Windows. This may be portable following HNS integration post TP5. 216 testRequires(c, DaemonIsLinux, testEnv.IsLocalDaemon, NotUserNamespace, NotArm) 217 dockerCmd(c, "network", "create", "-d", "bridge", "udNet") 218 219 dockerCmd(c, "run", "-d", "--net=udNet", "--name=first", "busybox", "top") 220 assert.NilError(c, waitRun("first")) 221 222 dockerCmd(c, "run", "-d", "--restart=always", "--net=udNet", "--name=second", 223 "--link=first:foo", "busybox", "top") 224 assert.NilError(c, waitRun("second")) 225 226 // ping to first and its alias foo must succeed 227 _, _, err := dockerCmdWithError("exec", "second", "ping", "-c", "1", "first") 228 assert.NilError(c, err) 229 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo") 230 assert.NilError(c, err) 231 232 // Now kill the second container and let the restart policy kick in 233 pidStr := inspectField(c, "second", "State.Pid") 234 235 pid, err := strconv.Atoi(pidStr) 236 assert.NilError(c, err) 237 238 p, err := os.FindProcess(pid) 239 assert.NilError(c, err) 240 assert.Assert(c, p != nil) 241 242 err = p.Kill() 243 assert.NilError(c, err) 244 245 err = waitInspect("second", "{{.RestartCount}}", "1", 5*time.Second) 246 assert.NilError(c, err) 247 248 err = waitInspect("second", "{{.State.Status}}", "running", 5*time.Second) 249 assert.NilError(c, err) 250 251 // ping to first and its alias foo must still succeed 252 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "first") 253 assert.NilError(c, err) 254 _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo") 255 assert.NilError(c, err) 256 } 257 258 func (s *DockerCLIRestartSuite) TestRestartPolicyAfterRestart(c *testing.T) { 259 testRequires(c, testEnv.IsLocalDaemon) 260 // Skipped for Hyper-V isolated containers. Test is currently written 261 // such that it assumes there is a host process to kill. In Hyper-V 262 // containers, the process is inside the utility VM, not on the host. 263 if DaemonIsWindows() { 264 skip.If(c, testEnv.GitHubActions()) 265 testRequires(c, testEnv.DaemonInfo.Isolation.IsProcess) 266 } 267 268 out := runSleepingContainer(c, "-d", "--restart=always") 269 id := strings.TrimSpace(out) 270 assert.NilError(c, waitRun(id)) 271 272 dockerCmd(c, "restart", id) 273 274 assert.NilError(c, waitRun(id)) 275 276 pidStr := inspectField(c, id, "State.Pid") 277 278 pid, err := strconv.Atoi(pidStr) 279 assert.NilError(c, err) 280 281 p, err := os.FindProcess(pid) 282 assert.NilError(c, err) 283 assert.Assert(c, p != nil) 284 285 err = p.Kill() 286 assert.NilError(c, err) 287 288 err = waitInspect(id, "{{.RestartCount}}", "1", 30*time.Second) 289 assert.NilError(c, err) 290 291 err = waitInspect(id, "{{.State.Status}}", "running", 30*time.Second) 292 assert.NilError(c, err) 293 } 294 295 func (s *DockerCLIRestartSuite) TestRestartContainerwithRestartPolicy(c *testing.T) { 296 out1, _ := dockerCmd(c, "run", "-d", "--restart=on-failure:3", "busybox", "false") 297 out2, _ := dockerCmd(c, "run", "-d", "--restart=always", "busybox", "false") 298 299 id1 := strings.TrimSpace(out1) 300 id2 := strings.TrimSpace(out2) 301 waitTimeout := 15 * time.Second 302 if testEnv.OSType == "windows" { 303 waitTimeout = 150 * time.Second 304 } 305 err := waitInspect(id1, "{{ .State.Restarting }} {{ .State.Running }}", "false false", waitTimeout) 306 assert.NilError(c, err) 307 308 dockerCmd(c, "restart", id1) 309 dockerCmd(c, "restart", id2) 310 311 // Make sure we can stop/start (regression test from a705e166cf3bcca62543150c2b3f9bfeae45ecfa) 312 dockerCmd(c, "stop", id1) 313 dockerCmd(c, "stop", id2) 314 dockerCmd(c, "start", id1) 315 dockerCmd(c, "start", id2) 316 317 // Kill the containers, making sure they are stopped at the end of the test 318 dockerCmd(c, "kill", id1) 319 dockerCmd(c, "kill", id2) 320 err = waitInspect(id1, "{{ .State.Restarting }} {{ .State.Running }}", "false false", waitTimeout) 321 assert.NilError(c, err) 322 err = waitInspect(id2, "{{ .State.Restarting }} {{ .State.Running }}", "false false", waitTimeout) 323 assert.NilError(c, err) 324 } 325 326 func (s *DockerCLIRestartSuite) TestRestartAutoRemoveContainer(c *testing.T) { 327 out := runSleepingContainer(c, "--rm") 328 329 id := strings.TrimSpace(out) 330 dockerCmd(c, "restart", id) 331 err := waitInspect(id, "{{ .State.Restarting }} {{ .State.Running }}", "false true", 15*time.Second) 332 assert.NilError(c, err) 333 334 out, _ = dockerCmd(c, "ps") 335 assert.Assert(c, is.Contains(out, id[:12]), "container should be restarted instead of removed: %v", out) 336 337 // Kill the container to make sure it will be removed 338 dockerCmd(c, "kill", id) 339 }