浏览代码

Remove RunCommandPipelineWithOutput

Signed-off-by: Daniel Nephin <dnephin@docker.com>
Daniel Nephin 7 年之前
父节点
当前提交
e885af2a6b

+ 8 - 0
integration-cli/cli/cli.go

@@ -229,3 +229,11 @@ func WithStdout(writer io.Writer) func(*icmd.Cmd) func() {
 		return nil
 	}
 }
+
+// WithStdin sets the standard input reader for the command
+func WithStdin(stdin io.Reader) func(*icmd.Cmd) func() {
+	return func(cmd *icmd.Cmd) func() {
+		cmd.Stdin = stdin
+		return nil
+	}
+}

+ 10 - 15
integration-cli/daemon/daemon.go

@@ -14,18 +14,20 @@ import (
 	"strings"
 	"time"
 
+	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/events"
 	"github.com/docker/docker/integration-cli/checker"
 	"github.com/docker/docker/integration-cli/request"
 	"github.com/docker/docker/opts"
 	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/docker/pkg/stringid"
-	"github.com/docker/docker/pkg/testutil"
 	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/docker/go-connections/sockets"
 	"github.com/docker/go-connections/tlsconfig"
 	"github.com/go-check/check"
 	"github.com/pkg/errors"
+	"github.com/stretchr/testify/require"
+	"golang.org/x/net/context"
 )
 
 type testingT interface {
@@ -570,20 +572,13 @@ func (d *Daemon) WaitRun(contID string) error {
 	return WaitInspectWithArgs(d.dockerBinary, contID, "{{.State.Running}}", "true", 10*time.Second, args...)
 }
 
-// GetBaseDeviceSize returns the base device size of the daemon
-func (d *Daemon) GetBaseDeviceSize(c *check.C) int64 {
-	infoCmdOutput, _, err := testutil.RunCommandPipelineWithOutput(
-		exec.Command(d.dockerBinary, "-H", d.Sock(), "info"),
-		exec.Command("grep", "Base Device Size"),
-	)
-	c.Assert(err, checker.IsNil)
-	basesizeSlice := strings.Split(infoCmdOutput, ":")
-	basesize := strings.Trim(basesizeSlice[1], " ")
-	basesize = strings.Trim(basesize, "\n")[:len(basesize)-3]
-	basesizeFloat, err := strconv.ParseFloat(strings.Trim(basesize, " "), 64)
-	c.Assert(err, checker.IsNil)
-	basesizeBytes := int64(basesizeFloat) * (1024 * 1024 * 1024)
-	return basesizeBytes
+// Info returns the info struct for this daemon
+func (d *Daemon) Info(t require.TestingT) types.Info {
+	apiclient, err := request.NewClientForHost(d.Sock())
+	require.NoError(t, err)
+	info, err := apiclient.Info(context.Background())
+	require.NoError(t, err)
+	return info
 }
 
 // Cmd executes a docker CLI command against this daemon.

+ 1 - 2
integration-cli/docker_cli_cp_test.go

@@ -11,7 +11,6 @@ import (
 	"strings"
 
 	"github.com/docker/docker/integration-cli/checker"
-	"github.com/docker/docker/pkg/testutil"
 	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/go-check/check"
 )
@@ -548,7 +547,7 @@ func (s *DockerSuite) TestCpToStdout(c *check.C) {
 	// failed to set up container
 	c.Assert(strings.TrimSpace(out), checker.Equals, "0")
 
-	out, _, err := testutil.RunCommandPipelineWithOutput(
+	out, err := RunCommandPipelineWithOutput(
 		exec.Command(dockerBinary, "cp", containerID+":/test", "-"),
 		exec.Command("tar", "-vtf", "-"))
 

+ 21 - 3
integration-cli/docker_cli_daemon_test.go

@@ -201,7 +201,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithInvalidBasesize(c *check.C) {
 	testRequires(c, Devicemapper)
 	s.d.Start(c)
 
-	oldBasesizeBytes := s.d.GetBaseDeviceSize(c)
+	oldBasesizeBytes := getBaseDeviceSize(c, s.d)
 	var newBasesizeBytes int64 = 1073741824 //1GB in bytes
 
 	if newBasesizeBytes < oldBasesizeBytes {
@@ -221,7 +221,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithIncreasedBasesize(c *check.C) {
 	testRequires(c, Devicemapper)
 	s.d.Start(c)
 
-	oldBasesizeBytes := s.d.GetBaseDeviceSize(c)
+	oldBasesizeBytes := getBaseDeviceSize(c, s.d)
 
 	var newBasesizeBytes int64 = 53687091200 //50GB in bytes
 
@@ -232,13 +232,31 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithIncreasedBasesize(c *check.C) {
 	err := s.d.RestartWithError("--storage-opt", fmt.Sprintf("dm.basesize=%d", newBasesizeBytes))
 	c.Assert(err, check.IsNil, check.Commentf("we should have been able to start the daemon with increased base device size: %v", err))
 
-	basesizeAfterRestart := s.d.GetBaseDeviceSize(c)
+	basesizeAfterRestart := getBaseDeviceSize(c, s.d)
 	newBasesize, err := convertBasesize(newBasesizeBytes)
 	c.Assert(err, check.IsNil, check.Commentf("Error in converting base device size: %v", err))
 	c.Assert(newBasesize, check.Equals, basesizeAfterRestart, check.Commentf("Basesize passed is not equal to Basesize set"))
 	s.d.Stop(c)
 }
 
+func getBaseDeviceSize(c *check.C, d *daemon.Daemon) int64 {
+	info := d.Info(c)
+	for _, statusLine := range info.DriverStatus {
+		key, value := statusLine[0], statusLine[1]
+		if key == "Base Device Size" {
+			return parseDeviceSize(c, value)
+		}
+	}
+	c.Fatal("failed to parse Base Device Size from info")
+	return int64(0)
+}
+
+func parseDeviceSize(c *check.C, raw string) int64 {
+	size, err := units.RAMInBytes(strings.TrimSpace(raw))
+	c.Assert(err, check.IsNil)
+	return size
+}
+
 func convertBasesize(basesizeBytes int64) (int64, error) {
 	basesize := units.HumanSize(float64(basesizeBytes))
 	basesize = strings.Trim(basesize, " ")[:len(basesize)-3]

+ 1 - 2
integration-cli/docker_cli_events_test.go

@@ -18,7 +18,6 @@ import (
 	"github.com/docker/docker/integration-cli/cli"
 	"github.com/docker/docker/integration-cli/cli/build"
 	"github.com/docker/docker/integration-cli/request"
-	"github.com/docker/docker/pkg/testutil"
 	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/go-check/check"
 )
@@ -230,7 +229,7 @@ func (s *DockerSuite) TestEventsImageImport(c *check.C) {
 	cleanedContainerID := strings.TrimSpace(out)
 
 	since := daemonUnixTime(c)
-	out, _, err := testutil.RunCommandPipelineWithOutput(
+	out, err := RunCommandPipelineWithOutput(
 		exec.Command(dockerBinary, "export", cleanedContainerID),
 		exec.Command(dockerBinary, "import", "-"),
 	)

+ 1 - 2
integration-cli/docker_cli_import_test.go

@@ -11,7 +11,6 @@ import (
 
 	"github.com/docker/docker/integration-cli/checker"
 	"github.com/docker/docker/integration-cli/cli"
-	"github.com/docker/docker/pkg/testutil"
 	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/go-check/check"
 )
@@ -21,7 +20,7 @@ func (s *DockerSuite) TestImportDisplay(c *check.C) {
 	out, _ := dockerCmd(c, "run", "-d", "busybox", "true")
 	cleanedContainerID := strings.TrimSpace(out)
 
-	out, _, err := testutil.RunCommandPipelineWithOutput(
+	out, err := RunCommandPipelineWithOutput(
 		exec.Command(dockerBinary, "export", cleanedContainerID),
 		exec.Command(dockerBinary, "import", "-"),
 	)

+ 10 - 11
integration-cli/docker_cli_save_load_test.go

@@ -17,7 +17,6 @@ import (
 
 	"github.com/docker/docker/integration-cli/checker"
 	"github.com/docker/docker/integration-cli/cli/build"
-	"github.com/docker/docker/pkg/testutil"
 	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/go-check/check"
 	digest "github.com/opencontainers/go-digest"
@@ -34,7 +33,7 @@ func (s *DockerSuite) TestSaveXzAndLoadRepoStdout(c *check.C) {
 
 	dockerCmd(c, "inspect", repoName)
 
-	repoTarball, _, err := testutil.RunCommandPipelineWithOutput(
+	repoTarball, err := RunCommandPipelineWithOutput(
 		exec.Command(dockerBinary, "save", repoName),
 		exec.Command("xz", "-c"),
 		exec.Command("gzip", "-c"))
@@ -63,7 +62,7 @@ func (s *DockerSuite) TestSaveXzGzAndLoadRepoStdout(c *check.C) {
 
 	dockerCmd(c, "inspect", repoName)
 
-	out, _, err := testutil.RunCommandPipelineWithOutput(
+	out, err := RunCommandPipelineWithOutput(
 		exec.Command(dockerBinary, "save", repoName),
 		exec.Command("xz", "-c"),
 		exec.Command("gzip", "-c"))
@@ -90,7 +89,7 @@ func (s *DockerSuite) TestSaveSingleTag(c *check.C) {
 	out, _ := dockerCmd(c, "images", "-q", "--no-trunc", repoName)
 	cleanedImageID := strings.TrimSpace(out)
 
-	out, _, err := testutil.RunCommandPipelineWithOutput(
+	out, err := RunCommandPipelineWithOutput(
 		exec.Command(dockerBinary, "save", fmt.Sprintf("%v:latest", repoName)),
 		exec.Command("tar", "t"),
 		exec.Command("grep", "-E", fmt.Sprintf("(^repositories$|%v)", cleanedImageID)))
@@ -109,7 +108,7 @@ func (s *DockerSuite) TestSaveCheckTimes(c *check.C) {
 	c.Assert(err, checker.IsNil, check.Commentf("failed to marshal from %q: err %v", repoName, err))
 	c.Assert(len(data), checker.Not(checker.Equals), 0, check.Commentf("failed to marshal the data from %q", repoName))
 	tarTvTimeFormat := "2006-01-02 15:04"
-	out, _, err = testutil.RunCommandPipelineWithOutput(
+	out, err = RunCommandPipelineWithOutput(
 		exec.Command(dockerBinary, "save", repoName),
 		exec.Command("tar", "tv"),
 		exec.Command("grep", "-E", fmt.Sprintf("%s %s", data[0].Created.Format(tarTvTimeFormat), digest.Digest(data[0].ID).Hex())))
@@ -167,7 +166,7 @@ func (s *DockerSuite) TestSaveAndLoadRepoFlags(c *check.C) {
 
 	before, _ := dockerCmd(c, "inspect", repoName)
 
-	out, _, err := testutil.RunCommandPipelineWithOutput(
+	out, err := RunCommandPipelineWithOutput(
 		exec.Command(dockerBinary, "save", repoName),
 		exec.Command(dockerBinary, "load"))
 	c.Assert(err, checker.IsNil, check.Commentf("failed to save and load repo: %s, %v", out, err))
@@ -196,7 +195,7 @@ func (s *DockerSuite) TestSaveMultipleNames(c *check.C) {
 	// Make two images
 	dockerCmd(c, "tag", "emptyfs:latest", fmt.Sprintf("%v-two:latest", repoName))
 
-	out, _, err := testutil.RunCommandPipelineWithOutput(
+	out, err := RunCommandPipelineWithOutput(
 		exec.Command(dockerBinary, "save", fmt.Sprintf("%v-one", repoName), fmt.Sprintf("%v-two:latest", repoName)),
 		exec.Command("tar", "xO", "repositories"),
 		exec.Command("grep", "-q", "-E", "(-one|-two)"),
@@ -228,7 +227,7 @@ func (s *DockerSuite) TestSaveRepoWithMultipleImages(c *check.C) {
 	deleteImages(repoName)
 
 	// create the archive
-	out, _, err := testutil.RunCommandPipelineWithOutput(
+	out, err := RunCommandPipelineWithOutput(
 		exec.Command(dockerBinary, "save", repoName, "busybox:latest"),
 		exec.Command("tar", "t"))
 	c.Assert(err, checker.IsNil, check.Commentf("failed to save multiple images: %s, %v", out, err))
@@ -272,7 +271,7 @@ func (s *DockerSuite) TestSaveDirectoryPermissions(c *check.C) {
 	RUN adduser -D user && mkdir -p /opt/a/b && chown -R user:user /opt/a
 	RUN touch /opt/a/b/c && chown user:user /opt/a/b/c`))
 
-	out, _, err := testutil.RunCommandPipelineWithOutput(
+	out, err := RunCommandPipelineWithOutput(
 		exec.Command(dockerBinary, "save", name),
 		exec.Command("tar", "-xf", "-", "-C", extractionDirectory),
 	)
@@ -384,7 +383,7 @@ func (s *DockerSuite) TestSaveLoadNoTag(c *check.C) {
 	id := inspectField(c, name, "Id")
 
 	// Test to make sure that save w/o name just shows imageID during load
-	out, _, err := testutil.RunCommandPipelineWithOutput(
+	out, err := RunCommandPipelineWithOutput(
 		exec.Command(dockerBinary, "save", id),
 		exec.Command(dockerBinary, "load"))
 	c.Assert(err, checker.IsNil, check.Commentf("failed to save and load repo: %s, %v", out, err))
@@ -395,7 +394,7 @@ func (s *DockerSuite) TestSaveLoadNoTag(c *check.C) {
 	c.Assert(out, checker.Contains, id)
 
 	// Test to make sure that save by name shows that name during load
-	out, _, err = testutil.RunCommandPipelineWithOutput(
+	out, err = RunCommandPipelineWithOutput(
 		exec.Command(dockerBinary, "save", name),
 		exec.Command(dockerBinary, "load"))
 	c.Assert(err, checker.IsNil, check.Commentf("failed to save and load repo: %s, %v", out, err))

+ 23 - 25
integration-cli/docker_cli_swarm_test.go

@@ -12,7 +12,6 @@ import (
 	"net/http"
 	"net/http/httptest"
 	"os"
-	"os/exec"
 	"path/filepath"
 	"strings"
 	"time"
@@ -23,7 +22,6 @@ import (
 	"github.com/docker/docker/integration-cli/checker"
 	"github.com/docker/docker/integration-cli/cli"
 	"github.com/docker/docker/integration-cli/daemon"
-	"github.com/docker/docker/pkg/testutil"
 	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/docker/docker/pkg/testutil/tempfile"
 	"github.com/docker/libnetwork/driverapi"
@@ -467,14 +465,17 @@ func (s *DockerSwarmSuite) TestSwarmIngressNetwork(c *check.C) {
 	d := s.AddDaemon(c, true, true)
 
 	// Ingress network can be removed
-	out, _, err := testutil.RunCommandPipelineWithOutput(
-		exec.Command("echo", "Y"),
-		exec.Command("docker", "-H", d.Sock(), "network", "rm", "ingress"),
-	)
-	c.Assert(err, checker.IsNil, check.Commentf(out))
+	removeNetwork := func(name string) *icmd.Result {
+		return cli.Docker(
+			cli.Args("-H", d.Sock(), "network", "rm", name),
+			cli.WithStdin(strings.NewReader("Y")))
+	}
+
+	result := removeNetwork("ingress")
+	result.Assert(c, icmd.Success)
 
 	// And recreated
-	out, err = d.Cmd("network", "create", "-d", "overlay", "--ingress", "new-ingress")
+	out, err := d.Cmd("network", "create", "-d", "overlay", "--ingress", "new-ingress")
 	c.Assert(err, checker.IsNil, check.Commentf(out))
 
 	// But only one is allowed
@@ -485,21 +486,19 @@ func (s *DockerSwarmSuite) TestSwarmIngressNetwork(c *check.C) {
 	// It cannot be removed if it is being used
 	out, err = d.Cmd("service", "create", "--no-resolve-image", "--name", "srv1", "-p", "9000:8000", "busybox", "top")
 	c.Assert(err, checker.IsNil, check.Commentf(out))
-	out, _, err = testutil.RunCommandPipelineWithOutput(
-		exec.Command("echo", "Y"),
-		exec.Command("docker", "-H", d.Sock(), "network", "rm", "new-ingress"),
-	)
-	c.Assert(err, checker.NotNil)
-	c.Assert(strings.TrimSpace(out), checker.Contains, "ingress network cannot be removed because service")
+
+	result = removeNetwork("new-ingress")
+	result.Assert(c, icmd.Expected{
+		ExitCode: 1,
+		Err:      "ingress network cannot be removed because service",
+	})
 
 	// But it can be removed once no more services depend on it
 	out, err = d.Cmd("service", "update", "--publish-rm", "9000:8000", "srv1")
 	c.Assert(err, checker.IsNil, check.Commentf(out))
-	out, _, err = testutil.RunCommandPipelineWithOutput(
-		exec.Command("echo", "Y"),
-		exec.Command("docker", "-H", d.Sock(), "network", "rm", "new-ingress"),
-	)
-	c.Assert(err, checker.IsNil, check.Commentf(out))
+
+	result = removeNetwork("new-ingress")
+	result.Assert(c, icmd.Success)
 
 	// A service which needs the ingress network cannot be created if no ingress is present
 	out, err = d.Cmd("service", "create", "--no-resolve-image", "--name", "srv2", "-p", "500:500", "busybox", "top")
@@ -520,15 +519,14 @@ func (s *DockerSwarmSuite) TestSwarmCreateServiceWithNoIngressNetwork(c *check.C
 	d := s.AddDaemon(c, true, true)
 
 	// Remove ingress network
-	out, _, err := testutil.RunCommandPipelineWithOutput(
-		exec.Command("echo", "Y"),
-		exec.Command("docker", "-H", d.Sock(), "network", "rm", "ingress"),
-	)
-	c.Assert(err, checker.IsNil, check.Commentf(out))
+	result := cli.Docker(
+		cli.Args("-H", d.Sock(), "network", "rm", "ingress"),
+		cli.WithStdin(strings.NewReader("Y")))
+	result.Assert(c, icmd.Success)
 
 	// Create a overlay network and launch a service on it
 	// Make sure nothing panics because ingress network is missing
-	out, err = d.Cmd("network", "create", "-d", "overlay", "another-network")
+	out, err := d.Cmd("network", "create", "-d", "overlay", "another-network")
 	c.Assert(err, checker.IsNil, check.Commentf(out))
 	out, err = d.Cmd("service", "create", "--no-resolve-image", "--name", "srv4", "--network", "another-network", "busybox", "top")
 	c.Assert(err, checker.IsNil, check.Commentf(out))

+ 4 - 5
integration-cli/docker_cli_userns_test.go

@@ -15,7 +15,6 @@ import (
 	"github.com/docker/docker/integration-cli/checker"
 	"github.com/docker/docker/pkg/stringid"
 	"github.com/docker/docker/pkg/system"
-	"github.com/docker/docker/pkg/testutil"
 	"github.com/go-check/check"
 )
 
@@ -62,15 +61,15 @@ func (s *DockerDaemonSuite) TestDaemonUserNamespaceRootSetting(c *check.C) {
 	c.Assert(err, checker.IsNil, check.Commentf("Could not inspect running container: out: %q", pid))
 	// check the uid and gid maps for the PID to ensure root is remapped
 	// (cmd = cat /proc/<pid>/uid_map | grep -E '0\s+9999\s+1')
-	out, rc1, err := testutil.RunCommandPipelineWithOutput(
+	out, err = RunCommandPipelineWithOutput(
 		exec.Command("cat", "/proc/"+strings.TrimSpace(pid)+"/uid_map"),
 		exec.Command("grep", "-E", fmt.Sprintf("0[[:space:]]+%d[[:space:]]+", uid)))
-	c.Assert(rc1, checker.Equals, 0, check.Commentf("Didn't match uid_map: output: %s", out))
+	c.Assert(err, check.IsNil)
 
-	out, rc2, err := testutil.RunCommandPipelineWithOutput(
+	out, err = RunCommandPipelineWithOutput(
 		exec.Command("cat", "/proc/"+strings.TrimSpace(pid)+"/gid_map"),
 		exec.Command("grep", "-E", fmt.Sprintf("0[[:space:]]+%d[[:space:]]+", gid)))
-	c.Assert(rc2, checker.Equals, 0, check.Commentf("Didn't match gid_map: output: %s", out))
+	c.Assert(err, check.IsNil)
 
 	// check that the touched file is owned by remapped uid:gid
 	stat, err := system.Stat(filepath.Join(tmpDir, "testfile"))

+ 5 - 1
integration-cli/request/request.go

@@ -165,7 +165,11 @@ func NewHTTPClient(host string) (*http.Client, error) {
 
 // NewClient returns a new Docker API client
 func NewClient() (dclient.APIClient, error) {
-	host := DaemonHost()
+	return NewClientForHost(DaemonHost())
+}
+
+// NewClientForHost returns a Docker API client for the host
+func NewClientForHost(host string) (dclient.APIClient, error) {
 	httpClient, err := NewHTTPClient(host)
 	if err != nil {
 		return nil, err

+ 48 - 0
integration-cli/utils_test.go

@@ -9,6 +9,7 @@ import (
 
 	"github.com/docker/docker/pkg/stringutils"
 	"github.com/docker/docker/pkg/testutil/cmd"
+	"github.com/pkg/errors"
 )
 
 func getPrefixAndSlashFromDaemonPlatform() (prefix, slash string) {
@@ -64,3 +65,50 @@ func RandomTmpDirPath(s string, platform string) string {
 	}
 	return filepath.ToSlash(path) // Using /
 }
+
+// RunCommandPipelineWithOutput runs the array of commands with the output
+// of each pipelined with the following (like cmd1 | cmd2 | cmd3 would do).
+// It returns the final output, the exitCode different from 0 and the error
+// if something bad happened.
+// Deprecated: use icmd instead
+func RunCommandPipelineWithOutput(cmds ...*exec.Cmd) (output string, err error) {
+	if len(cmds) < 2 {
+		return "", errors.New("pipeline does not have multiple cmds")
+	}
+
+	// connect stdin of each cmd to stdout pipe of previous cmd
+	for i, cmd := range cmds {
+		if i > 0 {
+			prevCmd := cmds[i-1]
+			cmd.Stdin, err = prevCmd.StdoutPipe()
+
+			if err != nil {
+				return "", fmt.Errorf("cannot set stdout pipe for %s: %v", cmd.Path, err)
+			}
+		}
+	}
+
+	// start all cmds except the last
+	for _, cmd := range cmds[:len(cmds)-1] {
+		if err = cmd.Start(); err != nil {
+			return "", fmt.Errorf("starting %s failed with error: %v", cmd.Path, err)
+		}
+	}
+
+	defer func() {
+		var pipeErrMsgs []string
+		// wait all cmds except the last to release their resources
+		for _, cmd := range cmds[:len(cmds)-1] {
+			if pipeErr := cmd.Wait(); pipeErr != nil {
+				pipeErrMsgs = append(pipeErrMsgs, fmt.Sprintf("command %s failed with error: %v", cmd.Path, pipeErr))
+			}
+		}
+		if len(pipeErrMsgs) > 0 && err == nil {
+			err = fmt.Errorf("pipelineError from Wait: %v", strings.Join(pipeErrMsgs, ", "))
+		}
+	}()
+
+	// wait on last cmd
+	out, err := cmds[len(cmds)-1].CombinedOutput()
+	return string(out), err
+}

+ 0 - 62
pkg/testutil/utils.go

@@ -1,62 +0,0 @@
-package testutil
-
-import (
-	"errors"
-	"fmt"
-	"os/exec"
-	"strings"
-
-	"github.com/docker/docker/pkg/system"
-)
-
-func runCommandWithOutput(cmd *exec.Cmd) (output string, exitCode int, err error) {
-	out, err := cmd.CombinedOutput()
-	exitCode = system.ProcessExitCode(err)
-	output = string(out)
-	return
-}
-
-// RunCommandPipelineWithOutput runs the array of commands with the output
-// of each pipelined with the following (like cmd1 | cmd2 | cmd3 would do).
-// It returns the final output, the exitCode different from 0 and the error
-// if something bad happened.
-func RunCommandPipelineWithOutput(cmds ...*exec.Cmd) (output string, exitCode int, err error) {
-	if len(cmds) < 2 {
-		return "", 0, errors.New("pipeline does not have multiple cmds")
-	}
-
-	// connect stdin of each cmd to stdout pipe of previous cmd
-	for i, cmd := range cmds {
-		if i > 0 {
-			prevCmd := cmds[i-1]
-			cmd.Stdin, err = prevCmd.StdoutPipe()
-
-			if err != nil {
-				return "", 0, fmt.Errorf("cannot set stdout pipe for %s: %v", cmd.Path, err)
-			}
-		}
-	}
-
-	// start all cmds except the last
-	for _, cmd := range cmds[:len(cmds)-1] {
-		if err = cmd.Start(); err != nil {
-			return "", 0, fmt.Errorf("starting %s failed with error: %v", cmd.Path, err)
-		}
-	}
-
-	defer func() {
-		var pipeErrMsgs []string
-		// wait all cmds except the last to release their resources
-		for _, cmd := range cmds[:len(cmds)-1] {
-			if pipeErr := cmd.Wait(); pipeErr != nil {
-				pipeErrMsgs = append(pipeErrMsgs, fmt.Sprintf("command %s failed with error: %v", cmd.Path, pipeErr))
-			}
-		}
-		if len(pipeErrMsgs) > 0 && err == nil {
-			err = fmt.Errorf("pipelineError from Wait: %v", strings.Join(pipeErrMsgs, ", "))
-		}
-	}()
-
-	// wait on last cmd
-	return runCommandWithOutput(cmds[len(cmds)-1])
-}

+ 0 - 55
pkg/testutil/utils_test.go

@@ -1,55 +0,0 @@
-package testutil
-
-import (
-	"os"
-	"os/exec"
-	"runtime"
-	"testing"
-)
-
-func TestRunCommandPipelineWithOutputWithNotEnoughCmds(t *testing.T) {
-	_, _, err := RunCommandPipelineWithOutput(exec.Command("ls"))
-	expectedError := "pipeline does not have multiple cmds"
-	if err == nil || err.Error() != expectedError {
-		t.Fatalf("Expected an error with %s, got err:%s", expectedError, err)
-	}
-}
-
-func TestRunCommandPipelineWithOutputErrors(t *testing.T) {
-	p := "$PATH"
-	if runtime.GOOS == "windows" {
-		p = "%PATH%"
-	}
-	cmd1 := exec.Command("ls")
-	cmd1.Stdout = os.Stdout
-	cmd2 := exec.Command("anything really")
-	_, _, err := RunCommandPipelineWithOutput(cmd1, cmd2)
-	if err == nil || err.Error() != "cannot set stdout pipe for anything really: exec: Stdout already set" {
-		t.Fatalf("Expected an error, got %v", err)
-	}
-
-	cmdWithError := exec.Command("doesnotexists")
-	cmdCat := exec.Command("cat")
-	_, _, err = RunCommandPipelineWithOutput(cmdWithError, cmdCat)
-	if err == nil || err.Error() != `starting doesnotexists failed with error: exec: "doesnotexists": executable file not found in `+p {
-		t.Fatalf("Expected an error, got %v", err)
-	}
-}
-
-func TestRunCommandPipelineWithOutput(t *testing.T) {
-	//TODO: Should run on Solaris
-	if runtime.GOOS == "solaris" {
-		t.Skip()
-	}
-	cmds := []*exec.Cmd{
-		// Print 2 characters
-		exec.Command("echo", "-n", "11"),
-		// Count the number or char from stdin (previous command)
-		exec.Command("wc", "-m"),
-	}
-	out, exitCode, err := RunCommandPipelineWithOutput(cmds...)
-	expectedOutput := "2\n"
-	if out != expectedOutput || exitCode != 0 || err != nil {
-		t.Fatalf("Expected %s for commands %v, got out:%s, exitCode:%d, err:%v", expectedOutput, cmds, out, exitCode, err)
-	}
-}