docker_cli_start_test.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. package main
  2. import (
  3. "fmt"
  4. "os/exec"
  5. "strings"
  6. "time"
  7. "github.com/go-check/check"
  8. )
  9. // Regression test for https://github.com/docker/docker/issues/7843
  10. func (s *DockerSuite) TestStartAttachReturnsOnError(c *check.C) {
  11. dockerCmd(c, "run", "-d", "--name", "test", "busybox")
  12. dockerCmd(c, "wait", "test")
  13. // Expect this to fail because the above container is stopped, this is what we want
  14. if _, err := runCommand(exec.Command(dockerBinary, "run", "-d", "--name", "test2", "--link", "test:test", "busybox")); err == nil {
  15. c.Fatal("Expected error but got none")
  16. }
  17. ch := make(chan error)
  18. go func() {
  19. // Attempt to start attached to the container that won't start
  20. // This should return an error immediately since the container can't be started
  21. if _, err := runCommand(exec.Command(dockerBinary, "start", "-a", "test2")); err == nil {
  22. ch <- fmt.Errorf("Expected error but got none")
  23. }
  24. close(ch)
  25. }()
  26. select {
  27. case err := <-ch:
  28. c.Assert(err, check.IsNil)
  29. case <-time.After(time.Second):
  30. c.Fatalf("Attach did not exit properly")
  31. }
  32. }
  33. // gh#8555: Exit code should be passed through when using start -a
  34. func (s *DockerSuite) TestStartAttachCorrectExitCode(c *check.C) {
  35. runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", "sleep 2; exit 1")
  36. out, _, _, err := runCommandWithStdoutStderr(runCmd)
  37. if err != nil {
  38. c.Fatalf("failed to run container: %v, output: %q", err, out)
  39. }
  40. out = strings.TrimSpace(out)
  41. // make sure the container has exited before trying the "start -a"
  42. waitCmd := exec.Command(dockerBinary, "wait", out)
  43. if _, _, err = runCommandWithOutput(waitCmd); err != nil {
  44. c.Fatalf("Failed to wait on container: %v", err)
  45. }
  46. startCmd := exec.Command(dockerBinary, "start", "-a", out)
  47. startOut, exitCode, err := runCommandWithOutput(startCmd)
  48. if err != nil && !strings.Contains("exit status 1", fmt.Sprintf("%s", err)) {
  49. c.Fatalf("start command failed unexpectedly with error: %v, output: %q", err, startOut)
  50. }
  51. if exitCode != 1 {
  52. c.Fatalf("start -a did not respond with proper exit code: expected 1, got %d", exitCode)
  53. }
  54. }
  55. func (s *DockerSuite) TestStartAttachSilent(c *check.C) {
  56. name := "teststartattachcorrectexitcode"
  57. runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "echo", "test")
  58. out, _, _, err := runCommandWithStdoutStderr(runCmd)
  59. if err != nil {
  60. c.Fatalf("failed to run container: %v, output: %q", err, out)
  61. }
  62. // make sure the container has exited before trying the "start -a"
  63. waitCmd := exec.Command(dockerBinary, "wait", name)
  64. if _, _, err = runCommandWithOutput(waitCmd); err != nil {
  65. c.Fatalf("wait command failed with error: %v", err)
  66. }
  67. startCmd := exec.Command(dockerBinary, "start", "-a", name)
  68. startOut, _, err := runCommandWithOutput(startCmd)
  69. if err != nil {
  70. c.Fatalf("start command failed unexpectedly with error: %v, output: %q", err, startOut)
  71. }
  72. if expected := "test\n"; startOut != expected {
  73. c.Fatalf("start -a produced unexpected output: expected %q, got %q", expected, startOut)
  74. }
  75. }
  76. func (s *DockerSuite) TestStartRecordError(c *check.C) {
  77. // when container runs successfully, we should not have state.Error
  78. dockerCmd(c, "run", "-d", "-p", "9999:9999", "--name", "test", "busybox", "top")
  79. stateErr, err := inspectField("test", "State.Error")
  80. c.Assert(err, check.IsNil)
  81. if stateErr != "" {
  82. c.Fatalf("Expected to not have state error but got state.Error(%q)", stateErr)
  83. }
  84. // Expect this to fail and records error because of ports conflict
  85. out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "--name", "test2", "-p", "9999:9999", "busybox", "top"))
  86. if err == nil {
  87. c.Fatalf("Expected error but got none, output %q", out)
  88. }
  89. stateErr, err = inspectField("test2", "State.Error")
  90. c.Assert(err, check.IsNil)
  91. expected := "port is already allocated"
  92. if stateErr == "" || !strings.Contains(stateErr, expected) {
  93. c.Fatalf("State.Error(%q) does not include %q", stateErr, expected)
  94. }
  95. // Expect the conflict to be resolved when we stop the initial container
  96. dockerCmd(c, "stop", "test")
  97. dockerCmd(c, "start", "test2")
  98. stateErr, err = inspectField("test2", "State.Error")
  99. c.Assert(err, check.IsNil)
  100. if stateErr != "" {
  101. c.Fatalf("Expected to not have state error but got state.Error(%q)", stateErr)
  102. }
  103. }
  104. func (s *DockerSuite) TestStartPausedContainer(c *check.C) {
  105. defer unpauseAllContainers()
  106. runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "testing", "busybox", "top")
  107. if out, _, err := runCommandWithOutput(runCmd); err != nil {
  108. c.Fatal(out, err)
  109. }
  110. runCmd = exec.Command(dockerBinary, "pause", "testing")
  111. if out, _, err := runCommandWithOutput(runCmd); err != nil {
  112. c.Fatal(out, err)
  113. }
  114. runCmd = exec.Command(dockerBinary, "start", "testing")
  115. if out, _, err := runCommandWithOutput(runCmd); err == nil || !strings.Contains(out, "Cannot start a paused container, try unpause instead.") {
  116. c.Fatalf("an error should have been shown that you cannot start paused container: %s\n%v", out, err)
  117. }
  118. }
  119. func (s *DockerSuite) TestStartMultipleContainers(c *check.C) {
  120. // run a container named 'parent' and create two container link to `parent`
  121. cmd := exec.Command(dockerBinary, "run", "-d", "--name", "parent", "busybox", "top")
  122. if out, _, err := runCommandWithOutput(cmd); err != nil {
  123. c.Fatal(out, err)
  124. }
  125. for _, container := range []string{"child_first", "child_second"} {
  126. cmd = exec.Command(dockerBinary, "create", "--name", container, "--link", "parent:parent", "busybox", "top")
  127. if out, _, err := runCommandWithOutput(cmd); err != nil {
  128. c.Fatal(out, err)
  129. }
  130. }
  131. // stop 'parent' container
  132. cmd = exec.Command(dockerBinary, "stop", "parent")
  133. if out, _, err := runCommandWithOutput(cmd); err != nil {
  134. c.Fatal(out, err)
  135. }
  136. out, err := inspectField("parent", "State.Running")
  137. c.Assert(err, check.IsNil)
  138. if out != "false" {
  139. c.Fatal("Container should be stopped")
  140. }
  141. // start all the three containers, container `child_first` start first which should be failed
  142. // container 'parent' start second and then start container 'child_second'
  143. cmd = exec.Command(dockerBinary, "start", "child_first", "parent", "child_second")
  144. out, _, err = runCommandWithOutput(cmd)
  145. if !strings.Contains(out, "Cannot start container child_first") || err == nil {
  146. c.Fatal("Expected error but got none")
  147. }
  148. for container, expected := range map[string]string{"parent": "true", "child_first": "false", "child_second": "true"} {
  149. out, err := inspectField(container, "State.Running")
  150. c.Assert(err, check.IsNil)
  151. if out != expected {
  152. c.Fatal("Container running state wrong")
  153. }
  154. }
  155. }
  156. func (s *DockerSuite) TestStartAttachMultipleContainers(c *check.C) {
  157. var cmd *exec.Cmd
  158. // run multiple containers to test
  159. for _, container := range []string{"test1", "test2", "test3"} {
  160. cmd = exec.Command(dockerBinary, "run", "-d", "--name", container, "busybox", "top")
  161. if out, _, err := runCommandWithOutput(cmd); err != nil {
  162. c.Fatal(out, err)
  163. }
  164. }
  165. // stop all the containers
  166. for _, container := range []string{"test1", "test2", "test3"} {
  167. cmd = exec.Command(dockerBinary, "stop", container)
  168. if out, _, err := runCommandWithOutput(cmd); err != nil {
  169. c.Fatal(out, err)
  170. }
  171. }
  172. // test start and attach multiple containers at once, expected error
  173. for _, option := range []string{"-a", "-i", "-ai"} {
  174. cmd = exec.Command(dockerBinary, "start", option, "test1", "test2", "test3")
  175. out, _, err := runCommandWithOutput(cmd)
  176. if !strings.Contains(out, "You cannot start and attach multiple containers at once.") || err == nil {
  177. c.Fatal("Expected error but got none")
  178. }
  179. }
  180. // confirm the state of all the containers be stopped
  181. for container, expected := range map[string]string{"test1": "false", "test2": "false", "test3": "false"} {
  182. out, err := inspectField(container, "State.Running")
  183. if err != nil {
  184. c.Fatal(out, err)
  185. }
  186. if out != expected {
  187. c.Fatal("Container running state wrong")
  188. }
  189. }
  190. }