1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
|
package main
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
"github.com/docker/docker/integration-cli/cli"
"github.com/docker/docker/testutil"
"github.com/pkg/errors"
"gotest.tools/v3/icmd"
)
func getPrefixAndSlashFromDaemonPlatform() (prefix, slash string) {
if testEnv.DaemonInfo.OSType == "windows" {
return "c:", `\`
}
return "", "/"
}
// TODO: update code to call cmd.RunCmd directly, and remove this function
// Deprecated: use gotest.tools/icmd
func runCommandWithOutput(execCmd *exec.Cmd) (string, int, error) {
result := icmd.RunCmd(icmd.Cmd{
Command: execCmd.Args,
Env: execCmd.Env,
Dir: execCmd.Dir,
Stdin: execCmd.Stdin,
Stdout: execCmd.Stdout,
})
return result.Combined(), result.ExitCode, result.Error
}
// 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
}
// 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")
}
path := filepath.Join(tmp, fmt.Sprintf("%s.%s", s, testutil.GenerateRandomAlphaOnlyString(10)))
if platform == "windows" {
return filepath.FromSlash(path) // Using \
}
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
}
type elementListOptions struct {
element, format string
}
func existingElements(c *testing.T, opts elementListOptions) []string {
var args []string
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 := cli.DockerCmd(c, args...).Combined()
var lines []string
for _, l := range strings.Split(out, "\n") {
if l != "" {
lines = append(lines, l)
}
}
return lines
}
// ExistingContainerIDs returns a list of currently existing container IDs.
func ExistingContainerIDs(c *testing.T) []string {
return existingElements(c, elementListOptions{element: "container", format: "{{.ID}}"})
}
// ExistingContainerNames returns a list of existing container names.
func ExistingContainerNames(c *testing.T) []string {
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")
}
|