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