浏览代码

Clean some runCommandWithOutput accross integration-cli code

There is still ways to go

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
Vincent Demeester 8 年之前
父节点
当前提交
87e3fcfe1e

+ 5 - 6
integration-cli/docker_cli_build_unix_test.go

@@ -16,6 +16,7 @@ import (
 
 	"github.com/docker/docker/integration-cli/checker"
 	"github.com/docker/docker/pkg/testutil"
+	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/docker/go-units"
 	"github.com/go-check/check"
 )
@@ -100,12 +101,10 @@ func (s *DockerSuite) TestBuildAddChangeOwnership(c *check.C) {
 		}
 		defer testFile.Close()
 
-		chownCmd := exec.Command("chown", "daemon:daemon", "foo")
-		chownCmd.Dir = tmpDir
-		out, _, err := runCommandWithOutput(chownCmd)
-		if err != nil {
-			c.Fatal(err, out)
-		}
+		icmd.RunCmd(icmd.Cmd{
+			Command: []string{"chown", "daemon:daemon", "foo"},
+			Dir: tmpDir,
+		}).Assert(c, icmd.Success)
 
 		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
 			c.Fatalf("failed to open destination dockerfile: %v", err)

+ 35 - 28
integration-cli/docker_cli_config_test.go

@@ -12,6 +12,7 @@ import (
 	"github.com/docker/docker/api"
 	"github.com/docker/docker/dockerversion"
 	"github.com/docker/docker/integration-cli/checker"
+	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/docker/docker/pkg/homedir"
 	"github.com/go-check/check"
 )
@@ -51,15 +52,15 @@ func (s *DockerSuite) TestConfigHTTPHeader(c *check.C) {
 	err = ioutil.WriteFile(tmpCfg, []byte(data), 0600)
 	c.Assert(err, checker.IsNil)
 
-	cmd := exec.Command(dockerBinary, "-H="+server.URL[7:], "ps")
-	out, _, _ := runCommandWithOutput(cmd)
+	result := icmd.RunCommand(dockerBinary, "-H="+server.URL[7:], "ps")
+	result.Assert(c, icmd.Success)
 
 	c.Assert(headers["User-Agent"], checker.NotNil, check.Commentf("Missing User-Agent"))
 
-	c.Assert(headers["User-Agent"][0], checker.Equals, "Docker-Client/"+dockerversion.Version+" ("+runtime.GOOS+")", check.Commentf("Badly formatted User-Agent,out:%v", out))
+	c.Assert(headers["User-Agent"][0], checker.Equals, "Docker-Client/"+dockerversion.Version+" ("+runtime.GOOS+")", check.Commentf("Badly formatted User-Agent,out:%v", result.Combined()))
 
 	c.Assert(headers["Myheader"], checker.NotNil)
-	c.Assert(headers["Myheader"][0], checker.Equals, "MyValue", check.Commentf("Missing/bad header,out:%v", out))
+	c.Assert(headers["Myheader"][0], checker.Equals, "MyValue", check.Commentf("Missing/bad header,out:%v", result.Combined()))
 
 }
 
@@ -72,11 +73,10 @@ func (s *DockerSuite) TestConfigDir(c *check.C) {
 	dockerCmd(c, "--config", cDir, "ps")
 
 	// Test with env var too
-	cmd := exec.Command(dockerBinary, "ps")
-	cmd.Env = appendBaseEnv(true, "DOCKER_CONFIG="+cDir)
-	out, _, err := runCommandWithOutput(cmd)
-
-	c.Assert(err, checker.IsNil, check.Commentf("ps2 didn't work,out:%v", out))
+	icmd.RunCmd(icm.Cmd{
+		Command: []string{dockerBinary, "ps"},
+		Env: appendBaseEnv(true, "DOCKER_CONFIG="+cDir),
+	}).Assert(c, icmd.Success)
 
 	// Start a server so we can check to see if the config file was
 	// loaded properly
@@ -99,42 +99,49 @@ func (s *DockerSuite) TestConfigDir(c *check.C) {
 
 	env := appendBaseEnv(false)
 
-	cmd = exec.Command(dockerBinary, "--config", cDir, "-H="+server.URL[7:], "ps")
-	cmd.Env = env
-	out, _, err = runCommandWithOutput(cmd)
-
-	c.Assert(err, checker.NotNil, check.Commentf("out:%v", out))
+	icmd.RunCmd(icmd.Cmd{
+		Command: []string{dockerBinary, "--config", cDir, "-H="+server.URL[7:], "ps"},
+		Env: env,
+	}).Assert(c, icmd.Exepected{
+		Error: "exit status 1",
+	})
 	c.Assert(headers["Myheader"], checker.NotNil)
 	c.Assert(headers["Myheader"][0], checker.Equals, "MyValue", check.Commentf("ps3 - Missing header,out:%v", out))
 
 	// Reset headers and try again using env var this time
 	headers = map[string][]string{}
-	cmd = exec.Command(dockerBinary, "-H="+server.URL[7:], "ps")
-	cmd.Env = append(env, "DOCKER_CONFIG="+cDir)
-	out, _, err = runCommandWithOutput(cmd)
-
-	c.Assert(err, checker.NotNil, check.Commentf("%v", out))
+	icmd.RunCmd(icmd.Cmd{
+		Command: []string{dockerBinary, "--config", cDir, "-H="+server.URL[7:], "ps"},
+		Env: append(env, "DOCKER_CONFIG="+cDir),
+	}).Assert(c, icmd.Exepected{
+		Error: "exit status 1",
+	})
 	c.Assert(headers["Myheader"], checker.NotNil)
 	c.Assert(headers["Myheader"][0], checker.Equals, "MyValue", check.Commentf("ps4 - Missing header,out:%v", out))
 
+	// FIXME(vdemeester) should be a unit test
 	// Reset headers and make sure flag overrides the env var
 	headers = map[string][]string{}
-	cmd = exec.Command(dockerBinary, "--config", cDir, "-H="+server.URL[7:], "ps")
-	cmd.Env = append(env, "DOCKER_CONFIG=MissingDir")
-	out, _, err = runCommandWithOutput(cmd)
-
-	c.Assert(err, checker.NotNil, check.Commentf("out:%v", out))
+	icmd.RunCmd(icmd.Cmd{
+		Command: []string{dockerBinary, "--config", cDir, "-H="+server.URL[7:], "ps"},
+		Env: append(env, "DOCKER_CONFIG=MissingDir"),
+	}).Assert(c, icmd.Exepected{
+		Error: "exit status 1",
+	})
 	c.Assert(headers["Myheader"], checker.NotNil)
 	c.Assert(headers["Myheader"][0], checker.Equals, "MyValue", check.Commentf("ps5 - Missing header,out:%v", out))
 
+	// FIXME(vdemeester) should be a unit test
 	// Reset headers and make sure flag overrides the env var.
 	// Almost same as previous but make sure the "MissingDir" isn't
 	// ignore - we don't want to default back to the env var.
 	headers = map[string][]string{}
-	cmd = exec.Command(dockerBinary, "--config", "MissingDir", "-H="+server.URL[7:], "ps")
-	cmd.Env = append(env, "DOCKER_CONFIG="+cDir)
-	out, _, err = runCommandWithOutput(cmd)
+	icmd.RunCmd(icmd.Cmd{
+		Command: []string{dockerBinary, "--config", "MissingDir", "-H="+server.URL[7:], "ps"},
+		Env: append(env, "DOCKER_CONFIG="+cDir),
+	}).Assert(c, icmd.Exepected{
+		Error: "exit status 1",
+	})
 
-	c.Assert(err, checker.NotNil, check.Commentf("out:%v", out))
 	c.Assert(headers["Myheader"], checker.IsNil, check.Commentf("ps6 - Headers shouldn't be the expected value,out:%v", out))
 }

+ 8 - 15
integration-cli/docker_cli_daemon_plugins_test.go

@@ -9,6 +9,7 @@ import (
 	"strings"
 	"syscall"
 
+	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/docker/docker/integration-cli/checker"
 	"github.com/docker/docker/pkg/mount"
 	"github.com/go-check/check"
@@ -92,10 +93,7 @@ func (s *DockerDaemonSuite) TestDaemonKillLiveRestoreWithPlugins(c *check.C) {
 		c.Fatalf("Could not kill daemon: %v", err)
 	}
 
-	cmd := exec.Command("pgrep", "-f", pluginProcessName)
-	if out, ec, err := runCommandWithOutput(cmd); ec != 0 {
-		c.Fatalf("Expected exit code '0', got %d err: %v output: %s ", ec, err, out)
-	}
+	icmd.RunCommand("pgrep", "-f", pluginProcessName).Assert(c, icmd.Success)
 }
 
 // TestDaemonShutdownLiveRestoreWithPlugins SIGTERMs daemon started with --live-restore.
@@ -121,10 +119,7 @@ func (s *DockerDaemonSuite) TestDaemonShutdownLiveRestoreWithPlugins(c *check.C)
 		c.Fatalf("Could not kill daemon: %v", err)
 	}
 
-	cmd := exec.Command("pgrep", "-f", pluginProcessName)
-	if out, ec, err := runCommandWithOutput(cmd); ec != 0 {
-		c.Fatalf("Expected exit code '0', got %d err: %v output: %s ", ec, err, out)
-	}
+	icmd.RunCommand("pgrep", "-f", pluginProcessName).Assert(c, icmd.Success)
 }
 
 // TestDaemonShutdownWithPlugins shuts down running plugins.
@@ -156,15 +151,13 @@ func (s *DockerDaemonSuite) TestDaemonShutdownWithPlugins(c *check.C) {
 		}
 	}
 
-	cmd := exec.Command("pgrep", "-f", pluginProcessName)
-	if out, ec, err := runCommandWithOutput(cmd); ec != 1 {
-		c.Fatalf("Expected exit code '1', got %d err: %v output: %s ", ec, err, out)
-	}
+	icmd.RunCommand("pgrep", "-f", pluginProcessName).Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Error: "exit status 1",
+	})
 
 	s.d.Start(c, "--live-restore")
-	cmd = exec.Command("pgrep", "-f", pluginProcessName)
-	out, _, err := runCommandWithOutput(cmd)
-	c.Assert(err, checker.IsNil, check.Commentf(out))
+	icmd.RunCommand("pgrep", "-f", pluginProcessName).Assert(c, icmd.Success)
 }
 
 // TestVolumePlugin tests volume creation using a plugin.

+ 86 - 151
integration-cli/docker_cli_daemon_test.go

@@ -262,30 +262,15 @@ func (s *DockerDaemonSuite) TestDaemonIptablesClean(c *check.C) {
 		c.Fatalf("Could not run top: %s, %v", out, err)
 	}
 
-	// get output from iptables with container running
 	ipTablesSearchString := "tcp dpt:80"
-	ipTablesCmd := exec.Command("iptables", "-nvL")
-	out, _, err := runCommandWithOutput(ipTablesCmd)
-	if err != nil {
-		c.Fatalf("Could not run iptables -nvL: %s, %v", out, err)
-	}
 
-	if !strings.Contains(out, ipTablesSearchString) {
-		c.Fatalf("iptables output should have contained %q, but was %q", ipTablesSearchString, out)
-	}
+	// get output from iptables with container running
+	verifyIPTablesContains(c, ipTablesSearchString)
 
 	s.d.Stop(c)
 
 	// get output from iptables after restart
-	ipTablesCmd = exec.Command("iptables", "-nvL")
-	out, _, err = runCommandWithOutput(ipTablesCmd)
-	if err != nil {
-		c.Fatalf("Could not run iptables -nvL: %s, %v", out, err)
-	}
-
-	if strings.Contains(out, ipTablesSearchString) {
-		c.Fatalf("iptables output should not have contained %q, but was %q", ipTablesSearchString, out)
-	}
+	verifyIPTablesDoesNotContains(c, ipTablesSearchString)
 }
 
 func (s *DockerDaemonSuite) TestDaemonIptablesCreate(c *check.C) {
@@ -297,36 +282,36 @@ func (s *DockerDaemonSuite) TestDaemonIptablesCreate(c *check.C) {
 
 	// get output from iptables with container running
 	ipTablesSearchString := "tcp dpt:80"
-	ipTablesCmd := exec.Command("iptables", "-nvL")
-	out, _, err := runCommandWithOutput(ipTablesCmd)
-	if err != nil {
-		c.Fatalf("Could not run iptables -nvL: %s, %v", out, err)
-	}
-
-	if !strings.Contains(out, ipTablesSearchString) {
-		c.Fatalf("iptables output should have contained %q, but was %q", ipTablesSearchString, out)
-	}
+	verifyIPTablesContains(c, ipTablesSearchString)
 
 	s.d.Restart(c)
 
 	// make sure the container is not running
 	runningOut, err := s.d.Cmd("inspect", "--format={{.State.Running}}", "top")
 	if err != nil {
-		c.Fatalf("Could not inspect on container: %s, %v", out, err)
+		c.Fatalf("Could not inspect on container: %s, %v", runningOut, err)
 	}
 	if strings.TrimSpace(runningOut) != "true" {
 		c.Fatalf("Container should have been restarted after daemon restart. Status running should have been true but was: %q", strings.TrimSpace(runningOut))
 	}
 
 	// get output from iptables after restart
-	ipTablesCmd = exec.Command("iptables", "-nvL")
-	out, _, err = runCommandWithOutput(ipTablesCmd)
-	if err != nil {
-		c.Fatalf("Could not run iptables -nvL: %s, %v", out, err)
+	verifyIPTablesContains(c, ipTablesSearchString)
+}
+
+func verifyIPTablesContains(c *check.C, ipTablesSearchString string) {
+	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())
 	}
+}
 
