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

     1  package main
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"io"
     8  	"io/ioutil"
     9  	"os"
    10  	"path"
    11  	"path/filepath"
    12  	"strconv"
    13  	"strings"
    14  	"time"
    15  
    16  	"github.com/docker/docker/api/types"
    17  	"github.com/docker/docker/client"
    18  	"github.com/docker/docker/integration-cli/checker"
    19  	"github.com/docker/docker/integration-cli/cli"
    20  	"github.com/docker/docker/integration-cli/daemon"
    21  	"github.com/docker/docker/integration-cli/request"
    22  	"github.com/go-check/check"
    23  	"github.com/gotestyourself/gotestyourself/icmd"
    24  	"golang.org/x/net/context"
    25  )
    26  
    27  // Deprecated
    28  func daemonHost() string {
    29  	return request.DaemonHost()
    30  }
    31  
    32  func deleteImages(images ...string) error {
    33  	args := []string{dockerBinary, "rmi", "-f"}
    34  	return icmd.RunCmd(icmd.Cmd{Command: append(args, images...)}).Error
    35  }
    36  
    37  // Deprecated: use cli.Docker or cli.DockerCmd
    38  func dockerCmdWithError(args ...string) (string, int, error) {
    39  	result := cli.Docker(cli.Args(args...))
    40  	if result.Error != nil {
    41  		return result.Combined(), result.ExitCode, result.Compare(icmd.Success)
    42  	}
    43  	return result.Combined(), result.ExitCode, result.Error
    44  }
    45  
    46  // Deprecated: use cli.Docker or cli.DockerCmd
    47  func dockerCmd(c *check.C, args ...string) (string, int) {
    48  	result := cli.DockerCmd(c, args...)
    49  	return result.Combined(), result.ExitCode
    50  }
    51  
    52  // Deprecated: use cli.Docker or cli.DockerCmd
    53  func dockerCmdWithResult(args ...string) *icmd.Result {
    54  	return cli.Docker(cli.Args(args...))
    55  }
    56  
    57  func findContainerIP(c *check.C, id string, network string) string {
    58  	out, _ := dockerCmd(c, "inspect", fmt.Sprintf("--format='{{ .NetworkSettings.Networks.%s.IPAddress }}'", network), id)
    59  	return strings.Trim(out, " \r\n'")
    60  }
    61  
    62  func getContainerCount(c *check.C) int {
    63  	const containers = "Containers:"
    64  
    65  	result := icmd.RunCommand(dockerBinary, "info")
    66  	result.Assert(c, icmd.Success)
    67  
    68  	lines := strings.Split(result.Combined(), "\n")
    69  	for _, line := range lines {
    70  		if strings.Contains(line, containers) {
    71  			output := strings.TrimSpace(line)
    72  			output = strings.TrimLeft(output, containers)
    73  			output = strings.Trim(output, " ")
    74  			containerCount, err := strconv.Atoi(output)
    75  			c.Assert(err, checker.IsNil)
    76  			return containerCount
    77  		}
    78  	}
    79  	return 0
    80  }
    81  
    82  func inspectFieldAndUnmarshall(c *check.C, name, field string, output interface{}) {
    83  	str := inspectFieldJSON(c, name, field)
    84  	err := json.Unmarshal([]byte(str), output)
    85  	if c != nil {
    86  		c.Assert(err, check.IsNil, check.Commentf("failed to unmarshal: %v", err))
    87  	}
    88  }
    89  
    90  // Deprecated: use cli.Inspect
    91  func inspectFilter(name, filter string) (string, error) {
    92  	format := fmt.Sprintf("{{%s}}", filter)
    93  	result := icmd.RunCommand(dockerBinary, "inspect", "-f", format, name)
    94  	if result.Error != nil || result.ExitCode != 0 {
    95  		return "", fmt.Errorf("failed to inspect %s: %s", name, result.Combined())
    96  	}
    97  	return strings.TrimSpace(result.Combined()), nil
    98  }
    99  
   100  // Deprecated: use cli.Inspect
   101  func inspectFieldWithError(name, field string) (string, error) {
   102  	return inspectFilter(name, fmt.Sprintf(".%s", field))
   103  }
   104  
   105  // Deprecated: use cli.Inspect
   106  func inspectField(c *check.C, name, field string) string {
   107  	out, err := inspectFilter(name, fmt.Sprintf(".%s", field))
   108  	if c != nil {
   109  		c.Assert(err, check.IsNil)
   110  	}
   111  	return out
   112  }
   113  
   114  // Deprecated: use cli.Inspect
   115  func inspectFieldJSON(c *check.C, name, field string) string {
   116  	out, err := inspectFilter(name, fmt.Sprintf("json .%s", field))
   117  	if c != nil {
   118  		c.Assert(err, check.IsNil)
   119  	}
   120  	return out
   121  }
   122  
   123  // Deprecated: use cli.Inspect
   124  func inspectFieldMap(c *check.C, name, path, field string) string {
   125  	out, err := inspectFilter(name, fmt.Sprintf("index .%s %q", path, field))
   126  	if c != nil {
   127  		c.Assert(err, check.IsNil)
   128  	}
   129  	return out
   130  }
   131  
   132  // Deprecated: use cli.Inspect
   133  func inspectMountSourceField(name, destination string) (string, error) {
   134  	m, err := inspectMountPoint(name, destination)
   135  	if err != nil {
   136  		return "", err
   137  	}
   138  	return m.Source, nil
   139  }
   140  
   141  // Deprecated: use cli.Inspect
   142  func inspectMountPoint(name, destination string) (types.MountPoint, error) {
   143  	out, err := inspectFilter(name, "json .Mounts")
   144  	if err != nil {
   145  		return types.MountPoint{}, err
   146  	}
   147  
   148  	return inspectMountPointJSON(out, destination)
   149  }
   150  
   151  var errMountNotFound = errors.New("mount point not found")
   152  
   153  // Deprecated: use cli.Inspect
   154  func inspectMountPointJSON(j, destination string) (types.MountPoint, error) {
   155  	var mp []types.MountPoint
   156  	if err := json.Unmarshal([]byte(j), &mp); err != nil {
   157  		return types.MountPoint{}, err
   158  	}
   159  
   160  	var m *types.MountPoint
   161  	for _, c := range mp {
   162  		if c.Destination == destination {
   163  			m = &c
   164  			break
   165  		}
   166  	}
   167  
   168  	if m == nil {
   169  		return types.MountPoint{}, errMountNotFound
   170  	}
   171  
   172  	return *m, nil
   173  }
   174  
   175  // Deprecated: use cli.Inspect
   176  func inspectImage(c *check.C, name, filter string) string {
   177  	args := []string{"inspect", "--type", "image"}
   178  	if filter != "" {
   179  		format := fmt.Sprintf("{{%s}}", filter)
   180  		args = append(args, "-f", format)
   181  	}
   182  	args = append(args, name)
   183  	result := icmd.RunCommand(dockerBinary, args...)
   184  	result.Assert(c, icmd.Success)
   185  	return strings.TrimSpace(result.Combined())
   186  }
   187  
   188  func getIDByName(c *check.C, name string) string {
   189  	id, err := inspectFieldWithError(name, "Id")
   190  	c.Assert(err, checker.IsNil)
   191  	return id
   192  }
   193  
   194  // Deprecated: use cli.Build
   195  func buildImageSuccessfully(c *check.C, name string, cmdOperators ...cli.CmdOperator) {
   196  	buildImage(name, cmdOperators...).Assert(c, icmd.Success)
   197  }
   198  
   199  // Deprecated: use cli.Build
   200  func buildImage(name string, cmdOperators ...cli.CmdOperator) *icmd.Result {
   201  	return cli.Docker(cli.Build(name), cmdOperators...)
   202  }
   203  
   204  // Write `content` to the file at path `dst`, creating it if necessary,
   205  // as well as any missing directories.
   206  // The file is truncated if it already exists.
   207  // Fail the test when error occurs.
   208  func writeFile(dst, content string, c *check.C) {
   209  	// Create subdirectories if necessary
   210  	c.Assert(os.MkdirAll(path.Dir(dst), 0700), check.IsNil)
   211  	f, err := os.OpenFile(dst, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0700)
   212  	c.Assert(err, check.IsNil)
   213  	defer f.Close()
   214  	// Write content (truncate if it exists)
   215  	_, err = io.Copy(f, strings.NewReader(content))
   216  	c.Assert(err, check.IsNil)
   217  }
   218  
   219  // Return the contents of file at path `src`.
   220  // Fail the test when error occurs.
   221  func readFile(src string, c *check.C) (content string) {
   222  	data, err := ioutil.ReadFile(src)
   223  	c.Assert(err, check.IsNil)
   224  
   225  	return string(data)
   226  }
   227  
   228  func containerStorageFile(containerID, basename string) string {
   229  	return filepath.Join(testEnv.PlatformDefaults.ContainerStoragePath, containerID, basename)
   230  }
   231  
   232  // docker commands that use this function must be run with the '-d' switch.
   233  func runCommandAndReadContainerFile(c *check.C, filename string, command string, args ...string) []byte {
   234  	result := icmd.RunCommand(command, args...)
   235  	result.Assert(c, icmd.Success)
   236  	contID := strings.TrimSpace(result.Combined())
   237  	if err := waitRun(contID); err != nil {
   238  		c.Fatalf("%v: %q", contID, err)
   239  	}
   240  	return readContainerFile(c, contID, filename)
   241  }
   242  
   243  func readContainerFile(c *check.C, containerID, filename string) []byte {
   244  	f, err := os.Open(containerStorageFile(containerID, filename))
   245  	c.Assert(err, checker.IsNil)
   246  	defer f.Close()
   247  
   248  	content, err := ioutil.ReadAll(f)
   249  	c.Assert(err, checker.IsNil)
   250  	return content
   251  }
   252  
   253  func readContainerFileWithExec(c *check.C, containerID, filename string) []byte {
   254  	result := icmd.RunCommand(dockerBinary, "exec", containerID, "cat", filename)
   255  	result.Assert(c, icmd.Success)
   256  	return []byte(result.Combined())
   257  }
   258  
   259  // daemonTime provides the current time on the daemon host
   260  func daemonTime(c *check.C) time.Time {
   261  	if testEnv.IsLocalDaemon() {
   262  		return time.Now()
   263  	}
   264  	cli, err := client.NewEnvClient()
   265  	c.Assert(err, check.IsNil)
   266  	defer cli.Close()
   267  
   268  	info, err := cli.Info(context.Background())
   269  	c.Assert(err, check.IsNil)
   270  
   271  	dt, err := time.Parse(time.RFC3339Nano, info.SystemTime)
   272  	c.Assert(err, check.IsNil, check.Commentf("invalid time format in GET /info response"))
   273  	return dt
   274  }
   275  
   276  // daemonUnixTime returns the current time on the daemon host with nanoseconds precision.
   277  // It return the time formatted how the client sends timestamps to the server.
   278  func daemonUnixTime(c *check.C) string {
   279  	return parseEventTime(daemonTime(c))
   280  }
   281  
   282  func parseEventTime(t time.Time) string {
   283  	return fmt.Sprintf("%d.%09d", t.Unix(), int64(t.Nanosecond()))
   284  }
   285  
   286  // appendBaseEnv appends the minimum set of environment variables to exec the
   287  // docker cli binary for testing with correct configuration to the given env
   288  // list.
   289  func appendBaseEnv(isTLS bool, env ...string) []string {
   290  	preserveList := []string{
   291  		// preserve remote test host
   292  		"DOCKER_HOST",
   293  
   294  		// windows: requires preserving SystemRoot, otherwise dial tcp fails
   295  		// with "GetAddrInfoW: A non-recoverable error occurred during a database lookup."
   296  		"SystemRoot",
   297  
   298  		// testing help text requires the $PATH to dockerd is set
   299  		"PATH",
   300  	}
   301  	if isTLS {
   302  		preserveList = append(preserveList, "DOCKER_TLS_VERIFY", "DOCKER_CERT_PATH")
   303  	}
   304  
   305  	for _, key := range preserveList {
   306  		if val := os.Getenv(key); val != "" {
   307  			env = append(env, fmt.Sprintf("%s=%s", key, val))
   308  		}
   309  	}
   310  	return env
   311  }
   312  
   313  func createTmpFile(c *check.C, content string) string {
   314  	f, err := ioutil.TempFile("", "testfile")
   315  	c.Assert(err, check.IsNil)
   316  
   317  	filename := f.Name()
   318  
   319  	err = ioutil.WriteFile(filename, []byte(content), 0644)
   320  	c.Assert(err, check.IsNil)
   321  
   322  	return filename
   323  }
   324  
   325  // waitRun will wait for the specified container to be running, maximum 5 seconds.
   326  // Deprecated: use cli.WaitFor
   327  func waitRun(contID string) error {
   328  	return waitInspect(contID, "{{.State.Running}}", "true", 5*time.Second)
   329  }
   330  
   331  // waitInspect will wait for the specified container to have the specified string
   332  // in the inspect output. It will wait until the specified timeout (in seconds)
   333  // is reached.
   334  // Deprecated: use cli.WaitFor
   335  func waitInspect(name, expr, expected string, timeout time.Duration) error {
   336  	return waitInspectWithArgs(name, expr, expected, timeout)
   337  }
   338  
   339  // Deprecated: use cli.WaitFor
   340  func waitInspectWithArgs(name, expr, expected string, timeout time.Duration, arg ...string) error {
   341  	return daemon.WaitInspectWithArgs(dockerBinary, name, expr, expected, timeout, arg...)
   342  }
   343  
   344  func getInspectBody(c *check.C, version, id string) []byte {
   345  	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithVersion(version))
   346  	c.Assert(err, check.IsNil)
   347  	defer cli.Close()
   348  	_, body, err := cli.ContainerInspectWithRaw(context.Background(), id, false)
   349  	c.Assert(err, check.IsNil)
   350  	return body
   351  }
   352  
   353  // Run a long running idle task in a background container using the
   354  // system-specific default image and command.
   355  func runSleepingContainer(c *check.C, extraArgs ...string) string {
   356  	return runSleepingContainerInImage(c, defaultSleepImage, extraArgs...)
   357  }
   358  
   359  // Run a long running idle task in a background container using the specified
   360  // image and the system-specific command.
   361  func runSleepingContainerInImage(c *check.C, image string, extraArgs ...string) string {
   362  	args := []string{"run", "-d"}
   363  	args = append(args, extraArgs...)
   364  	args = append(args, image)
   365  	args = append(args, sleepCommandForDaemonPlatform()...)
   366  	return strings.TrimSpace(cli.DockerCmd(c, args...).Combined())
   367  }
   368  
   369  // minimalBaseImage returns the name of the minimal base image for the current
   370  // daemon platform.
   371  func minimalBaseImage() string {
   372  	return testEnv.PlatformDefaults.BaseImage
   373  }
   374  
   375  func getGoroutineNumber() (int, error) {
   376  	cli, err := client.NewEnvClient()
   377  	if err != nil {
   378  		return 0, err
   379  	}
   380  	defer cli.Close()
   381  
   382  	info, err := cli.Info(context.Background())
   383  	if err != nil {
   384  		return 0, err
   385  	}
   386  	return info.NGoroutines, nil
   387  }
   388  
   389  func waitForGoroutines(expected int) error {
   390  	t := time.After(30 * time.Second)
   391  	for {
   392  		select {
   393  		case <-t:
   394  			n, err := getGoroutineNumber()
   395  			if err != nil {
   396  				return err
   397  			}
   398  			if n > expected {
   399  				return fmt.Errorf("leaked goroutines: expected less than or equal to %d, got: %d", expected, n)
   400  			}
   401  		default:
   402  			n, err := getGoroutineNumber()
   403  			if err != nil {
   404  				return err
   405  			}
   406  			if n <= expected {
   407  				return nil
   408  			}
   409  			time.Sleep(200 * time.Millisecond)
   410  		}
   411  	}
   412  }
   413  
   414  // getErrorMessage returns the error message from an error API response
   415  func getErrorMessage(c *check.C, body []byte) string {
   416  	var resp types.ErrorResponse
   417  	c.Assert(json.Unmarshal(body, &resp), check.IsNil)
   418  	return strings.TrimSpace(resp.Message)
   419  }
   420  
   421  func waitAndAssert(c *check.C, timeout time.Duration, f checkF, checker check.Checker, args ...interface{}) {
   422  	after := time.After(timeout)
   423  	for {
   424  		v, comment := f(c)
   425  		assert, _ := checker.Check(append([]interface{}{v}, args...), checker.Info().Params)
   426  		select {
   427  		case <-after:
   428  			assert = true
   429  		default:
   430  		}
   431  		if assert {
   432  			if comment != nil {
   433  				args = append(args, comment)
   434  			}
   435  			c.Assert(v, checker, args...)
   436  			return
   437  		}
   438  		time.Sleep(100 * time.Millisecond)
   439  	}
   440  }
   441  
   442  type checkF func(*check.C) (interface{}, check.CommentInterface)
   443  type reducer func(...interface{}) interface{}
   444  
   445  func reducedCheck(r reducer, funcs ...checkF) checkF {
   446  	return func(c *check.C) (interface{}, check.CommentInterface) {
   447  		var values []interface{}
   448  		var comments []string
   449  		for _, f := range funcs {
   450  			v, comment := f(c)
   451  			values = append(values, v)
   452  			if comment != nil {
   453  				comments = append(comments, comment.CheckCommentString())
   454  			}
   455  		}
   456  		return r(values...), check.Commentf("%v", strings.Join(comments, ", "))
   457  	}
   458  }
   459  
   460  func sumAsIntegers(vals ...interface{}) interface{} {
   461  	var s int
   462  	for _, v := range vals {
   463  		s += v.(int)
   464  	}
   465  	return s
   466  }