github.com/rita33cool1/iot-system-gateway@v0.0.0-20200911033302-e65bde238cc5/docker-engine/integration-cli/utils_test.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"os/exec"
     7  	"path/filepath"
     8  	"strings"
     9  
    10  	"github.com/docker/docker/internal/testutil"
    11  	"github.com/go-check/check"
    12  	"github.com/gotestyourself/gotestyourself/icmd"
    13  	"github.com/pkg/errors"
    14  )
    15  
    16  func getPrefixAndSlashFromDaemonPlatform() (prefix, slash string) {
    17  	if testEnv.OSType == "windows" {
    18  		return "c:", `\`
    19  	}
    20  	return "", "/"
    21  }
    22  
    23  // TODO: update code to call cmd.RunCmd directly, and remove this function
    24  // Deprecated: use gotestyourself/gotestyourself/icmd
    25  func runCommandWithOutput(execCmd *exec.Cmd) (string, int, error) {
    26  	result := icmd.RunCmd(transformCmd(execCmd))
    27  	return result.Combined(), result.ExitCode, result.Error
    28  }
    29  
    30  // Temporary shim for migrating commands to the new function
    31  func transformCmd(execCmd *exec.Cmd) icmd.Cmd {
    32  	return icmd.Cmd{
    33  		Command: execCmd.Args,
    34  		Env:     execCmd.Env,
    35  		Dir:     execCmd.Dir,
    36  		Stdin:   execCmd.Stdin,
    37  		Stdout:  execCmd.Stdout,
    38  	}
    39  }
    40  
    41  // ParseCgroupPaths parses 'procCgroupData', which is output of '/proc/<pid>/cgroup', and returns
    42  // a map which cgroup name as key and path as value.
    43  func ParseCgroupPaths(procCgroupData string) map[string]string {
    44  	cgroupPaths := map[string]string{}
    45  	for _, line := range strings.Split(procCgroupData, "\n") {
    46  		parts := strings.Split(line, ":")
    47  		if len(parts) != 3 {
    48  			continue
    49  		}
    50  		cgroupPaths[parts[1]] = parts[2]
    51  	}
    52  	return cgroupPaths
    53  }
    54  
    55  // RandomTmpDirPath provides a temporary path with rand string appended.
    56  // does not create or checks if it exists.
    57  func RandomTmpDirPath(s string, platform string) string {
    58  	// TODO: why doesn't this use os.TempDir() ?
    59  	tmp := "/tmp"
    60  	if platform == "windows" {
    61  		tmp = os.Getenv("TEMP")
    62  	}
    63  	path := filepath.Join(tmp, fmt.Sprintf("%s.%s", s, testutil.GenerateRandomAlphaOnlyString(10)))
    64  	if platform == "windows" {
    65  		return filepath.FromSlash(path) // Using \
    66  	}
    67  	return filepath.ToSlash(path) // Using /
    68  }
    69  
    70  // RunCommandPipelineWithOutput runs the array of commands with the output
    71  // of each pipelined with the following (like cmd1 | cmd2 | cmd3 would do).
    72  // It returns the final output, the exitCode different from 0 and the error
    73  // if something bad happened.
    74  // Deprecated: use icmd instead
    75  func RunCommandPipelineWithOutput(cmds ...*exec.Cmd) (output string, err error) {
    76  	if len(cmds) < 2 {
    77  		return "", errors.New("pipeline does not have multiple cmds")
    78  	}
    79  
    80  	// connect stdin of each cmd to stdout pipe of previous cmd
    81  	for i, cmd := range cmds {
    82  		if i > 0 {
    83  			prevCmd := cmds[i-1]
    84  			cmd.Stdin, err = prevCmd.StdoutPipe()
    85  
    86  			if err != nil {
    87  				return "", fmt.Errorf("cannot set stdout pipe for %s: %v", cmd.Path, err)
    88  			}
    89  		}
    90  	}
    91  
    92  	// start all cmds except the last
    93  	for _, cmd := range cmds[:len(cmds)-1] {
    94  		if err = cmd.Start(); err != nil {
    95  			return "", fmt.Errorf("starting %s failed with error: %v", cmd.Path, err)
    96  		}
    97  	}
    98  
    99  	defer func() {
   100  		var pipeErrMsgs []string
   101  		// wait all cmds except the last to release their resources
   102  		for _, cmd := range cmds[:len(cmds)-1] {
   103  			if pipeErr := cmd.Wait(); pipeErr != nil {
   104  				pipeErrMsgs = append(pipeErrMsgs, fmt.Sprintf("command %s failed with error: %v", cmd.Path, pipeErr))
   105  			}
   106  		}
   107  		if len(pipeErrMsgs) > 0 && err == nil {
   108  			err = fmt.Errorf("pipelineError from Wait: %v", strings.Join(pipeErrMsgs, ", "))
   109  		}
   110  	}()
   111  
   112  	// wait on last cmd
   113  	out, err := cmds[len(cmds)-1].CombinedOutput()
   114  	return string(out), err
   115  }
   116  
   117  type elementListOptions struct {
   118  	element, format string
   119  }
   120  
   121  func existingElements(c *check.C, opts elementListOptions) []string {
   122  	args := []string{}
   123  	switch opts.element {
   124  	case "container":
   125  		args = append(args, "ps", "-a")
   126  	case "image":
   127  		args = append(args, "images", "-a")
   128  	case "network":
   129  		args = append(args, "network", "ls")
   130  	case "plugin":
   131  		args = append(args, "plugin", "ls")
   132  	case "volume":
   133  		args = append(args, "volume", "ls")
   134  	}
   135  	if opts.format != "" {
   136  		args = append(args, "--format", opts.format)
   137  	}
   138  	out, _ := dockerCmd(c, args...)
   139  	lines := []string{}
   140  	for _, l := range strings.Split(out, "\n") {
   141  		if l != "" {
   142  			lines = append(lines, l)
   143  		}
   144  	}
   145  	return lines
   146  }
   147  
   148  // ExistingContainerIDs returns a list of currently existing container IDs.
   149  func ExistingContainerIDs(c *check.C) []string {
   150  	return existingElements(c, elementListOptions{element: "container", format: "{{.ID}}"})
   151  }
   152  
   153  // ExistingContainerNames returns a list of existing container names.
   154  func ExistingContainerNames(c *check.C) []string {
   155  	return existingElements(c, elementListOptions{element: "container", format: "{{.Names}}"})
   156  }
   157  
   158  // RemoveLinesForExistingElements removes existing elements from the output of a
   159  // docker command.
   160  // This function takes an output []string and returns a []string.
   161  func RemoveLinesForExistingElements(output, existing []string) []string {
   162  	for _, e := range existing {
   163  		index := -1
   164  		for i, line := range output {
   165  			if strings.Contains(line, e) {
   166  				index = i
   167  				break
   168  			}
   169  		}
   170  		if index != -1 {
   171  			output = append(output[:index], output[index+1:]...)
   172  		}
   173  	}
   174  	return output
   175  }
   176  
   177  // RemoveOutputForExistingElements removes existing elements from the output of
   178  // a docker command.
   179  // This function takes an output string and returns a string.
   180  func RemoveOutputForExistingElements(output string, existing []string) string {
   181  	res := RemoveLinesForExistingElements(strings.Split(output, "\n"), existing)
   182  	return strings.Join(res, "\n")
   183  }