-	if !strings.Contains(out, ipTablesSearchString) {
-		c.Fatalf("iptables output after restart should have contained %q, but was %q", ipTablesSearchString, out)
+func verifyIPTablesDoesNotContains(c *check.C, ipTablesSearchString string) {
+	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())
 	}
 }
 
@@ -564,10 +549,7 @@ func (s *DockerDaemonSuite) TestDaemonExitOnFailure(c *check.C) {
 			c.Fatalf("Expected daemon not to start, got %v", err)
 		}
 		// look in the log and make sure we got the message that daemon is shutting down
-		runCmd := exec.Command("grep", "Error starting daemon", s.d.LogFileName())
-		if out, _, err := runCommandWithOutput(runCmd); err != nil {
-			c.Fatalf("Expected 'Error starting daemon' message; but doesn't exist in log: %q, err: %v", out, err)
-		}
+		icmd.RunCommand("grep", "Error starting daemon", s.d.LogFileName()).Assert(c, icmd.Success)
 	} else {
 		//if we didn't get an error and the daemon is running, this is a failure
 		c.Fatal("Conflicting options should cause the daemon to error out with a failure")
@@ -584,20 +566,15 @@ func (s *DockerDaemonSuite) TestDaemonBridgeExternal(c *check.C) {
 	bridgeIP := "192.169.1.1/24"
 	_, bridgeIPNet, _ := net.ParseCIDR(bridgeIP)
 
-	out, err := createInterface(c, "bridge", bridgeName, bridgeIP)
-	c.Assert(err, check.IsNil, check.Commentf(out))
+	createInterface(c, "bridge", bridgeName, bridgeIP)
 	defer deleteInterface(c, bridgeName)
 
 	d.StartWithBusybox(c, "--bridge", bridgeName)
 
 	ipTablesSearchString := bridgeIPNet.String()
-	ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL")
-	out, _, err = runCommandWithOutput(ipTablesCmd)
-	c.Assert(err, check.IsNil)
-
-	c.Assert(strings.Contains(out, ipTablesSearchString), check.Equals, true,
-		check.Commentf("iptables output should have contained %q, but was %q",
-			ipTablesSearchString, out))
+	icmd.RunCommand("iptables", "-t", "nat", "-nvL").Assert(c, icmd.Expected{
+		Out: ipTablesSearchString,
+	})
 
 	_, err = d.Cmd("run", "-d", "--name", "ExtContainer", "busybox", "top")
 	c.Assert(err, check.IsNil)
@@ -617,41 +594,27 @@ func (s *DockerDaemonSuite) TestDaemonBridgeNone(c *check.C) {
 	defer d.Restart(c)
 
 	// verify docker0 iface is not there
-	out, _, err := runCommandWithOutput(exec.Command("ifconfig", "docker0"))
-	c.Assert(err, check.NotNil, check.Commentf("docker0 should not be present if daemon started with --bridge=none"))
-	c.Assert(strings.Contains(out, "Device not found"), check.Equals, true)
+	icmd.RunCommand("ifconfig", "docker0").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Error:    "exit status 1",
+		Err:      "Device not found",
+	})
 
 	// verify default "bridge" network is not there
-	out, err = d.Cmd("network", "inspect", "bridge")
+	out, err := d.Cmd("network", "inspect", "bridge")
 	c.Assert(err, check.NotNil, check.Commentf("\"bridge\" network should not be present if daemon started with --bridge=none"))
 	c.Assert(strings.Contains(out, "No such network"), check.Equals, true)
 }
 
