integration-cli/utils_test.go
6db32fde
 package main
 
 import (
9db68f4d
 	"fmt"
 	"os"
def13fa2
 	"os/exec"
9db68f4d
 	"path/filepath"
e8bd6718
 	"strings"
e25352a4
 	"testing"
e8bd6718
 
7c35a241
 	"github.com/docker/docker/internal/testutil"
e885af2a
 	"github.com/pkg/errors"
38457285
 	"gotest.tools/icmd"
6db32fde
 )
 
382c96ee
 func getPrefixAndSlashFromDaemonPlatform() (prefix, slash string) {
18a771a7
 	if testEnv.OSType == "windows" {
382c96ee
 		return "c:", `\`
 	}
 	return "", "/"
 }
 
d7022f2b
 // TODO: update code to call cmd.RunCmd directly, and remove this function
38457285
 // Deprecated: use gotest.tools/icmd
d7022f2b
 func runCommandWithOutput(execCmd *exec.Cmd) (string, int, error) {
92427b3a
 	result := icmd.RunCmd(transformCmd(execCmd))
d7022f2b
 	return result.Combined(), result.ExitCode, result.Error
6db32fde
 }
 
d7022f2b
 // Temporary shim for migrating commands to the new function
92427b3a
 func transformCmd(execCmd *exec.Cmd) icmd.Cmd {
 	return icmd.Cmd{
d7022f2b
 		Command: execCmd.Args,
 		Env:     execCmd.Env,
 		Dir:     execCmd.Dir,
 		Stdin:   execCmd.Stdin,
 		Stdout:  execCmd.Stdout,
 	}
6db32fde
 }
e8bd6718
 
 // ParseCgroupPaths parses 'procCgroupData', which is output of '/proc/<pid>/cgroup', and returns
 // a map which cgroup name as key and path as value.
 func ParseCgroupPaths(procCgroupData string) map[string]string {
 	cgroupPaths := map[string]string{}
 	for _, line := range strings.Split(procCgroupData, "\n") {
 		parts := strings.Split(line, ":")
 		if len(parts) != 3 {
 			continue
 		}
 		cgroupPaths[parts[1]] = parts[2]
 	}
 	return cgroupPaths
 }
9db68f4d
 
 // RandomTmpDirPath provides a temporary path with rand string appended.
 // does not create or checks if it exists.
 func RandomTmpDirPath(s string, platform string) string {
 	// TODO: why doesn't this use os.TempDir() ?
 	tmp := "/tmp"
 	if platform == "windows" {
 		tmp = os.Getenv("TEMP")
 	}
7c35a241
 	path := filepath.Join(tmp, fmt.Sprintf("%s.%s", s, testutil.GenerateRandomAlphaOnlyString(10)))
9db68f4d
 	if platform == "windows" {
 		return filepath.FromSlash(path) // Using \
 	}
 	return filepath.ToSlash(path) // Using /
 }
e885af2a
 
 // 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
 }
dc6ddfa8
 
 type elementListOptions struct {
 	element, format string
 }
 
64a928a3
 func existingElements(c *testing.T, opts elementListOptions) []string {
f23c00d8
 	var args []string
dc6ddfa8
 	switch opts.element {
 	case "container":
 		args = append(args, "ps", "-a")
 	case "image":
 		args = append(args, "images", "-a")
 	case "network":
 		args = append(args, "network", "ls")
 	case "plugin":
 		args = append(args, "plugin", "ls")
 	case "volume":
 		args = append(args, "volume", "ls")
 	}
 	if opts.format != "" {
 		args = append(args, "--format", opts.format)
 	}
 	out, _ := dockerCmd(c, args...)
f23c00d8
 	var lines []string
dc6ddfa8
 	for _, l := range strings.Split(out, "\n") {
 		if l != "" {
 			lines = append(lines, l)
 		}
 	}
 	return lines
 }
 
 // ExistingContainerIDs returns a list of currently existing container IDs.
64a928a3
 func ExistingContainerIDs(c *testing.T) []string {
dc6ddfa8
 	return existingElements(c, elementListOptions{element: "container", format: "{{.ID}}"})
 }
 
 // ExistingContainerNames returns a list of existing container names.
64a928a3
 func ExistingContainerNames(c *testing.T) []string {
dc6ddfa8
 	return existingElements(c, elementListOptions{element: "container", format: "{{.Names}}"})
 }
 
 // RemoveLinesForExistingElements removes existing elements from the output of a
 // docker command.
 // This function takes an output []string and returns a []string.
 func RemoveLinesForExistingElements(output, existing []string) []string {
 	for _, e := range existing {
 		index := -1
 		for i, line := range output {
 			if strings.Contains(line, e) {
 				index = i
 				break
 			}
 		}
 		if index != -1 {
 			output = append(output[:index], output[index+1:]...)
 		}
 	}
 	return output
 }
 
 // RemoveOutputForExistingElements removes existing elements from the output of
 // a docker command.
 // This function takes an output string and returns a string.
 func RemoveOutputForExistingElements(output string, existing []string) string {
 	res := RemoveLinesForExistingElements(strings.Split(output, "\n"), existing)
 	return strings.Join(res, "\n")
 }