Browse code

Fix docker start muliple containers continue on one failed and add docker start show error message from daemon when start failed

Signed-off-by: Lei Jitang <leijitang@huawei.com>

Lei Jitang authored on 2015/03/08 14:44:25
Showing 2 changed files
... ...
@@ -778,14 +778,18 @@ func (cli *DockerCli) CmdStart(args ...string) error {
778 778
 			return err
779 779
 		}
780 780
 	}
781
-
781
+	var encounteredError error
782 782
 	for _, name := range cmd.Args() {
783 783
 		_, _, err := readBody(cli.call("POST", "/containers/"+name+"/start", nil, false))
784 784
 		if err != nil {
785 785
 			if !*attach && !*openStdin {
786
+				// attach and openStdin is false means it could be starting multiple containers
787
+				// when a container start failed, show the error message and start next
786 788
 				fmt.Fprintf(cli.err, "%s\n", err)
789
+				encounteredError = fmt.Errorf("Error: failed to start one or more containers")
790
+			} else {
791
+				encounteredError = err
787 792
 			}
788
-			return fmt.Errorf("Error: failed to start one or more containers")
789 793
 		} else {
790 794
 			if !*attach && !*openStdin {
791 795
 				fmt.Fprintf(cli.out, "%s\n", name)
... ...
@@ -793,6 +797,10 @@ func (cli *DockerCli) CmdStart(args ...string) error {
793 793
 		}
794 794
 	}
795 795
 
796
+	if encounteredError != nil {
797
+		return encounteredError
798
+	}
799
+
796 800
 	if *openStdin || *attach {
797 801
 		if tty && cli.isTerminalOut {
798 802
 			if err := cli.monitorTtySize(cmd.Arg(0), false); err != nil {
... ...
@@ -187,3 +187,56 @@ func TestStartPausedContainer(t *testing.T) {
187 187
 
188 188
 	logDone("start - error should show if trying to start paused container")
189 189
 }
190
+
191
+func TestStartMultipleContainers(t *testing.T) {
192
+	defer deleteAllContainers()
193
+	// run a container named 'parent' and create two container link to `parent`
194
+	cmd := exec.Command(dockerBinary, "run", "-d", "--name", "parent", "busybox", "top")
195
+	if out, _, err := runCommandWithOutput(cmd); err != nil {
196
+		t.Fatal(out, err)
197
+	}
198
+	for _, container := range []string{"child_first", "child_second"} {
199
+		cmd = exec.Command(dockerBinary, "create", "--name", container, "--link", "parent:parent", "busybox", "top")
200
+		if out, _, err := runCommandWithOutput(cmd); err != nil {
201
+			t.Fatal(out, err)
202
+		}
203
+	}
204
+
205
+	// stop 'parent' container
206
+	cmd = exec.Command(dockerBinary, "stop", "parent")
207
+	if out, _, err := runCommandWithOutput(cmd); err != nil {
208
+		t.Fatal(out, err)
209
+	}
210
+	cmd = exec.Command(dockerBinary, "inspect", "-f", "{{.State.Running}}", "parent")
211
+	out, _, err := runCommandWithOutput(cmd)
212
+	if err != nil {
213
+		t.Fatal(out, err)
214
+	}
215
+	out = strings.Trim(out, "\r\n")
216
+	if out != "false" {
217
+		t.Fatal("Container should be stopped")
218
+	}
219
+
220
+	// start all the three containers, container `child_first` start first which should be faild
221
+	// container 'parent' start second and then start container 'child_second'
222
+	cmd = exec.Command(dockerBinary, "start", "child_first", "parent", "child_second")
223
+	out, _, err = runCommandWithOutput(cmd)
224
+	if !strings.Contains(out, "Cannot start container child_first") || err == nil {
225
+		t.Fatal("Expected error but got none")
226
+	}
227
+
228
+	for container, expected := range map[string]string{"parent": "true", "child_first": "false", "child_second": "true"} {
229
+		cmd = exec.Command(dockerBinary, "inspect", "-f", "{{.State.Running}}", container)
230
+		out, _, err = runCommandWithOutput(cmd)
231
+		if err != nil {
232
+			t.Fatal(out, err)
233
+		}
234
+		out = strings.Trim(out, "\r\n")
235
+		if out != expected {
236
+			t.Fatal("Container running state wrong")
237
+		}
238
+
239
+	}
240
+
241
+	logDone("start - start multiple containers continue on one failed")
242
+}