-func createInterface(c *check.C, ifType string, ifName string, ipNet string) (string, error) {
-	args := []string{"link", "add", "name", ifName, "type", ifType}
-	ipLinkCmd := exec.Command("ip", args...)
-	out, _, err := runCommandWithOutput(ipLinkCmd)
-	if err != nil {
-		return out, err
-	}
-
-	ifCfgCmd := exec.Command("ifconfig", ifName, ipNet, "up")
-	out, _, err = runCommandWithOutput(ifCfgCmd)
-	return out, err
+func createInterface(c *check.C, ifType string, ifName string, ipNet string) {
+	icmd.RunCommand("ip", "link", "add", "name", ifName, "type", ifType).Assert(c, icmd.Success)
+	icmd.RunCommand("ifconfig", ifName, ipNet, "up").Assert(c, icmd.Success)
 }
 
 func deleteInterface(c *check.C, ifName string) {
-	ifCmd := exec.Command("ip", "link", "delete", ifName)
-	out, _, err := runCommandWithOutput(ifCmd)
-	c.Assert(err, check.IsNil, check.Commentf(out))
-
-	flushCmd := exec.Command("iptables", "-t", "nat", "--flush")
-	out, _, err = runCommandWithOutput(flushCmd)
-	c.Assert(err, check.IsNil, check.Commentf(out))
-
-	flushCmd = exec.Command("iptables", "--flush")
-	out, _, err = runCommandWithOutput(flushCmd)
-	c.Assert(err, check.IsNil, check.Commentf(out))
+	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)
 }
 
 func (s *DockerDaemonSuite) TestDaemonBridgeIP(c *check.C) {
@@ -723,8 +686,7 @@ func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr(c *check.C) {
 	bridgeName := "external-bridge"
 	bridgeIP := "192.169.1.1/24"
 
-	out, err := createInterface(c, "bridge", bridgeName, bridgeIP)
-	c.Assert(err, check.IsNil, check.Commentf(out))
+	createInterface(c, "bridge", bridgeName, bridgeIP)
 	defer deleteInterface(c, bridgeName)
 
 	args := []string{"--bridge", bridgeName, "--fixed-cidr", "192.169.1.0/30"}
@@ -747,14 +709,13 @@ func (s *DockerDaemonSuite) TestDaemonBridgeFixedCidr2(c *check.C) {
 	bridgeName := "external-bridge"
 	bridgeIP := "10.2.2.1/16"
 
-	out, err := createInterface(c, "bridge", bridgeName, bridgeIP)
-	c.Assert(err, check.IsNil, check.Commentf(out))
+	createInterface(c, "bridge", bridgeName, bridgeIP)
 	defer deleteInterface(c, bridgeName)
 
 	d.StartWithBusybox(c, "--bip", bridgeIP, "--fixed-cidr", "10.2.2.0/24")
 	defer s.d.Restart(c)
 
-	out, err = d.Cmd("run", "-d", "--name", "bb", "busybox", "top")
+	out, err := d.Cmd("run", "-d", "--name", "bb", "busybox", "top")
 	c.Assert(err, checker.IsNil, check.Commentf(out))
 	defer d.Cmd("stop", "bb")
 
@@ -772,14 +733,13 @@ func (s *DockerDaemonSuite) TestDaemonBridgeFixedCIDREqualBridgeNetwork(c *check
 	bridgeName := "external-bridge"
 	bridgeIP := "172.27.42.1/16"
 
-	out, err := createInterface(c, "bridge", bridgeName, bridgeIP)
-	c.Assert(err, check.IsNil, check.Commentf(out))
+	createInterface(c, "bridge", bridgeName, bridgeIP)
 	defer deleteInterface(c, bridgeName)
 
 	d.StartWithBusybox(c, "--bridge", bridgeName, "--fixed-cidr", bridgeIP)
 	defer s.d.Restart(c)
 
-	out, err = d.Cmd("run", "-d", "busybox", "top")
+	out, err := d.Cmd("run", "-d", "busybox", "top")
 	c.Assert(err, check.IsNil, check.Commentf(out))
 	cid1 := strings.TrimSpace(out)
 	defer d.Cmd("stop", cid1)
@@ -871,21 +831,18 @@ func (s *DockerDaemonSuite) TestDaemonIP(c *check.C) {
 	c.Assert(strings.Contains(out, "Error starting userland proxy"), check.Equals, true)
 
 	ifName := "dummy"
-	out, err = createInterface(c, "dummy", ifName, ipStr)
-	c.Assert(err, check.IsNil, check.Commentf(out))
+	createInterface(c, "dummy", ifName, ipStr)
 	defer deleteInterface(c, ifName)
 
 	_, err = d.Cmd("run", "-d", "-p", "8000:8000", "busybox", "top")
 	c.Assert(err, check.IsNil)
 
-	ipTablesCmd := exec.Command("iptables", "-t", "nat", "-nvL")
-	out, _, err = runCommandWithOutput(ipTablesCmd)
-	c.Assert(err, check.IsNil)
-
+	result := icmd.RunCommand("iptables", "-t", "nat", "-nvL")
+	result.Assert(c, icmd.Success)
 	regex := fmt.Sprintf("DNAT.*%s.*dpt:8000", ip.String())
-	matched, _ := regexp.MatchString(regex, out)
+	matched, _ := regexp.MatchString(regex, result.Combined())
 	c.Assert(matched, check.Equals, true,
-		check.Commentf("iptables output should have contained %q, but was %q", regex, out))
+		check.Commentf("iptables output should have contained %q, but was %q", regex, result.Combined()))
 }
 
 func (s *DockerDaemonSuite) TestDaemonICCPing(c *check.C) {
@@ -895,22 +852,18 @@ func (s *DockerDaemonSuite) TestDaemonICCPing(c *check.C) {
 	bridgeName := "external-bridge"
 	bridgeIP := "192.169.1.1/24"
 
-	out, err := createInterface(c, "bridge", bridgeName, bridgeIP)
-	c.Assert(err, check.IsNil, check.Commentf(out))
+	createInterface(c, "bridge", bridgeName, bridgeIP)
 	defer deleteInterface(c, bridgeName)
 
-	args := []string{"--bridge", bridgeName, "--icc=false"}
-	d.StartWithBusybox(c, args...)
+	d.StartWithBusybox(c, "--bridge", bridgeName, "--icc=false")
 	defer d.Restart(c)
 
-	ipTablesCmd := exec.Command("iptables", "-nvL", "FORWARD")
-	out, _, err = runCommandWithOutput(ipTablesCmd)
-	c.Assert(err, check.IsNil)
-
+	result := icmd.RunCommand("iptables", "-nvL", "FORWARD")
+	result.Assert(c, icmd.Success)
 	regex := fmt.Sprintf("DROP.*all.*%s.*%s", bridgeName, bridgeName)
-	matched, _ := regexp.MatchString(regex, out)
+	matched, _ := regexp.MatchString(regex, result.Combined())
 	c.Assert(matched, check.Equals, true,
-		check.Commentf("iptables output should have contained %q, but was %q", regex, out))
+		check.Commentf("iptables output should have contained %q, but was %q", regex, result.Combined()))
 
 	// Pinging another container must fail with --icc=false
 	pingContainers(c, d, true)
@@ -924,7 +877,7 @@ func (s *DockerDaemonSuite) TestDaemonICCPing(c *check.C) {
 	// But, Pinging external or a Host interface must succeed
 	pingCmd := fmt.Sprintf("ping -c 1 %s -W 1", ip.String())
 	runArgs := []string{"run", "--rm", "busybox", "sh", "-c", pingCmd}
-	_, err = d.Cmd(runArgs...)
+	_, err := d.Cmd(runArgs...)
 	c.Assert(err, check.IsNil)
 }
 
@@ -934,24 +887,20 @@ func (s *DockerDaemonSuite) TestDaemonICCLinkExpose(c *check.C) {
 	bridgeName := "external-bridge"
 	bridgeIP := "192.169.1.1/24"
 
-	out, err := createInterface(c, "bridge", bridgeName, bridgeIP)
-	c.Assert(err, check.IsNil, check.Commentf(out))
+	createInterface(c, "bridge", bridgeName, bridgeIP)
 	defer deleteInterface(c, bridgeName)
 
-	args := []string{"--bridge", bridgeName, "--icc=false"}
-	d.StartWithBusybox(c, args...)
+	d.StartWithBusybox(c, "--bridge", bridgeName, "--icc=false")
 	defer d.Restart(c)
 
-	ipTablesCmd := exec.Command("iptables", "-nvL", "FORWARD")
-	out, _, err = runCommandWithOutput(ipTablesCmd)
-	c.Assert(err, check.IsNil)
-
+	result := icmd.RunCommand("iptables", "-nvL", "FORWARD")
+	result.Assert(c, icmd.Success)
 	regex := fmt.Sprintf("DROP.*all.*%s.*%s", bridgeName, bridgeName)
-	matched, _ := regexp.MatchString(regex, out)
+	matched, _ := regexp.MatchString(regex, result.Combined())
 	c.Assert(matched, check.Equals, true,
-		check.Commentf("iptables output should have contained %q, but was %q", regex, out))
+		check.Commentf("iptables output should have contained %q, but was %q", regex, result.Combined()))
 
-	out, err = d.Cmd("run", "-d", "--expose", "4567", "--name", "icc1", "busybox", "nc", "-l", "-p", "4567")
+	out, err := d.Cmd("run", "-d", "--expose", "4567", "--name", "icc1", "busybox", "nc", "-l", "-p", "4567")
 	c.Assert(err, check.IsNil, check.Commentf(out))
 
 	out, err = d.Cmd("run", "--link", "icc1:icc1", "busybox", "nc", "icc1", "4567")
@@ -962,14 +911,13 @@ func (s *DockerDaemonSuite) TestDaemonLinksIpTablesRulesWhenLinkAndUnlink(c *che
 	bridgeName := "external-bridge"
 	bridgeIP := "192.169.1.1/24"
 
-	out, err := createInterface(c, "bridge", bridgeName, bridgeIP)
-	c.Assert(err, check.IsNil, check.Commentf(out))
+	createInterface(c, "bridge", bridgeName, bridgeIP)
 	defer deleteInterface(c, bridgeName)
 
 	s.d.StartWithBusybox(c, "--bridge", bridgeName, "--icc=false")
 	defer s.d.Restart(c)
 
-	_, err = s.d.Cmd("run", "-d", "--name", "child", "--publish", "8080:80", "busybox", "top")
+	_, err := s.d.Cmd("run", "-d", "--name", "child", "--publish", "8080:80", "busybox", "top")
 	c.Assert(err, check.IsNil)
 	_, err = s.d.Cmd("run", "-d", "--name", "parent", "--link", "child:http", "busybox", "top")
 	c.Assert(err, check.IsNil)
@@ -1464,10 +1412,7 @@ func (s *DockerDaemonSuite) TestCleanupMountsAfterDaemonAndContainerKill(c *chec
 	c.Assert(strings.Contains(string(mountOut), id), check.Equals, true, comment)
 
 	// kill the container
-	runCmd := exec.Command(ctrBinary, "--address", "unix:///var/run/docker/libcontainerd/docker-containerd.sock", "containers", "kill", id)
-	if out, ec, err := runCommandWithOutput(runCmd); err != nil {
-		c.Fatalf("Failed to run ctr, ExitCode: %d, err: %v output: %s id: %s\n", ec, err, out, id)
-	}
+	icmd.RunCommand(ctrBinary, "--address", "unix:///var/run/docker/libcontainerd/docker-containerd.sock", "containers", "kill", id).Assert(c, icmd.Success)
 
 	// restart daemon.
 	d.Restart(c)
@@ -1564,10 +1509,9 @@ func (s *DockerDaemonSuite) TestDaemonRestartCleanupNetns(c *check.C) {
 	}
 
 	// Test if the file still exists
-	out, _, err = runCommandWithOutput(exec.Command("stat", "-c", "%n", fileName))
-	out = strings.TrimSpace(out)
-	c.Assert(err, check.IsNil, check.Commentf("Output: %s", out))
-	c.Assert(out, check.Equals, fileName, check.Commentf("Output: %s", out))
+	icmd.RunCommand("stat", "-c", "%n", fileName).Assert(c, icmd.Expected{
+		Out: fileName,
+	})
 
 	// Remove the container and restart the daemon
 	if out, err := s.d.Cmd("rm", "netns"); err != nil {
@@ -1577,32 +1521,34 @@ func (s *DockerDaemonSuite) TestDaemonRestartCleanupNetns(c *check.C) {
 	s.d.Restart(c)
 
 	// Test again and see now the netns file does not exist
-	out, _, err = runCommandWithOutput(exec.Command("stat", "-c", "%n", fileName))
-	out = strings.TrimSpace(out)
-	c.Assert(err, check.Not(check.IsNil), check.Commentf("Output: %s", out))
+	icmd.RunCommand("stat", "-c", "%n", fileName).Assert(c, icmd.Expected{
+		Err:      "No such file or directory",
+		ExitCode: 1,
+	})
 }
 
 // tests regression detailed in #13964 where DOCKER_TLS_VERIFY env is ignored
 func (s *DockerDaemonSuite) TestDaemonTLSVerifyIssue13964(c *check.C) {
 	host := "tcp://localhost:4271"
 	s.d.Start(c, "-H", host)
-	cmd := exec.Command(dockerBinary, "-H", host, "info")
-	cmd.Env = []string{"DOCKER_TLS_VERIFY=1", "DOCKER_CERT_PATH=fixtures/https"}
-	out, _, err := runCommandWithOutput(cmd)
-	c.Assert(err, check.Not(check.IsNil), check.Commentf("%s", out))
-	c.Assert(strings.Contains(out, "error during connect"), check.Equals, true)
-
+	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",
+	})
 }
 
 func setupV6(c *check.C) {
 	// Hack to get the right IPv6 address on docker0, which has already been created
 	result := icmd.RunCommand("ip", "addr", "add", "fe80::1/64", "dev", "docker0")
-	result.Assert(c, icmd.Expected{})
+	result.Assert(c, icmd.Success)
 }
 
 func teardownV6(c *check.C) {
 	result := icmd.RunCommand("ip", "addr", "del", "fe80::1/64", "dev", "docker0")
-	result.Assert(c, icmd.Expected{})
+	result.Assert(c, icmd.Success)
 }
 
 func (s *DockerDaemonSuite) TestDaemonRestartWithContainerWithRestartPolicyAlways(c *check.C) {
@@ -1708,10 +1654,7 @@ func (s *DockerDaemonSuite) TestDaemonCorruptedLogDriverAddress(c *check.C) {
 	})
 	c.Assert(d.StartWithError("--log-driver=syslog", "--log-opt", "syslog-address=corrupted:42"), check.NotNil)
 	expected := "Failed to set log opts: syslog-address should be in form proto://address"
-	runCmd := exec.Command("grep", expected, d.LogFileName())
-	if out, _, err := runCommandWithOutput(runCmd); err != nil {
-		c.Fatalf("Expected %q message; but doesn't exist in log: %q, err: %v", expected, out, err)
-	}
+	icmd.RunCommand("grep", expected, d.LogFileName()).Assert(c, icmd.Success)
 }
 
 // FIXME(vdemeester) should be a unit test
@@ -1721,10 +1664,7 @@ func (s *DockerDaemonSuite) TestDaemonCorruptedFluentdAddress(c *check.C) {
 	})
 	c.Assert(d.StartWithError("--log-driver=fluentd", "--log-opt", "fluentd-address=corrupted:c"), check.NotNil)
 	expected := "Failed to set log opts: invalid fluentd-address corrupted:c: "
-	runCmd := exec.Command("grep", expected, d.LogFileName())
-	if out, _, err := runCommandWithOutput(runCmd); err != nil {
-		c.Fatalf("Expected %q message; but doesn't exist in log: %q, err: %v", expected, out, err)
-	}
+	icmd.RunCommand("grep", expected, d.LogFileName()).Assert(c, icmd.Success)
 }
 
 // FIXME(vdemeester) Use a new daemon instance instead of the Suite one
@@ -1808,13 +1748,11 @@ func (s *DockerDaemonSuite) TestDaemonNoSpaceLeftOnDeviceError(c *check.C) {
 	// create a 2MiB image and mount it as graph root
 	// 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)
 	dockerCmd(c, "run", "--rm", "-v", testDir+":/test", "busybox", "sh", "-c", "dd of=/test/testfs.img bs=1M seek=2 count=0")
-	out, _, err := runCommandWithOutput(exec.Command("mkfs.ext4", "-F", filepath.Join(testDir, "testfs.img"))) // `mkfs.ext4` is not in busybox
-	c.Assert(err, checker.IsNil, check.Commentf(out))
+	icmd.RunCommand("mkfs.ext4", "-F", filepath.Join(testDir, "testfs.img")).Assert(c, icmd.Success)
 
-	cmd := exec.Command("losetup", "-f", "--show", filepath.Join(testDir, "testfs.img"))
-	loout, err := cmd.CombinedOutput()
-	c.Assert(err, checker.IsNil)
-	loopname := strings.TrimSpace(string(loout))
+	result := icmd.RunCommand("losetup", "-f", "--show", filepath.Join(testDir, "testfs.img"))
+	result.Assert(c, icmd.Success)
+	loopname := strings.TrimSpace(string(result.Combined()))
 	defer exec.Command("losetup", "-d", loopname).Run()
 
 	dockerCmd(c, "run", "--privileged", "--rm", "-v", testDir+":/test:shared", "busybox", "sh", "-c", fmt.Sprintf("mkdir -p /test/test-mount && mount -t ext4 -no loop,rw %v /test/test-mount", loopname))
@@ -2007,10 +1945,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithKilledRunningContainer(t *check
 	}
 
 	// kill the container
-	runCmd := exec.Command(ctrBinary, "--address", "unix:///var/run/docker/libcontainerd/docker-containerd.sock", "containers", "kill", cid)
-	if out, ec, err := runCommandWithOutput(runCmd); err != nil {
-		t.Fatalf("Failed to run ctr, ExitCode: %d, err: '%v' output: '%s' cid: '%s'\n", ec, err, out, cid)
-	}
+	icmd.RunCommand(ctrBinary, "--address", "unix:///var/run/docker/libcontainerd/docker-containerd.sock", "containers", "kill", cid).Assert(c, icmd.Success)
 
 	// Give time to containerd to process the command if we don't
 	// the exit event might be received after we do the inspect

+ 15 - 13
integration-cli/docker_cli_export_import_test.go

@@ -2,10 +2,10 @@ package main
 
 import (
 	"os"
-	"os/exec"
 	"strings"
 
 	"github.com/docker/docker/integration-cli/checker"
+	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/go-check/check"
 )
 
@@ -18,12 +18,13 @@ func (s *DockerSuite) TestExportContainerAndImportImage(c *check.C) {
 
 	out, _ := dockerCmd(c, "export", containerID)
 
-	importCmd := exec.Command(dockerBinary, "import", "-", "repo/testexp:v1")
-	importCmd.Stdin = strings.NewReader(out)
-	out, _, err := runCommandWithOutput(importCmd)
-	c.Assert(err, checker.IsNil, check.Commentf("failed to import image repo/testexp:v1: %s", out))
+	result := icmd.RunCmd(icmd.Cmd{
+		Command: dockerBinary, "import", "-", "repo/testexp:v1",
+		Stdin: strings.NewReader(out),
+	})
+	result.Assert(c, icmd.Success)
 
-	cleanedImageID := strings.TrimSpace(out)
+	cleanedImageID := strings.TrimSpace(result.Combined())
 	c.Assert(cleanedImageID, checker.Not(checker.Equals), "", check.Commentf("output should have been an image id"))
 }
 
@@ -36,14 +37,15 @@ func (s *DockerSuite) TestExportContainerWithOutputAndImportImage(c *check.C) {
 	dockerCmd(c, "export", "--output=testexp.tar", containerID)
 	defer os.Remove("testexp.tar")
 
-	out, _, err := runCommandWithOutput(exec.Command("cat", "testexp.tar"))
-	c.Assert(err, checker.IsNil, check.Commentf(out))
+	resultCat := icmd.RunCommand("cat", "testexp.tar")
+	resultCat.Assert(c, icmd.Success)
 
-	importCmd := exec.Command(dockerBinary, "import", "-", "repo/testexp:v1")
-	importCmd.Stdin = strings.NewReader(out)
-	out, _, err = runCommandWithOutput(importCmd)
-	c.Assert(err, checker.IsNil, check.Commentf("failed to import image repo/testexp:v1: %s", out))
+	result := icmd.RunCmd(icmd.Cmd{
+		Command: dockerBinary, "import", "-", "repo/testexp:v1",
+		Stdin: strings.NewReader(resultCat.Combined()),
+	})
+	result.Assert(c, icmd.Success)
 
-	cleanedImageID := strings.TrimSpace(out)
+	cleanedImageID := strings.TrimSpace(result.Combined())
 	c.Assert(cleanedImageID, checker.Not(checker.Equals), "", check.Commentf("output should have been an image id"))
 }

+ 15 - 12
integration-cli/docker_cli_help_test.go

@@ -14,6 +14,7 @@ import (
 )
 
 func (s *DockerSuite) TestHelpTextVerify(c *check.C) {
+	// FIXME(vdemeester) should be a unit test, probably using golden files ?
 	testRequires(c, DaemonIsLinux)
 
 	// Make sure main help text fits within 80 chars and that
@@ -52,11 +53,12 @@ func (s *DockerSuite) TestHelpTextVerify(c *check.C) {
 		scanForHome := runtime.GOOS != "windows" && home != "/"
 
 		// Check main help text to make sure its not over 80 chars
-		helpCmd := exec.Command(dockerBinary, "help")
-		helpCmd.Env = newEnvs
-		out, _, err := runCommandWithOutput(helpCmd)
-		c.Assert(err, checker.IsNil, check.Commentf(out))
-		lines := strings.Split(out, "\n")
+		result := icmd.RunCmd(icmd.Cmd{
+			Command: []stirng{dockerBinary, "help"},
+			Env: newEnvs,
+		})
+		result.Assert(c, icmd.Success)
+		lines := strings.Split(result.Combined(), "\n")
 		for _, line := range lines {
 			// All lines should not end with a space
 			c.Assert(line, checker.Not(checker.HasSuffix), " ", check.Commentf("Line should not end with a space"))
@@ -75,16 +77,17 @@ func (s *DockerSuite) TestHelpTextVerify(c *check.C) {
 		// Make sure each cmd's help text fits within 90 chars and that
 		// on non-windows system we use ~ when possible (to shorten things).
 		// Pull the list of commands from the "Commands:" section of docker help
-		helpCmd = exec.Command(dockerBinary, "help")
-		helpCmd.Env = newEnvs
-		out, _, err = runCommandWithOutput(helpCmd)
-		c.Assert(err, checker.IsNil, check.Commentf(out))
-		i := strings.Index(out, "Commands:")
-		c.Assert(i, checker.GreaterOrEqualThan, 0, check.Commentf("Missing 'Commands:' in:\n%s", out))
+		// FIXME(vdemeester) Why re-run help ?
+		//helpCmd = exec.Command(dockerBinary, "help")
+		//helpCmd.Env = newEnvs
+		//out, _, err = runCommandWithOutput(helpCmd)
+		//c.Assert(err, checker.IsNil, check.Commentf(out))
+		i := strings.Index(result.Combined(), "Commands:")
+		c.Assert(i, checker.GreaterOrEqualThan, 0, check.Commentf("Missing 'Commands:' in:\n%s", result.Combined()))
 
 		cmds := []string{}
 		// Grab all chars starting at "Commands:"
-		helpOut := strings.Split(out[i:], "\n")
+		helpOut := strings.Split(result.Combined()[i:], "\n")
 		// Skip first line, it is just "Commands:"
 		helpOut = helpOut[1:]
 

+ 7 - 6
integration-cli/docker_cli_logs_test.go

@@ -8,6 +8,7 @@ import (
 	"strings"
 	"time"
 
+	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/docker/docker/integration-cli/checker"
 	"github.com/docker/docker/pkg/jsonlog"
 	"github.com/docker/docker/pkg/testutil"
@@ -188,14 +189,14 @@ func (s *DockerSuite) TestLogsSince(c *check.C) {
 
 	// Test with default value specified and parameter omitted
 	expected := []string{"log1", "log2", "log3"}
-	for _, cmd := range []*exec.Cmd{
-		exec.Command(dockerBinary, "logs", "-t", name),
-		exec.Command(dockerBinary, "logs", "-t", "--since=0", name),
+	for _, cmd := range [][]string{
+		[]string{dockerBinary, "logs", "-t", name},
+		[]string{dockerBinary, "logs", "-t", "--since=0", name},
 	} {
-		out, _, err = runCommandWithOutput(cmd)
-		c.Assert(err, checker.IsNil, check.Commentf("failed to log container: %s", out))
+		result := icmd.RunCommand(cmd...)
+		result.Assert(c, icmd.Success)
 		for _, v := range expected {
-			c.Assert(out, checker.Contains, v)
+			c.Assert(result.Combined(), checker.Contains, v)
 		}
 	}
 }

+ 2 - 3
integration-cli/docker_cli_network_unix_test.go

@@ -803,15 +803,14 @@ func (s *DockerDaemonSuite) TestDockerNetworkNoDiscoveryDefaultBridgeNetwork(c *
 	hostsFile := "/etc/hosts"
 	bridgeName := "external-bridge"
 	bridgeIP := "192.169.255.254/24"
-	out, err := createInterface(c, "bridge", bridgeName, bridgeIP)
-	c.Assert(err, check.IsNil, check.Commentf(out))
+	createInterface(c, "bridge", bridgeName, bridgeIP)
 	defer deleteInterface(c, bridgeName)
 
 	s.d.StartWithBusybox(c, "--bridge", bridgeName)
 	defer s.d.Restart(c)
 
 	// run two containers and store first container's etc/hosts content
-	out, err = s.d.Cmd("run", "-d", "busybox", "top")
+	out, err := s.d.Cmd("run", "-d", "busybox", "top")
 	c.Assert(err, check.IsNil)
 	cid1 := strings.TrimSpace(out)
 	defer s.d.Cmd("stop", cid1)

+ 15 - 15
integration-cli/docker_cli_proxy_test.go

@@ -5,20 +5,18 @@ import (
 	"os/exec"
 	"strings"
 
+	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/docker/docker/integration-cli/checker"
 	"github.com/go-check/check"
 )
 
 func (s *DockerSuite) TestCLIProxyDisableProxyUnixSock(c *check.C) {
-	testRequires(c, DaemonIsLinux)
-	testRequires(c, SameHostDaemon) // test is valid when DOCKER_HOST=unix://..
-
-	cmd := exec.Command(dockerBinary, "info")
-	cmd.Env = appendBaseEnv(false, "HTTP_PROXY=http://127.0.0.1:9999")
-
-	out, _, err := runCommandWithOutput(cmd)
-	c.Assert(err, checker.IsNil, check.Commentf("%v", out))
+	testRequires(c, DaemonIsLinux, SameHostDaemon)
 
+	icmd.RunCmd(icm.Cmd{
+		Command: []string{dockerBinary, "info"},
+		Env: appendBaseEnv(false, "HTTP_PROXY=http://127.0.0.1:9999"),
+	}).Assert(c, icmd.Success)
 }
 
 // Can't use localhost here since go has a special case to not use proxy if connecting to localhost
@@ -41,12 +39,14 @@ func (s *DockerDaemonSuite) TestCLIProxyProxyTCPSock(c *check.C) {
 	c.Assert(ip, checker.Not(checker.Equals), "")
 
 	s.d.Start(c, "-H", "tcp://"+ip+":2375")
-	cmd := exec.Command(dockerBinary, "info")
-	cmd.Env = []string{"DOCKER_HOST=tcp://" + ip + ":2375", "HTTP_PROXY=127.0.0.1:9999"}
-	out, _, err := runCommandWithOutput(cmd)
-	c.Assert(err, checker.NotNil, check.Commentf("%v", out))
+
+	icmd.RunCmd(icmd.Cmd{
+		Command: []string{dockerBinary, "info"},
+		Env: []string{"DOCKER_HOST=tcp://" + ip + ":2375", "HTTP_PROXY=127.0.0.1:9999"},
+	}).Assert(c, icmd.Expected{Error:"exit status 1", ExitCode: 1})
 	// Test with no_proxy
-	cmd.Env = append(cmd.Env, "NO_PROXY="+ip)
-	out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "info"))
-	c.Assert(err, checker.IsNil, check.Commentf("%v", out))
+	icmd.RunCommand(icmd.Cmd{
+		Command: []string{dockerBinary, "info"},
+		Env: []string{"DOCKER_HOST=tcp://" + ip + ":2375", "HTTP_PROXY=127.0.0.1:9999", "NO_PROXY="+ip},
+	}).Assert(c, icmd.Success)
 }

+ 12 - 20
integration-cli/docker_cli_ps_test.go

@@ -669,22 +669,19 @@ func (s *DockerSuite) TestPsImageIDAfterUpdate(c *check.C) {
 	originalImageName := "busybox:TestPsImageIDAfterUpdate-original"
 	updatedImageName := "busybox:TestPsImageIDAfterUpdate-updated"
 
-	runCmd := exec.Command(dockerBinary, "tag", "busybox:latest", originalImageName)
-	out, _, err := runCommandWithOutput(runCmd)
-	c.Assert(err, checker.IsNil)
+	icmd.RunCommand(dockerBinary, "tag", "busybox:latest", originalImageName).Assert(c, icmd.Success)
 
 	originalImageID, err := getIDByName(originalImageName)
 	c.Assert(err, checker.IsNil)
 
-	runCmd = exec.Command(dockerBinary, append([]string{"run", "-d", originalImageName}, sleepCommandForDaemonPlatform()...)...)
-	out, _, err = runCommandWithOutput(runCmd)
-	c.Assert(err, checker.IsNil)
-	containerID := strings.TrimSpace(out)
+	result := icmd.RunCommand(dockerBinary, append([]string{"run", "-d", originalImageName}, sleepCommandForDaemonPlatform()...)...)
+	result.Assert(c, icmd.Success)
+	containerID := strings.TrimSpace(result.Combined())
 
-	linesOut, err := exec.Command(dockerBinary, "ps", "--no-trunc").CombinedOutput()
-	c.Assert(err, checker.IsNil)
+	result = icmd.RunCommand(dockerBinary, "ps", "--no-trunc")
+	result.Assert(c, icmd.Success)
 
-	lines := strings.Split(strings.TrimSpace(string(linesOut)), "\n")
+	lines := strings.Split(strings.TrimSpace(string(result.Combined())), "\n")
 	// skip header
 	lines = lines[1:]
 	c.Assert(len(lines), checker.Equals, 1)
@@ -694,18 +691,13 @@ func (s *DockerSuite) TestPsImageIDAfterUpdate(c *check.C) {
 		c.Assert(f[1], checker.Equals, originalImageName)
 	}
 
-	runCmd = exec.Command(dockerBinary, "commit", containerID, updatedImageName)
-	out, _, err = runCommandWithOutput(runCmd)
-	c.Assert(err, checker.IsNil)
-
-	runCmd = exec.Command(dockerBinary, "tag", updatedImageName, originalImageName)
-	out, _, err = runCommandWithOutput(runCmd)
-	c.Assert(err, checker.IsNil)
+	icmd.RunCommand(dockerBinary, "commit", containerID, updatedImageName).Assert(c, icmd.Success)
+	icmd.RunCommand(dockerBinary, "tag", updatedImageName, originalImageName).Assert(c, icmd.Success)
 
-	linesOut, err = exec.Command(dockerBinary, "ps", "--no-trunc").CombinedOutput()
-	c.Assert(err, checker.IsNil)
+	result = icmd.RunCommand(dockerBinary, "ps", "--no-trunc")
+	result.Assert(c, icmd.Success)
 
-	lines = strings.Split(strings.TrimSpace(string(linesOut)), "\n")
+	lines = strings.Split(strings.TrimSpace(string(result.Combined())), "\n")
 	// skip header
 	lines = lines[1:]
 	c.Assert(len(lines), checker.Equals, 1)

+ 7 - 6
integration-cli/docker_cli_pull_local_test.go

@@ -12,6 +12,7 @@ import (
 
 	"github.com/docker/distribution"
 	"github.com/docker/distribution/digest"
+	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/docker/distribution/manifest"
 	"github.com/docker/distribution/manifest/manifestlist"
 	"github.com/docker/distribution/manifest/schema2"
@@ -87,8 +88,8 @@ func testConcurrentPullWholeRepo(c *check.C) {
 
 	for i := 0; i != numPulls; i++ {
 		go func() {
-			_, _, err := runCommandWithOutput(exec.Command(dockerBinary, "pull", "-a", repoName))
-			results <- err
+			result := icmd.RunCommand(dockerBinary, "pull", "-a", repoName)
+			results <- result.Error
 		}()
 	}
 
@@ -125,8 +126,8 @@ func testConcurrentFailingPull(c *check.C) {
 
 	for i := 0; i != numPulls; i++ {
 		go func() {
-			_, _, err := runCommandWithOutput(exec.Command(dockerBinary, "pull", repoName+":asdfasdf"))
-			results <- err
+			result := icmd.RunCommand(dockerBinary, "pull", repoName+":asdfasdf")
+			results <- result.Error
 		}()
 	}
 
@@ -175,8 +176,8 @@ func testConcurrentPullMultipleTags(c *check.C) {
 
 	for _, repo := range repos {
 		go func(repo string) {
-			_, _, err := runCommandWithOutput(exec.Command(dockerBinary, "pull", repo))
-			results <- err
+			result := icmd.RunCommand(dockerBinary, "pull", repo)
+			results <- result.Error
 		}(repo)
 	}
 

+ 7 - 6
integration-cli/docker_cli_push_test.go

@@ -14,6 +14,7 @@ import (
 	"time"
 
 	"github.com/docker/distribution/reference"
+	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	cliconfig "github.com/docker/docker/cli/config"
 	"github.com/docker/docker/integration-cli/checker"
 	"github.com/docker/docker/pkg/testutil"
@@ -135,10 +136,10 @@ func testPushEmptyLayer(c *check.C) {
 	c.Assert(err, check.IsNil, check.Commentf("Could not open test tarball"))
 	defer freader.Close()
 
-	importCmd := exec.Command(dockerBinary, "import", "-", repoName)
-	importCmd.Stdin = freader
-	out, _, err := runCommandWithOutput(importCmd)
-	c.Assert(err, check.IsNil, check.Commentf("import failed: %q", out))
+	icmd.RunCmd(icmd.Cmd{
+		Command: []string{dockerBinary, "import", "-", repoName},
+		Stdin: freader,
+	}).Assert(c, icmd.Success)
 
 	// Now verify we can push it
 	out, _, err = dockerCmdWithError("push", repoName)
@@ -177,8 +178,8 @@ func testConcurrentPush(c *check.C) {
 
 	for _, repo := range repos {
 		go func(repo string) {
-			_, _, err := runCommandWithOutput(exec.Command(dockerBinary, "push", repo))
-			results <- err
+			result := icmd.RunCommand(dockerBinary, "push", repo)
+			results <- result.Error
 		}(repo)
 	}
 

+ 5 - 5
integration-cli/docker_cli_rmi_test.go

@@ -6,6 +6,7 @@ import (
 	"strings"
 	"time"
 
+	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/docker/docker/integration-cli/checker"
 	"github.com/docker/docker/pkg/stringid"
 	"github.com/go-check/check"
@@ -175,12 +176,11 @@ func (s *DockerSuite) TestRmiTagWithExistingContainers(c *check.C) {
 func (s *DockerSuite) TestRmiForceWithExistingContainers(c *check.C) {
 	image := "busybox-clone"
 
-	cmd := exec.Command(dockerBinary, "build", "--no-cache", "-t", image, "-")
-	cmd.Stdin = strings.NewReader(`FROM busybox
+	icmd.RunCmd(icmd.Cmd{
+		Command: []string{dockerBinary, "build", "--no-cache", "-t", image, "-"},
+		Stdin: strings.NewReader(`FROM busybox
 MAINTAINER foo`)
-
-	out, _, err := runCommandWithOutput(cmd)
-	c.Assert(err, checker.IsNil, check.Commentf("Could not build %s: %s", image, out))
+	}).Assert(c, icmd.Success)
 
 	dockerCmd(c, "run", "--name", "test-force-rmi", image, "/bin/true")
 

+ 51 - 64
integration-cli/docker_cli_run_test.go

@@ -819,21 +819,21 @@ func (s *DockerSuite) TestRunEnvironment(c *check.C) {
 	// TODO Windows: Environment handling is different between Linux and
 	// Windows and this test relies currently on unix functionality.
 	testRequires(c, DaemonIsLinux)
-	cmd := exec.Command(dockerBinary, "run", "-h", "testing", "-e=FALSE=true", "-e=TRUE", "-e=TRICKY", "-e=HOME=", "busybox", "env")
-	cmd.Env = append(os.Environ(),
-		"TRUE=false",
-		"TRICKY=tri\ncky\n",
-	)
-
-	out, _, err := runCommandWithOutput(cmd)
-	if err != nil {
-		c.Fatal(err, out)
-	}
+	result := icmd.RunCmd(icmd.Cmd{
+		Command: []string{dockerBinary, "run", "-h", "testing", "-e=FALSE=true", "-e=TRUE", "-e=TRICKY", "-e=HOME=", "busybox", "env"},
+		Env: append(os.Environ(),
+			"TRUE=false",
+			"TRICKY=tri\ncky\n",
+		),
+	})
+	result.Assert(c, icmd.Success)
 
-	actualEnv := strings.Split(strings.TrimSpace(out), "\n")
+	actualEnv := strings.Split(strings.TrimSpace(result.Combined()), "\n")
 	sort.Strings(actualEnv)
 
 	goodEnv := []string{
+		// The first two should not be tested here, those are "inherent" environment variable. This test validates
+		// the -e behavior, not the default environment variable (that could be subject to change)
 		"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
 		"HOSTNAME=testing",
 		"FALSE=true",
@@ -863,15 +863,13 @@ func (s *DockerSuite) TestRunEnvironmentErase(c *check.C) {
 	// not set in our local env that they're removed (if present) in
 	// the container
 
-	cmd := exec.Command(dockerBinary, "run", "-e", "FOO", "-e", "HOSTNAME", "busybox", "env")
-	cmd.Env = appendBaseEnv(true)
-
-	out, _, err := runCommandWithOutput(cmd)
-	if err != nil {
-		c.Fatal(err, out)
-	}
+	result := icmd.RunCmd(icmd.Cmd{
+		Command: []string{dockerBinary, "run", "-e", "FOO", "-e", "HOSTNAME", "busybox", "env"},
+		Env: appendBaseEnd(true),
+	})
+	result.Assert(c, icmd.Success)
 
-	actualEnv := strings.Split(strings.TrimSpace(out), "\n")
+	actualEnv := strings.Split(strings.TrimSpace(result.Combined()), "\n")
 	sort.Strings(actualEnv)
 
 	goodEnv := []string{
@@ -897,15 +895,13 @@ func (s *DockerSuite) TestRunEnvironmentOverride(c *check.C) {
 	// Test to make sure that when we use -e on env vars that are
 	// already in the env that we're overriding them
 
-	cmd := exec.Command(dockerBinary, "run", "-e", "HOSTNAME", "-e", "HOME=/root2", "busybox", "env")
-	cmd.Env = appendBaseEnv(true, "HOSTNAME=bar")
-
-	out, _, err := runCommandWithOutput(cmd)
-	if err != nil {
-		c.Fatal(err, out)
-	}
+	result := icmd.RunCmd(icmd.Cmd{
+		Command: []string{dockerBinary, "run", "-e", "HOSTNAME", "-e", "HOME=/root2", "busybox", "env"},
+		Env: appendBaseEnv(true, "HOSTNAME=bar"),
+	})
+	result.Assert(c, icmd.Success)
 
-	actualEnv := strings.Split(strings.TrimSpace(out), "\n")
+	actualEnv := strings.Split(strings.TrimSpace(result.Combined()), "\n")
 	sort.Strings(actualEnv)
 
 	goodEnv := []string{
@@ -2111,12 +2107,9 @@ func (s *DockerSuite) TestRunDeallocatePortOnMissingIptablesRule(c *check.C) {
 
 	id := strings.TrimSpace(out)
 	ip := inspectField(c, id, "NetworkSettings.Networks.bridge.IPAddress")
-	iptCmd := exec.Command("iptables", "-D", "DOCKER", "-d", fmt.Sprintf("%s/32", ip),
-		"!", "-i", "docker0", "-o", "docker0", "-p", "tcp", "-m", "tcp", "--dport", "23", "-j", "ACCEPT")
-	out, _, err := runCommandWithOutput(iptCmd)
-	if err != nil {
-		c.Fatal(err, out)
-	}
+	icmd.RunCommand("iptables", "-D", "DOCKER", "-d", fmt.Sprintf("%s/32", ip),
+		"!", "-i", "docker0", "-o", "docker0", "-p", "tcp", "-m", "tcp", "--dport", "23", "-j", "ACCEPT").Assert(c, icmd.Success)
+
 	if err := deleteContainer(false, id); err != nil {
 		c.Fatal(err)
 	}
@@ -4012,23 +4005,19 @@ func (s *DockerSuite) TestRunWrongCpusetMemsFlagValue(c *check.C) {
 // TestRunNonExecutableCmd checks that 'docker run busybox foo' exits with error code 127'
 func (s *DockerSuite) TestRunNonExecutableCmd(c *check.C) {
 	name := "testNonExecutableCmd"
-	runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "foo")
-	_, exit, _ := runCommandWithOutput(runCmd)
-	stateExitCode := findContainerExitCode(c, name)
-	if !(exit == 127 && strings.Contains(stateExitCode, "127")) {
-		c.Fatalf("Run non-executable command should have errored with exit code 127, but we got exit: %d, State.ExitCode: %s", exit, stateExitCode)
-	}
+	icmd.RunCommand(dockerBinary, "run", "--name", name, "busybox", "foo").Assert(c, icmd.Expected{
+		ExitCode: 127,
+		Error: "exit status 127",
+	})
 }
 
 // TestRunNonExistingCmd checks that 'docker run busybox /bin/foo' exits with code 127.
 func (s *DockerSuite) TestRunNonExistingCmd(c *check.C) {
 	name := "testNonExistingCmd"
-	runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "/bin/foo")
-	_, exit, _ := runCommandWithOutput(runCmd)
-	stateExitCode := findContainerExitCode(c, name)
-	if !(exit == 127 && strings.Contains(stateExitCode, "127")) {
-		c.Fatalf("Run non-existing command should have errored with exit code 127, but we got exit: %d, State.ExitCode: %s", exit, stateExitCode)
-	}
+	icmd.RunCommand(dockerBinary, "run", "--name", name, "busybox", "/bin/foo").Assert(c, icmd.Expected{
+		ExitCode: 127,
+		Error: "exit status 127",
+	})
 }
 
 // TestCmdCannotBeInvoked checks that 'docker run busybox /etc' exits with 126, or
@@ -4040,30 +4029,28 @@ func (s *DockerSuite) TestCmdCannotBeInvoked(c *check.C) {
 		expected = 127
 	}
 	name := "testCmdCannotBeInvoked"
-	runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "/etc")
-	_, exit, _ := runCommandWithOutput(runCmd)
-	stateExitCode := findContainerExitCode(c, name)
-	if !(exit == expected && strings.Contains(stateExitCode, strconv.Itoa(expected))) {
-		c.Fatalf("Run cmd that cannot be invoked should have errored with code %d, but we got exit: %d, State.ExitCode: %s", expected, exit, stateExitCode)
-	}
+	icmd.RunCommand(dockerBinary, "run", "--name", name, "busybox", "/etc").Assert(c, icmd.Expected{
+		ExitCode: expected,
+		Error: fmt.Sprintf("exit status %d", expected),
+	})
 }
 
 // TestRunNonExistingImage checks that 'docker run foo' exits with error msg 125 and contains  'Unable to find image'
+// FIXME(vdemeester) should be a unit test
 func (s *DockerSuite) TestRunNonExistingImage(c *check.C) {
-	runCmd := exec.Command(dockerBinary, "run", "foo")
-	out, exit, err := runCommandWithOutput(runCmd)
-	if !(err != nil && exit == 125 && strings.Contains(out, "Unable to find image")) {
-		c.Fatalf("Run non-existing image should have errored with 'Unable to find image' code 125, but we got out: %s, exit: %d, err: %s", out, exit, err)
-	}
+	icmd.RunCommand(dockerBinary, "run", "foo").Assert(c, icmd.Expected{
+		ExitCode: 125,
+		Err: "Unable to find image",
+	})
 }
 
 // TestDockerFails checks that 'docker run -foo busybox' exits with 125 to signal docker run failed
+// FIXME(vdemeester) should be a unit test
 func (s *DockerSuite) TestDockerFails(c *check.C) {
-	runCmd := exec.Command(dockerBinary, "run", "-foo", "busybox")
-	out, exit, err := runCommandWithOutput(runCmd)
-	if !(err != nil && exit == 125) {
-		c.Fatalf("Docker run with flag not defined should exit with 125, but we got out: %s, exit: %d, err: %s", out, exit, err)
-	}
+	icmd.RunCommand(dockerBinary, "run", "-foo", "busybox").Assert(c, icmd.Expected{
+		ExitCode: 125,
+		Error: "exit status 125",
+	})
 }
 
 // TestRunInvalidReference invokes docker run with a bad reference.
@@ -4490,9 +4477,9 @@ func (s *DockerSuite) TestRunServicingContainer(c *check.C) {
 	err := waitExited(containerID, 60*time.Second)
 	c.Assert(err, checker.IsNil)
 
-	cmd := exec.Command("powershell", "echo", `(Get-WinEvent -ProviderName "Microsoft-Windows-Hyper-V-Compute" -FilterXPath 'Event[System[EventID=2010]]' -MaxEvents 1).Message`)
-	out2, _, err := runCommandWithOutput(cmd)
-	c.Assert(err, checker.IsNil)
+	result := icmd.RunCommand("powershell", "echo", `(Get-WinEvent -ProviderName "Microsoft-Windows-Hyper-V-Compute" -FilterXPath 'Event[System[EventID=2010]]' -MaxEvents 1).Message`)
+	result.Assert(c, icmd.Success)
+	out2 := result.Combined()
 	c.Assert(out2, checker.Contains, `"Servicing":true`, check.Commentf("Servicing container does not appear to have been started: %s", out2))
 	c.Assert(out2, checker.Contains, `Windows Container (Servicing)`, check.Commentf("Didn't find 'Windows Container (Servicing): %s", out2))
 	c.Assert(out2, checker.Contains, containerID+"_servicing", check.Commentf("Didn't find '%s_servicing': %s", containerID+"_servicing", out2))

+ 122 - 144
integration-cli/docker_cli_run_unix_test.go

@@ -21,6 +21,7 @@ import (
 	"github.com/docker/docker/pkg/mount"
 	"github.com/docker/docker/pkg/parsers"
 	"github.com/docker/docker/pkg/sysinfo"
+	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/go-check/check"
 	"github.com/kr/pty"
 )
@@ -884,7 +885,6 @@ func (s *DockerSuite) TestRunTmpfsMountsWithOptions(c *check.C) {
 }
 
 func (s *DockerSuite) TestRunSysctls(c *check.C) {
-
 	testRequires(c, DaemonIsLinux)
 	var err error
 
@@ -907,11 +907,11 @@ func (s *DockerSuite) TestRunSysctls(c *check.C) {
 	c.Assert(err, check.IsNil)
 	c.Assert(sysctls["net.ipv4.ip_forward"], check.Equals, "0")
 
-	runCmd := exec.Command(dockerBinary, "run", "--sysctl", "kernel.foobar=1", "--name", "test2", "busybox", "cat", "/proc/sys/kernel/foobar")
-	out, _, _ = runCommandWithOutput(runCmd)
-	if !strings.Contains(out, "invalid argument") {
-		c.Fatalf("expected --sysctl to fail, got %s", out)
-	}
+	icmd.RunCommand(dockerBinary, "run", "--sysctl", "kernel.foobar=1", "--name", "test2",
+		"busybox", "cat", "/proc/sys/kernel/foobar").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Err:      "invalid argument",
+	})
 }
 
 // TestRunSeccompProfileDenyUnshare checks that 'docker run --security-opt seccomp=/tmp/profile.json debian:jessie unshare' exits with operation not permitted.
@@ -935,11 +935,12 @@ func (s *DockerSuite) TestRunSeccompProfileDenyUnshare(c *check.C) {
 	if _, err := tmpFile.Write([]byte(jsonData)); err != nil {
 		c.Fatal(err)
 	}
-	runCmd := exec.Command(dockerBinary, "run", "--security-opt", "apparmor=unconfined", "--security-opt", "seccomp="+tmpFile.Name(), "debian:jessie", "unshare", "-p", "-m", "-f", "-r", "mount", "-t", "proc", "none", "/proc")
-	out, _, _ := runCommandWithOutput(runCmd)
-	if !strings.Contains(out, "Operation not permitted") {
-		c.Fatalf("expected unshare with seccomp profile denied to fail, got %s", out)
-	}
+	icmd.RunCommand(dockerBinary, "run", "--security-opt", "apparmor=unconfined",
+		"--security-opt", "seccomp="+tmpFile.Name(),
+		"debian:jessie", "unshare", "-p", "-m", "-f", "-r", "mount", "-t", "proc", "none", "/proc").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Err: "Operation not permitted",
+	})
 }
 
 // TestRunSeccompProfileDenyChmod checks that 'docker run --security-opt seccomp=/tmp/profile.json busybox chmod 400 /etc/hostname' exits with operation not permitted.
@@ -969,11 +970,11 @@ func (s *DockerSuite) TestRunSeccompProfileDenyChmod(c *check.C) {
 	if _, err := tmpFile.Write([]byte(jsonData)); err != nil {
 		c.Fatal(err)
 	}
-	runCmd := exec.Command(dockerBinary, "run", "--security-opt", "seccomp="+tmpFile.Name(), "busybox", "chmod", "400", "/etc/hostname")
-	out, _, _ := runCommandWithOutput(runCmd)
-	if !strings.Contains(out, "Operation not permitted") {
-		c.Fatalf("expected chmod with seccomp profile denied to fail, got %s", out)
-	}
+	icmd.RunCommand(dockerBinary, "run", "--security-opt", "seccomp="+tmpFile.Name(),
+		"busybox", "chmod", "400", "/etc/hostname").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Err: "Operation not permitted",
+	})
 }
 
 // TestRunSeccompProfileDenyUnshareUserns checks that 'docker run debian:jessie unshare --map-root-user --user sh -c whoami' with a specific profile to
@@ -1006,11 +1007,12 @@ func (s *DockerSuite) TestRunSeccompProfileDenyUnshareUserns(c *check.C) {
 	if _, err := tmpFile.Write([]byte(jsonData)); err != nil {
 		c.Fatal(err)
 	}
-	runCmd := exec.Command(dockerBinary, "run", "--security-opt", "apparmor=unconfined", "--security-opt", "seccomp="+tmpFile.Name(), "debian:jessie", "unshare", "--map-root-user", "--user", "sh", "-c", "whoami")
-	out, _, _ := runCommandWithOutput(runCmd)
-	if !strings.Contains(out, "Operation not permitted") {
-		c.Fatalf("expected unshare userns with seccomp profile denied to fail, got %s", out)
-	}
+	icmd.RunCommand(dockerBinary, "run",
+		"--security-opt", "apparmor=unconfined", "--security-opt", "seccomp="+tmpFile.Name(),
+		"debian:jessie", "unshare", "--map-root-user", "--user", "sh", "-c", "whoami").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Err: "Operation not permitted",
+	})
 }
 
 // TestRunSeccompProfileDenyCloneUserns checks that 'docker run syscall-test'
@@ -1019,11 +1021,10 @@ func (s *DockerSuite) TestRunSeccompProfileDenyCloneUserns(c *check.C) {
 	testRequires(c, SameHostDaemon, seccompEnabled)
 	ensureSyscallTest(c)
 
-	runCmd := exec.Command(dockerBinary, "run", "syscall-test", "userns-test", "id")
-	out, _, err := runCommandWithOutput(runCmd)
-	if err == nil || !strings.Contains(out, "clone failed: Operation not permitted") {
-		c.Fatalf("expected clone userns with default seccomp profile denied to fail, got %s: %v", out, err)
-	}
+	icmd.RunCommand(dockerBinary, "run", "syscall-test", "userns-test", "id").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Err: "clone failed: Operation not permitted",
+	})
 }
 
 // TestRunSeccompUnconfinedCloneUserns checks that
@@ -1033,10 +1034,10 @@ func (s *DockerSuite) TestRunSeccompUnconfinedCloneUserns(c *check.C) {
 	ensureSyscallTest(c)
 
 	// make sure running w privileged is ok
-	runCmd := exec.Command(dockerBinary, "run", "--security-opt", "seccomp=unconfined", "syscall-test", "userns-test", "id")
-	if out, _, err := runCommandWithOutput(runCmd); err != nil || !strings.Contains(out, "nobody") {
-		c.Fatalf("expected clone userns with --security-opt seccomp=unconfined to succeed, got %s: %v", out, err)
-	}
+	icmd.RunCommand(dockerBinary, "run", "--security-opt", "seccomp=unconfined",
+		"syscall-test", "userns-test", "id").Assert(c, icmd.Expected{
+		Out: "nobody",
+	})
 }
 
 // TestRunSeccompAllowPrivCloneUserns checks that 'docker run --privileged syscall-test'
@@ -1046,10 +1047,9 @@ func (s *DockerSuite) TestRunSeccompAllowPrivCloneUserns(c *check.C) {
 	ensureSyscallTest(c)
 
 	// make sure running w privileged is ok
-	runCmd := exec.Command(dockerBinary, "run", "--privileged", "syscall-test", "userns-test", "id")
-	if out, _, err := runCommandWithOutput(runCmd); err != nil || !strings.Contains(out, "nobody") {
-		c.Fatalf("expected clone userns with --privileged to succeed, got %s: %v", out, err)
-	}
+	icmd.RunCommand(dockerBinary, "run", "--privileged", "syscall-test", "userns-test", "id").Assert(c, icmd.Expected{
+		Out: "nobody",
+	})
 }
 
 // TestRunSeccompProfileAllow32Bit checks that 32 bit code can run on x86_64
@@ -1058,10 +1058,7 @@ func (s *DockerSuite) TestRunSeccompProfileAllow32Bit(c *check.C) {
 	testRequires(c, SameHostDaemon, seccompEnabled, IsAmd64)
 	ensureSyscallTest(c)
 
-	runCmd := exec.Command(dockerBinary, "run", "syscall-test", "exit32-test", "id")
-	if out, _, err := runCommandWithOutput(runCmd); err != nil {
-		c.Fatalf("expected to be able to run 32 bit code, got %s: %v", out, err)
-	}
+	icmd.RunCommand(dockerBinary, "run", "syscall-test", "exit32-test", "id").Assert(c, icmd.Success)
 }
 
 // TestRunSeccompAllowSetrlimit checks that 'docker run debian:jessie ulimit -v 1048510' succeeds.
@@ -1069,10 +1066,7 @@ func (s *DockerSuite) TestRunSeccompAllowSetrlimit(c *check.C) {
 	testRequires(c, SameHostDaemon, seccompEnabled)
 
 	// ulimit uses setrlimit, so we want to make sure we don't break it
-	runCmd := exec.Command(dockerBinary, "run", "debian:jessie", "bash", "-c", "ulimit -v 1048510")
-	if out, _, err := runCommandWithOutput(runCmd); err != nil {
-		c.Fatalf("expected ulimit with seccomp to succeed, got %s: %v", out, err)
-	}
+	icmd.RunCommand(dockerBinary, "run", "debian:jessie", "bash", "-c", "ulimit -v 1048510").Assert(c, icmd.Success)
 }
 
 func (s *DockerSuite) TestRunSeccompDefaultProfileAcct(c *check.C) {
@@ -1147,10 +1141,10 @@ func (s *DockerSuite) TestRunNoNewPrivSetuid(c *check.C) {
 	ensureNNPTest(c)
 
 	// test that running a setuid binary results in no effective uid transition
-	runCmd := exec.Command(dockerBinary, "run", "--security-opt", "no-new-privileges", "--user", "1000", "nnp-test", "/usr/bin/nnp-test")
-	if out, _, err := runCommandWithOutput(runCmd); err != nil || !strings.Contains(out, "EUID=1000") {
-		c.Fatalf("expected output to contain EUID=1000, got %s: %v", out, err)
-	}
+	icmd.RunCommand(dockerBinary, "run", "--security-opt", "no-new-privileges", "--user", "1000",
+		"nnp-test", "/usr/bin/nnp-test").Assert(c, icmd.Expected{
+		Out: "EUID=1000",
+	})
 }
 
 func (s *DockerSuite) TestUserNoEffectiveCapabilitiesChown(c *check.C) {
@@ -1158,19 +1152,17 @@ func (s *DockerSuite) TestUserNoEffectiveCapabilitiesChown(c *check.C) {
 	ensureSyscallTest(c)
 
 	// test that a root user has default capability CAP_CHOWN
-	runCmd := exec.Command(dockerBinary, "run", "busybox", "chown", "100", "/tmp")
-	_, _, err := runCommandWithOutput(runCmd)
-	c.Assert(err, check.IsNil)
+	dockerCmd("run", "busybox", "chown", "100", "/tmp")
 	// test that non root user does not have default capability CAP_CHOWN
-	runCmd = exec.Command(dockerBinary, "run", "--user", "1000:1000", "busybox", "chown", "100", "/tmp")
-	out, _, err := runCommandWithOutput(runCmd)
-	c.Assert(err, checker.NotNil, check.Commentf(out))
-	c.Assert(out, checker.Contains, "Operation not permitted")
+	icmd.RunCommand(dockerBinary, "run", "--user", "1000:1000", "busybox", "chown", "100", "/tmp").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Err: "Operation not permitted",
+	})
 	// test that root user can drop default capability CAP_CHOWN
-	runCmd = exec.Command(dockerBinary, "run", "--cap-drop", "chown", "busybox", "chown", "100", "/tmp")
-	out, _, err = runCommandWithOutput(runCmd)
-	c.Assert(err, checker.NotNil, check.Commentf(out))
-	c.Assert(out, checker.Contains, "Operation not permitted")
+	icmd.RunCommand(dockerBinary, "run", "--cap-drop", "chown", "busybox", "chown", "100", "/tmp").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Err: "Operation not permitted",
+	})
 }
 
 func (s *DockerSuite) TestUserNoEffectiveCapabilitiesDacOverride(c *check.C) {
@@ -1178,15 +1170,12 @@ func (s *DockerSuite) TestUserNoEffectiveCapabilitiesDacOverride(c *check.C) {
 	ensureSyscallTest(c)
 
 	// test that a root user has default capability CAP_DAC_OVERRIDE
-	runCmd := exec.Command(dockerBinary, "run", "busybox", "sh", "-c", "echo test > /etc/passwd")
-	_, _, err := runCommandWithOutput(runCmd)
-	c.Assert(err, check.IsNil)
+	dockerCmd("run", "busybox", "sh", "-c", "echo test > /etc/passwd")
 	// test that non root user does not have default capability CAP_DAC_OVERRIDE
-	runCmd = exec.Command(dockerBinary, "run", "--user", "1000:1000", "busybox", "sh", "-c", "echo test > /etc/passwd")
-	out, _, err := runCommandWithOutput(runCmd)
-	c.Assert(err, checker.NotNil, check.Commentf(out))
-	c.Assert(out, checker.Contains, "Permission denied")
-	// TODO test that root user can drop default capability CAP_DAC_OVERRIDE
+	icmd.RunCommand(dockerBinary, "run", "--user", "1000:1000", "busybox", "sh", "-c", "echo test > /etc/passwd").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Err: "Permission denied",
+	})
 }
 
 func (s *DockerSuite) TestUserNoEffectiveCapabilitiesFowner(c *check.C) {
@@ -1194,14 +1183,12 @@ func (s *DockerSuite) TestUserNoEffectiveCapabilitiesFowner(c *check.C) {
 	ensureSyscallTest(c)
 
 	// test that a root user has default capability CAP_FOWNER
-	runCmd := exec.Command(dockerBinary, "run", "busybox", "chmod", "777", "/etc/passwd")
-	_, _, err := runCommandWithOutput(runCmd)
-	c.Assert(err, check.IsNil)
+	dockerCmd("run", "busybox", "chmod", "777", "/etc/passwd")
 	// test that non root user does not have default capability CAP_FOWNER
-	runCmd = exec.Command(dockerBinary, "run", "--user", "1000:1000", "busybox", "chmod", "777", "/etc/passwd")
-	out, _, err := runCommandWithOutput(runCmd)
-	c.Assert(err, checker.NotNil, check.Commentf(out))
-	c.Assert(out, checker.Contains, "Operation not permitted")
+	icmd.RunCommand(dockerBinary, "run", "--user", "1000:1000", "busybox", "chmod", "777", "/etc/passwd").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Err: "Operation not permitted",
+	})
 	// TODO test that root user can drop default capability CAP_FOWNER
 }
 
@@ -1212,19 +1199,17 @@ func (s *DockerSuite) TestUserNoEffectiveCapabilitiesSetuid(c *check.C) {
 	ensureSyscallTest(c)
 
 	// test that a root user has default capability CAP_SETUID
-	runCmd := exec.Command(dockerBinary, "run", "syscall-test", "setuid-test")
-	_, _, err := runCommandWithOutput(runCmd)
-	c.Assert(err, check.IsNil)
+	dockerCmd("run", "syscall-test", "setuid-test")
 	// test that non root user does not have default capability CAP_SETUID
-	runCmd = exec.Command(dockerBinary, "run", "--user", "1000:1000", "syscall-test", "setuid-test")
-	out, _, err := runCommandWithOutput(runCmd)
-	c.Assert(err, checker.NotNil, check.Commentf(out))
-	c.Assert(out, checker.Contains, "Operation not permitted")
+	icmd.RunCommand(dockerBinary, "run", "--user", "1000:1000", "syscall-test", "setuid-test").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Err: "Operation not permitted",
+	})
 	// test that root user can drop default capability CAP_SETUID
-	runCmd = exec.Command(dockerBinary, "run", "--cap-drop", "setuid", "syscall-test", "setuid-test")
-	out, _, err = runCommandWithOutput(runCmd)
-	c.Assert(err, checker.NotNil, check.Commentf(out))
-	c.Assert(out, checker.Contains, "Operation not permitted")
+	icmd.RunCommand(dockerBinary, "run", "--cap-drop", "setuid", "syscall-test", "setuid-test").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Err: "Operation not permitted",
+	})
 }
 
 func (s *DockerSuite) TestUserNoEffectiveCapabilitiesSetgid(c *check.C) {
@@ -1232,19 +1217,17 @@ func (s *DockerSuite) TestUserNoEffectiveCapabilitiesSetgid(c *check.C) {
 	ensureSyscallTest(c)
 
 	// test that a root user has default capability CAP_SETGID
-	runCmd := exec.Command(dockerBinary, "run", "syscall-test", "setgid-test")
-	_, _, err := runCommandWithOutput(runCmd)
-	c.Assert(err, check.IsNil)
+	dockerCmd("run", "syscall-test", "setgid-test")
 	// test that non root user does not have default capability CAP_SETGID
-	runCmd = exec.Command(dockerBinary, "run", "--user", "1000:1000", "syscall-test", "setgid-test")
-	out, _, err := runCommandWithOutput(runCmd)
-	c.Assert(err, checker.NotNil, check.Commentf(out))
-	c.Assert(out, checker.Contains, "Operation not permitted")
+	icmd.RunCommand(dockerBinary, "run", "--user", "1000:1000", "syscall-test", "setgid-test").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Err: "Operation not permitted",
+	})
 	// test that root user can drop default capability CAP_SETGID
-	runCmd = exec.Command(dockerBinary, "run", "--cap-drop", "setgid", "syscall-test", "setgid-test")
-	out, _, err = runCommandWithOutput(runCmd)
-	c.Assert(err, checker.NotNil, check.Commentf(out))
-	c.Assert(out, checker.Contains, "Operation not permitted")
+	icmd.RunCommand(dockerBinary, "run", "--cap-drop", "setgid", "syscall-test", "setgid-test").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Err: "Operation not permitted",
+	})
 }
 
 // TODO CAP_SETPCAP
@@ -1254,19 +1237,17 @@ func (s *DockerSuite) TestUserNoEffectiveCapabilitiesNetBindService(c *check.C)
 	ensureSyscallTest(c)
 
 	// test that a root user has default capability CAP_NET_BIND_SERVICE
-	runCmd := exec.Command(dockerBinary, "run", "syscall-test", "socket-test")
-	_, _, err := runCommandWithOutput(runCmd)
-	c.Assert(err, check.IsNil)
+	dockerCmd("run", "syscall-test", "socket-test")
 	// test that non root user does not have default capability CAP_NET_BIND_SERVICE
-	runCmd = exec.Command(dockerBinary, "run", "--user", "1000:1000", "syscall-test", "socket-test")
-	out, _, err := runCommandWithOutput(runCmd)
-	c.Assert(err, checker.NotNil, check.Commentf(out))
-	c.Assert(out, checker.Contains, "Permission denied")
+	icmd.RunCommand(dockerBinary, "run", "--user", "1000:1000", "syscall-test", "socket-test").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Err: "Permission denied",
+	})
 	// test that root user can drop default capability CAP_NET_BIND_SERVICE
-	runCmd = exec.Command(dockerBinary, "run", "--cap-drop", "net_bind_service", "syscall-test", "socket-test")
-	out, _, err = runCommandWithOutput(runCmd)
-	c.Assert(err, checker.NotNil, check.Commentf(out))
-	c.Assert(out, checker.Contains, "Permission denied")
+	icmd.RunCommand(dockerBinary, "run", "--cap-drop", "net_bind_service", "syscall-test", "socket-test").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Err: "Permission denied",
+	})
 }
 
 func (s *DockerSuite) TestUserNoEffectiveCapabilitiesNetRaw(c *check.C) {
@@ -1274,19 +1255,17 @@ func (s *DockerSuite) TestUserNoEffectiveCapabilitiesNetRaw(c *check.C) {
 	ensureSyscallTest(c)
 
 	// test that a root user has default capability CAP_NET_RAW
-	runCmd := exec.Command(dockerBinary, "run", "syscall-test", "raw-test")
-	_, _, err := runCommandWithOutput(runCmd)
-	c.Assert(err, check.IsNil)
+	dockerCmd("run", "syscall-test", "raw-test")
 	// test that non root user does not have default capability CAP_NET_RAW
-	runCmd = exec.Command(dockerBinary, "run", "--user", "1000:1000", "syscall-test", "raw-test")
-	out, _, err := runCommandWithOutput(runCmd)
-	c.Assert(err, checker.NotNil, check.Commentf(out))
-	c.Assert(out, checker.Contains, "Operation not permitted")
+	icmd.RunCommand(dockerBinary, "run", "--user", "1000:1000", "syscall-test", "raw-test").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Err: "Operation not permitted",
+	})
 	// test that root user can drop default capability CAP_NET_RAW
-	runCmd = exec.Command(dockerBinary, "run", "--cap-drop", "net_raw", "syscall-test", "raw-test")
-	out, _, err = runCommandWithOutput(runCmd)
-	c.Assert(err, checker.NotNil, check.Commentf(out))
-	c.Assert(out, checker.Contains, "Operation not permitted")
+	icmd.RunCommand(dockerBinary, "run", "--cap-drop", "net_raw", "syscall-test", "raw-test").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Err: "Operation not permitted",
+	})
 }
 
 func (s *DockerSuite) TestUserNoEffectiveCapabilitiesChroot(c *check.C) {
@@ -1294,19 +1273,17 @@ func (s *DockerSuite) TestUserNoEffectiveCapabilitiesChroot(c *check.C) {
 	ensureSyscallTest(c)
 
 	// test that a root user has default capability CAP_SYS_CHROOT
-	runCmd := exec.Command(dockerBinary, "run", "busybox", "chroot", "/", "/bin/true")
-	_, _, err := runCommandWithOutput(runCmd)
-	c.Assert(err, check.IsNil)
+	dockerCmd("run", "busybox", "chroot", "/", "/bin/true")
 	// test that non root user does not have default capability CAP_SYS_CHROOT
-	runCmd = exec.Command(dockerBinary, "run", "--user", "1000:1000", "busybox", "chroot", "/", "/bin/true")
-	out, _, err := runCommandWithOutput(runCmd)
-	c.Assert(err, checker.NotNil, check.Commentf(out))
-	c.Assert(out, checker.Contains, "Operation not permitted")
+	icmd.RunCommand(dockerBinary, "run", "--user", "1000:1000", "busybox", "chroot", "/", "/bin/true").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Err: "Operation not permitted",
+	})
 	// test that root user can drop default capability CAP_SYS_CHROOT
-	runCmd = exec.Command(dockerBinary, "run", "--cap-drop", "sys_chroot", "busybox", "chroot", "/", "/bin/true")
-	out, _, err = runCommandWithOutput(runCmd)
-	c.Assert(err, checker.NotNil, check.Commentf(out))
-	c.Assert(out, checker.Contains, "Operation not permitted")
+	icmd.RunCommand(dockerBinary, "run", "--cap-drop", "sys_chroot", "busybox", "chroot", "/", "/bin/true").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Err: "Operation not permitted",
+	})
 }
 
 func (s *DockerSuite) TestUserNoEffectiveCapabilitiesMknod(c *check.C) {
@@ -1314,19 +1291,18 @@ func (s *DockerSuite) TestUserNoEffectiveCapabilitiesMknod(c *check.C) {
 	ensureSyscallTest(c)
 
 	// test that a root user has default capability CAP_MKNOD
-	runCmd := exec.Command(dockerBinary, "run", "busybox", "mknod", "/tmp/node", "b", "1", "2")
-	_, _, err := runCommandWithOutput(runCmd)
-	c.Assert(err, check.IsNil)
+	dockerCmd("run", "busybox", "mknod", "/tmp/node", "b", "1", "2")
 	// test that non root user does not have default capability CAP_MKNOD
-	runCmd = exec.Command(dockerBinary, "run", "--user", "1000:1000", "busybox", "mknod", "/tmp/node", "b", "1", "2")
-	out, _, err := runCommandWithOutput(runCmd)
-	c.Assert(err, checker.NotNil, check.Commentf(out))
-	c.Assert(out, checker.Contains, "Operation not permitted")
+	// test that root user can drop default capability CAP_SYS_CHROOT
+	icmd.RunCommand(dockerBinary, "run", "--user", "1000:1000", "busybox", "mknod", "/tmp/node", "b", "1", "2").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Err: "Operation not permitted",
+	})
 	// test that root user can drop default capability CAP_MKNOD
-	runCmd = exec.Command(dockerBinary, "run", "--cap-drop", "mknod", "busybox", "mknod", "/tmp/node", "b", "1", "2")
-	out, _, err = runCommandWithOutput(runCmd)
-	c.Assert(err, checker.NotNil, check.Commentf(out))
-	c.Assert(out, checker.Contains, "Operation not permitted")
+	icmd.RunCommand(dockerBinary, "run", "--cap-drop", "mknod", "busybox", "mknod", "/tmp/node", "b", "1", "2").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Err: "Operation not permitted",
+	})
 }
 
 // TODO CAP_AUDIT_WRITE
@@ -1336,14 +1312,16 @@ func (s *DockerSuite) TestRunApparmorProcDirectory(c *check.C) {
 	testRequires(c, SameHostDaemon, Apparmor)
 
 	// running w seccomp unconfined tests the apparmor profile
-	runCmd := exec.Command(dockerBinary, "run", "--security-opt", "seccomp=unconfined", "busybox", "chmod", "777", "/proc/1/cgroup")
-	if out, _, err := runCommandWithOutput(runCmd); err == nil || !(strings.Contains(out, "Permission denied") || strings.Contains(out, "Operation not permitted")) {
-		c.Fatalf("expected chmod 777 /proc/1/cgroup to fail, got %s: %v", out, err)
+	result := icmd.RunCommand(dockerBinary, "run", "--security-opt", "seccomp=unconfined", "busybox", "chmod", "777", "/proc/1/cgroup")
+	result.Assert(c, icmd.Expected{ExitCode: 1})
+	if !(strings.Contains(result.Combined(), "Permission denied") || strings.Contains(result.Combined(), "Operation not permitted")) {
+		c.Fatalf("expected chmod 777 /proc/1/cgroup to fail, got %s: %v", result.Combined(), err)
 	}
 
-	runCmd = exec.Command(dockerBinary, "run", "--security-opt", "seccomp=unconfined", "busybox", "chmod", "777", "/proc/1/attr/current")
-	if out, _, err := runCommandWithOutput(runCmd); err == nil || !(strings.Contains(out, "Permission denied") || strings.Contains(out, "Operation not permitted")) {
-		c.Fatalf("expected chmod 777 /proc/1/attr/current to fail, got %s: %v", out, err)
+	result = icmd.RunCommand(dockerBinary, "run", "--security-opt", "seccomp=unconfined", "busybox", "chmod", "777", "/proc/1/attr/current")
+	result.Assert(c, icmd.Expected{ExitCode: 1})
+	if !(strings.Contains(result.Combined(), "Permission denied") || strings.Contains(result.Combined(), "Operation not permitted")) {
+		c.Fatalf("expected chmod 777 /proc/1/attr/current to fail, got %s: %v", result.Combined(), err)
 	}
 }
 

+ 6 - 7
integration-cli/docker_cli_volume_test.go

@@ -226,11 +226,11 @@ func (s *DockerSuite) TestVolumeCLIRm(c *check.C) {
 
 	volumeID := "testing"
 	dockerCmd(c, "run", "-v", volumeID+":"+prefix+"/foo", "--name=test", "busybox", "sh", "-c", "echo hello > /foo/bar")
-	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "volume", "rm", "testing"))
-	c.Assert(
-		err,
-		check.Not(check.IsNil),
-		check.Commentf("Should not be able to remove volume that is in use by a container\n%s", out))
+
+	icmd.RunCommand(dockerBinary, "volume", "rm", "testing").Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Error: "exit status 1",
+	})
 
 	out, _ = dockerCmd(c, "run", "--volumes-from=test", "--name=test2", "busybox", "sh", "-c", "cat /foo/bar")
 	c.Assert(strings.TrimSpace(out), check.Equals, "hello")
@@ -401,8 +401,7 @@ func (s *DockerSuite) TestVolumeCLIRmForce(c *check.C) {
 	c.Assert(strings.TrimSpace(out), checker.Not(checker.Equals), "")
 	// Mountpoint is in the form of "/var/lib/docker/volumes/.../_data", removing `/_data`
 	path := strings.TrimSuffix(strings.TrimSpace(out), "/_data")
-	out, _, err := runCommandWithOutput(exec.Command("rm", "-rf", path))
-	c.Assert(err, check.IsNil)
+	icmd.RunCommand("rm", "-rf", path).Assert(c, icmd.Success)
 
 	dockerCmd(c, "volume", "rm", "-f", "test")
 	out, _ = dockerCmd(c, "volume", "ls")

+ 2 - 1
integration-cli/docker_cli_wait_test.go

@@ -6,6 +6,7 @@ import (
 	"strings"
 	"time"
 
+	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/docker/docker/integration-cli/checker"
 	"github.com/go-check/check"
 )
@@ -36,7 +37,7 @@ func (s *DockerSuite) TestWaitBlockedExitZero(c *check.C) {
 	chWait := make(chan string)
 	go func() {
 		chWait <- ""
-		out, _, _ := runCommandWithOutput(exec.Command(dockerBinary, "wait", containerID))
+		out := icmd.RunCommand(dockerBinary, "wait", containerID).Combined()
 		chWait <- out
 	}()
 

+ 26 - 71
integration-cli/docker_experimental_network_test.go

@@ -3,7 +3,6 @@
 package main
 
 import (
-	"os/exec"
 	"strings"
 	"time"
 
@@ -48,8 +47,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkMacvlanPersistance(c *check.C) {
 	// master dummy interface 'dm' abbreviation represents 'docker macvlan'
 	master := "dm-dummy0"
 	// simulate the master link the vlan tagged subinterface parent link will use
-	out, err := createMasterDummy(c, master)
-	c.Assert(err, check.IsNil, check.Commentf(out))
+	createMasterDummy(c, master)
 	// create a network specifying the desired sub-interface name
 	dockerCmd(c, "network", "create", "--driver=macvlan", "-o", "parent=dm-dummy0.60", "dm-persist")
 	assertNwIsAvailable(c, "dm-persist")
@@ -67,8 +65,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanPersistance(c *check.C) {
 	// master dummy interface 'di' notation represent 'docker ipvlan'
 	master := "di-dummy0"
 	// simulate the master link the vlan tagged subinterface parent link will use
-	out, err := createMasterDummy(c, master)
-	c.Assert(err, check.IsNil, check.Commentf(out))
+	createMasterDummy(c, master)
 	// create a network specifying the desired sub-interface name
 	dockerCmd(c, "network", "create", "--driver=ipvlan", "-o", "parent=di-dummy0.70", "di-persist")
 	assertNwIsAvailable(c, "di-persist")
@@ -86,8 +83,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkMacvlanSubIntCreate(c *check.C) {
 	// master dummy interface 'dm' abbreviation represents 'docker macvlan'
 	master := "dm-dummy0"
 	// simulate the master link the vlan tagged subinterface parent link will use
-	out, err := createMasterDummy(c, master)
-	c.Assert(err, check.IsNil, check.Commentf(out))
+	createMasterDummy(c, master)
 	// create a network specifying the desired sub-interface name
 	dockerCmd(c, "network", "create", "--driver=macvlan", "-o", "parent=dm-dummy0.50", "dm-subinterface")
 	assertNwIsAvailable(c, "dm-subinterface")
@@ -101,8 +97,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanSubIntCreate(c *check.C) {
 	// master dummy interface 'dm' abbreviation represents 'docker ipvlan'
 	master := "di-dummy0"
 	// simulate the master link the vlan tagged subinterface parent link will use
-	out, err := createMasterDummy(c, master)
-	c.Assert(err, check.IsNil, check.Commentf(out))
+	createMasterDummy(c, master)
 	// create a network specifying the desired sub-interface name
 	dockerCmd(c, "network", "create", "--driver=ipvlan", "-o", "parent=di-dummy0.60", "di-subinterface")
 	assertNwIsAvailable(c, "di-subinterface")
@@ -115,17 +110,15 @@ func (s *DockerNetworkSuite) TestDockerNetworkMacvlanOverlapParent(c *check.C) {
 	testRequires(c, DaemonIsLinux, macvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 	// master dummy interface 'dm' abbreviation represents 'docker macvlan'
 	master := "dm-dummy0"
-	out, err := createMasterDummy(c, master)
-	c.Assert(err, check.IsNil, check.Commentf(out))
-	out, err = createVlanInterface(c, master, "dm-dummy0.40", "40")
-	c.Assert(err, check.IsNil, check.Commentf(out))
+	createMasterDummy(c, master)
+	createVlanInterface(c, master, "dm-dummy0.40", "40")
 	// create a network using an existing parent interface
 	dockerCmd(c, "network", "create", "--driver=macvlan", "-o", "parent=dm-dummy0.40", "dm-subinterface")
 	assertNwIsAvailable(c, "dm-subinterface")
 	// attempt to create another network using the same parent iface that should fail
-	out, _, err = dockerCmdWithError("network", "create", "--driver=macvlan", "-o", "parent=dm-dummy0.40", "dm-parent-net-overlap")
+	out, _, err := dockerCmdWithError("network", "create", "--driver=macvlan", "-o", "parent=dm-dummy0.40", "dm-parent-net-overlap")
 	// verify that the overlap returns an error
-	c.Assert(err, check.NotNil)
+	c.Assert(err, check.NotNil, check.Commentf(out))
 	// cleanup the master interface which also collects the slave dev
 	deleteInterface(c, "dm-dummy0")
 }
@@ -135,17 +128,15 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanOverlapParent(c *check.C) {
 	testRequires(c, DaemonIsLinux, ipvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 	// master dummy interface 'dm' abbreviation represents 'docker ipvlan'
 	master := "di-dummy0"
-	out, err := createMasterDummy(c, master)
-	c.Assert(err, check.IsNil, check.Commentf(out))
-	out, err = createVlanInterface(c, master, "di-dummy0.30", "30")
-	c.Assert(err, check.IsNil, check.Commentf(out))
+	createMasterDummy(c, master)
+	createVlanInterface(c, master, "di-dummy0.30", "30")
 	// create a network using an existing parent interface
 	dockerCmd(c, "network", "create", "--driver=ipvlan", "-o", "parent=di-dummy0.30", "di-subinterface")
 	assertNwIsAvailable(c, "di-subinterface")
 	// attempt to create another network using the same parent iface that should fail
-	out, _, err = dockerCmdWithError("network", "create", "--driver=ipvlan", "-o", "parent=di-dummy0.30", "di-parent-net-overlap")
+	out, _, err := dockerCmdWithError("network", "create", "--driver=ipvlan", "-o", "parent=di-dummy0.30", "di-parent-net-overlap")
 	// verify that the overlap returns an error
-	c.Assert(err, check.NotNil)
+	c.Assert(err, check.NotNil, check.Commentf(out))
 	// cleanup the master interface which also collects the slave dev
 	deleteInterface(c, "di-dummy0")
 }
@@ -488,9 +479,8 @@ func (s *DockerSuite) TestDockerNetworkMacVlanExistingParent(c *check.C) {
 	// macvlan bridge mode - empty parent interface containers can reach each other internally but not externally
 	testRequires(c, DaemonIsLinux, macvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 	netName := "dm-parent-exists"
-	out, err := createMasterDummy(c, "dm-dummy0")
+	createMasterDummy(c, "dm-dummy0")
 	//out, err := createVlanInterface(c, "dm-parent", "dm-slave", "macvlan", "bridge")
-	c.Assert(err, check.IsNil, check.Commentf(out))
 	// create a network using an existing parent interface
 	dockerCmd(c, "network", "create", "--driver=macvlan", "-o", "parent=dm-dummy0", netName)
 	assertNwIsAvailable(c, netName)
@@ -498,20 +488,16 @@ func (s *DockerSuite) TestDockerNetworkMacVlanExistingParent(c *check.C) {
 	dockerCmd(c, "network", "rm", netName)
 	assertNwNotAvailable(c, netName)
 	// verify the network delete did not delete the predefined link
-	out, err = linkExists(c, "dm-dummy0")
-	c.Assert(err, check.IsNil, check.Commentf(out))
+	linkExists(c, "dm-dummy0")
 	deleteInterface(c, "dm-dummy0")
-	c.Assert(err, check.IsNil, check.Commentf(out))
 }
 
 func (s *DockerSuite) TestDockerNetworkMacVlanSubinterface(c *check.C) {
 	// macvlan bridge mode -  empty parent interface containers can reach each other internally but not externally
 	testRequires(c, DaemonIsLinux, macvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 	netName := "dm-subinterface"
-	out, err := createMasterDummy(c, "dm-dummy0")
-	c.Assert(err, check.IsNil, check.Commentf(out))
-	out, err = createVlanInterface(c, "dm-dummy0", "dm-dummy0.20", "20")
-	c.Assert(err, check.IsNil, check.Commentf(out))
+	createMasterDummy(c, "dm-dummy0")
+	createVlanInterface(c, "dm-dummy0", "dm-dummy0.20", "20")
 	// create a network using an existing parent interface
 	dockerCmd(c, "network", "create", "--driver=macvlan", "-o", "parent=dm-dummy0.20", netName)
 	assertNwIsAvailable(c, netName)
@@ -522,7 +508,7 @@ func (s *DockerSuite) TestDockerNetworkMacVlanSubinterface(c *check.C) {
 	dockerCmd(c, "run", "-d", "--net=dm-subinterface", "--name=second", "busybox", "top")
 	c.Assert(waitRun("second"), check.IsNil)
 	// verify containers can communicate
-	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
+	_, _, err := dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
 	c.Assert(err, check.IsNil)
 
 	// remove the containers
@@ -532,56 +518,25 @@ func (s *DockerSuite) TestDockerNetworkMacVlanSubinterface(c *check.C) {
 	dockerCmd(c, "network", "rm", netName)
 	assertNwNotAvailable(c, netName)
 	// verify the network delete did not delete the predefined sub-interface
-	out, err = linkExists(c, "dm-dummy0.20")
-	c.Assert(err, check.IsNil, check.Commentf(out))
+	linkExists(c, "dm-dummy0.20")
 	// delete the parent interface which also collects the slave
 	deleteInterface(c, "dm-dummy0")
-	c.Assert(err, check.IsNil, check.Commentf(out))
 }
 
-func createMasterDummy(c *check.C, master string) (string, error) {
+func createMasterDummy(c *check.C, master string) {
 	// ip link add <dummy_name> type dummy
-	args := []string{"link", "add", master, "type", "dummy"}
-	ipLinkCmd := exec.Command("ip", args...)
-	out, _, err := runCommandWithOutput(ipLinkCmd)
-	if err != nil {
-		return out, err
-	}
-	// ip link set dummy_name up
-	args = []string{"link", "set", master, "up"}
-	ipLinkCmd = exec.Command("ip", args...)
-	out, _, err = runCommandWithOutput(ipLinkCmd)
-	if err != nil {
-		return out, err
-	}
-	return out, err
+	icmd.RunCommand("ip", "link", "add", master, "type", "dummy").Assert(c, icmd.Success)
+	icmd.RunCommand("ip", "link", "set", master, "up").Assert(c, icmd.Success)
 }
 
-func createVlanInterface(c *check.C, master, slave, id string) (string, error) {
+func createVlanInterface(c *check.C, master, slave, id string) {
 	// ip link add link <master> name <master>.<VID> type vlan id <VID>
-	args := []string{"link", "add", "link", master, "name", slave, "type", "vlan", "id", id}
-	ipLinkCmd := exec.Command("ip", args...)
-	out, _, err := runCommandWithOutput(ipLinkCmd)
-	if err != nil {
-		return out, err
-	}
+	icmd.RunCommand("ip", "link", "add", "link", master, "name", slave, "type", "vlan", "id", id).Assert(c, icmd.Success)
 	// ip link set <sub_interface_name> up
-	args = []string{"link", "set", slave, "up"}
-	ipLinkCmd = exec.Command("ip", args...)
-	out, _, err = runCommandWithOutput(ipLinkCmd)
-	if err != nil {
-		return out, err
-	}
-	return out, err
+	icmd.RunCommand("ip", "link", "set", slave, "up").Assert(c, icmd.Success)
 }
 
-func linkExists(c *check.C, master string) (string, error) {
+func linkExists(c *check.C, master string) {
 	// verify the specified link exists, ip link show <link_name>
-	args := []string{"link", "show", master}
-	ipLinkCmd := exec.Command("ip", args...)
-	out, _, err := runCommandWithOutput(ipLinkCmd)
-	if err != nil {
-		return out, err
-	}
-	return out, err
+	icmd.RunCommand("ip", "link", "show", master).Assert(c, icmd.Success)
 }

+ 6 - 4
integration-cli/docker_utils_test.go

@@ -818,10 +818,12 @@ func buildImageFromContextWithOut(name string, ctx *FakeContext, useCache bool,
 	}
 	args = append(args, buildFlags...)
 	args = append(args, ".")
-	buildCmd := exec.Command(dockerBinary, args...)
-	buildCmd.Dir = ctx.Dir
-	out, exitCode, err := runCommandWithOutput(buildCmd)
-	if err != nil || exitCode != 0 {
+	result := icmd.RunCmd(icmd.Cmd{
+		Command: append([]string{dockerBinary}, args...),
+		Dir:     ctx.Dir,
+	})
+	out := result.Combined()
+	if result.Error != nil || result.ExitCode != 0 {
 		return "", "", fmt.Errorf("failed to build the image: %s", out)
 	}
 	id, err := getIDByName(name)