github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/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  	"net/http"
    10  	"os"
    11  	"path"
    12  	"path/filepath"
    13  	"strconv"
    14  	"strings"
    15  	"time"
    16  
    17  	"github.com/docker/docker/api/types"
    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/registry"
    22  	"github.com/docker/docker/integration-cli/request"
    23  	icmd "github.com/docker/docker/pkg/testutil/cmd"
    24  	"github.com/go-check/check"
    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  // Deprecated: use trustedcmd
   205  func trustedBuild(cmd *icmd.Cmd) func() {
   206  	trustedCmd(cmd)
   207  	return nil
   208  }
   209  
   210  // Write `content` to the file at path `dst`, creating it if necessary,
   211  // as well as any missing directories.
   212  // The file is truncated if it already exists.
   213  // Fail the test when error occurs.
   214  func writeFile(dst, content string, c *check.C) {
   215  	// Create subdirectories if necessary
   216  	c.Assert(os.MkdirAll(path.Dir(dst), 0700), check.IsNil)
   217  	f, err := os.OpenFile(dst, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0700)
   218  	c.Assert(err, check.IsNil)
   219  	defer f.Close()
   220  	// Write content (truncate if it exists)
   221  	_, err = io.Copy(f, strings.NewReader(content))
   222  	c.Assert(err, check.IsNil)
   223  }
   224  
   225  // Return the contents of file at path `src`.
   226  // Fail the test when error occurs.
   227  func readFile(src string, c *check.C) (content string) {
   228  	data, err := ioutil.ReadFile(src)
   229  	c.Assert(err, check.IsNil)
   230  
   231  	return string(data)
   232  }
   233  
   234  func containerStorageFile(containerID, basename string) string {
   235  	return filepath.Join(testEnv.ContainerStoragePath(), containerID, basename)
   236  }
   237  
   238  // docker commands that use this function must be run with the '-d' switch.
   239  func runCommandAndReadContainerFile(c *check.C, filename string, command string, args ...string) []byte {
   240  	result := icmd.RunCommand(command, args...)
   241  	result.Assert(c, icmd.Success)
   242  	contID := strings.TrimSpace(result.Combined())
   243  	if err := waitRun(contID); err != nil {
   244  		c.Fatalf("%v: %q", contID, err)
   245  	}
   246  	return readContainerFile(c, contID, filename)
   247  }
   248  
   249  func readContainerFile(c *check.C, containerID, filename string) []byte {
   250  	f, err := os.Open(containerStorageFile(containerID, filename))
   251  	c.Assert(err, checker.IsNil)
   252  	defer f.Close()
   253  
   254  	content, err := ioutil.ReadAll(f)
   255  	c.Assert(err, checker.IsNil)
   256  	return content
   257  }
   258  
   259  func readContainerFileWithExec(c *check.C, containerID, filename string) []byte {
   260  	result := icmd.RunCommand(dockerBinary, "exec", containerID, "cat", filename)
   261  	result.Assert(c, icmd.Success)
   262  	return []byte(result.Combined())
   263  }
   264  
   265  // daemonTime provides the current time on the daemon host
   266  func daemonTime(c *check.C) time.Time {
   267  	if testEnv.LocalDaemon() {
   268  		return time.Now()
   269  	}
   270  
   271  	status, body, err := request.SockRequest("GET", "/info", nil, daemonHost())
   272  	c.Assert(err, check.IsNil)
   273  	c.Assert(status, check.Equals, http.StatusOK)
   274  
   275  	type infoJSON struct {
   276  		SystemTime string
   277  	}
   278  	var info infoJSON
   279  	err = json.Unmarshal(body, &info)
   280  	c.Assert(err, check.IsNil, check.Commentf("unable to unmarshal GET /info response"))
   281  
   282  	dt, err := time.Parse(time.RFC3339Nano, info.SystemTime)
   283  	c.Assert(err, check.IsNil, check.Commentf("invalid time format in GET /info response"))
   284  	return dt
   285  }
   286  
   287  // daemonUnixTime returns the current time on the daemon host with nanoseconds precision.
   288  // It return the time formatted how the client sends timestamps to the server.
   289  func daemonUnixTime(c *check.C) string {
   290  	return parseEventTime(daemonTime(c))
   291  }
   292  
   293  func parseEventTime(t time.Time) string {
   294  	return fmt.Sprintf("%d.%09d", t.Unix(), int64(t.Nanosecond()))
   295  }
   296  
   297  func setupRegistry(c *check.C, schema1 bool, auth, tokenURL string) *registry.V2 {
   298  	reg, err := registry.NewV2(schema1, auth, tokenURL, privateRegistryURL)
   299  	c.Assert(err, check.IsNil)
   300  
   301  	// Wait for registry to be ready to serve requests.
   302  	for i := 0; i != 50; i++ {
   303  		if err = reg.Ping(); err == nil {
   304  			break
   305  		}
   306  		time.Sleep(100 * time.Millisecond)
   307  	}
   308  
   309  	c.Assert(err, check.IsNil, check.Commentf("Timeout waiting for test registry to become available: %v", err))
   310  	return reg
   311  }
   312  
   313  func setupNotary(c *check.C) *testNotary {
   314  	ts, err := newTestNotary(c)
   315  	c.Assert(err, check.IsNil)
   316  
   317  	return ts
   318  }
   319  
   320  // appendBaseEnv appends the minimum set of environment variables to exec the
   321  // docker cli binary for testing with correct configuration to the given env
   322  // list.
   323  func appendBaseEnv(isTLS bool, env ...string) []string {
   324  	preserveList := []string{
   325  		// preserve remote test host
   326  		"DOCKER_HOST",
   327  
   328  		// windows: requires preserving SystemRoot, otherwise dial tcp fails
   329  		// with "GetAddrInfoW: A non-recoverable error occurred during a database lookup."
   330  		"SystemRoot",
   331  
   332  		// testing help text requires the $PATH to dockerd is set
   333  		"PATH",
   334  	}
   335  	if isTLS {
   336  		preserveList = append(preserveList, "DOCKER_TLS_VERIFY", "DOCKER_CERT_PATH")
   337  	}
   338  
   339  	for _, key := range preserveList {
   340  		if val := os.Getenv(key); val != "" {
   341  			env = append(env, fmt.Sprintf("%s=%s", key, val))
   342  		}
   343  	}
   344  	return env
   345  }
   346  
   347  func createTmpFile(c *check.C, content string) string {
   348  	f, err := ioutil.TempFile("", "testfile")
   349  	c.Assert(err, check.IsNil)
   350  
   351  	filename := f.Name()
   352  
   353  	err = ioutil.WriteFile(filename, []byte(content), 0644)
   354  	c.Assert(err, check.IsNil)
   355  
   356  	return filename
   357  }
   358  
   359  // waitRun will wait for the specified container to be running, maximum 5 seconds.
   360  // Deprecated: use cli.WaitFor
   361  func waitRun(contID string) error {
   362  	return waitInspect(contID, "{{.State.Running}}", "true", 5*time.Second)
   363  }
   364  
   365  // waitInspect will wait for the specified container to have the specified string
   366  // in the inspect output. It will wait until the specified timeout (in seconds)
   367  // is reached.
   368  // Deprecated: use cli.WaitFor
   369  func waitInspect(name, expr, expected string, timeout time.Duration) error {
   370  	return waitInspectWithArgs(name, expr, expected, timeout)
   371  }
   372  
   373  // Deprecated: use cli.WaitFor
   374  func waitInspectWithArgs(name, expr, expected string, timeout time.Duration, arg ...string) error {
   375  	return daemon.WaitInspectWithArgs(dockerBinary, name, expr, expected, timeout, arg...)
   376  }
   377  
   378  func getInspectBody(c *check.C, version, id string) []byte {
   379  	endpoint := fmt.Sprintf("/%s/containers/%s/json", version, id)
   380  	status, body, err := request.SockRequest("GET", endpoint, nil, daemonHost())
   381  	c.Assert(err, check.IsNil)
   382  	c.Assert(status, check.Equals, http.StatusOK)
   383  	return body
   384  }
   385  
   386  // Run a long running idle task in a background container using the
   387  // system-specific default image and command.
   388  func runSleepingContainer(c *check.C, extraArgs ...string) string {
   389  	return runSleepingContainerInImage(c, defaultSleepImage, extraArgs...)
   390  }
   391  
   392  // Run a long running idle task in a background container using the specified
   393  // image and the system-specific command.
   394  func runSleepingContainerInImage(c *check.C, image string, extraArgs ...string) string {
   395  	args := []string{"run", "-d"}
   396  	args = append(args, extraArgs...)
   397  	args = append(args, image)
   398  	args = append(args, sleepCommandForDaemonPlatform()...)
   399  	return cli.DockerCmd(c, args...).Combined()
   400  }
   401  
   402  // minimalBaseImage returns the name of the minimal base image for the current
   403  // daemon platform.
   404  func minimalBaseImage() string {
   405  	return testEnv.MinimalBaseImage()
   406  }
   407  
   408  func getGoroutineNumber() (int, error) {
   409  	i := struct {
   410  		NGoroutines int
   411  	}{}
   412  	status, b, err := request.SockRequest("GET", "/info", nil, daemonHost())
   413  	if err != nil {
   414  		return 0, err
   415  	}
   416  	if status != http.StatusOK {
   417  		return 0, fmt.Errorf("http status code: %d", status)
   418  	}
   419  	if err := json.Unmarshal(b, &i); err != nil {
   420  		return 0, err
   421  	}
   422  	return i.NGoroutines, nil
   423  }
   424  
   425  func waitForGoroutines(expected int) error {
   426  	t := time.After(30 * time.Second)
   427  	for {
   428  		select {
   429  		case <-t:
   430  			n, err := getGoroutineNumber()
   431  			if err != nil {
   432  				return err
   433  			}
   434  			if n > expected {
   435  				return fmt.Errorf("leaked goroutines: expected less than or equal to %d, got: %d", expected, n)
   436  			}
   437  		default:
   438  			n, err := getGoroutineNumber()
   439  			if err != nil {
   440  				return err
   441  			}
   442  			if n <= expected {
   443  				return nil
   444  			}
   445  			time.Sleep(200 * time.Millisecond)
   446  		}
   447  	}
   448  }
   449  
   450  // getErrorMessage returns the error message from an error API response
   451  func getErrorMessage(c *check.C, body []byte) string {
   452  	var resp types.ErrorResponse
   453  	c.Assert(json.Unmarshal(body, &resp), check.IsNil)
   454  	return strings.TrimSpace(resp.Message)
   455  }
   456  
   457  func waitAndAssert(c *check.C, timeout time.Duration, f checkF, checker check.Checker, args ...interface{}) {
   458  	after := time.After(timeout)
   459  	for {
   460  		v, comment := f(c)
   461  		assert, _ := checker.Check(append([]interface{}{v}, args...), checker.Info().Params)
   462  		select {
   463  		case <-after:
   464  			assert = true
   465  		default:
   466  		}
   467  		if assert {
   468  			if comment != nil {
   469  				args = append(args, comment)
   470  			}
   471  			c.Assert(v, checker, args...)
   472  			return
   473  		}
   474  		time.Sleep(100 * time.Millisecond)
   475  	}
   476  }
   477  
   478  type checkF func(*check.C) (interface{}, check.CommentInterface)
   479  type reducer func(...interface{}) interface{}
   480  
   481  func reducedCheck(r reducer, funcs ...checkF) checkF {
   482  	return func(c *check.C) (interface{}, check.CommentInterface) {
   483  		var values []interface{}
   484  		var comments []string
   485  		for _, f := range funcs {
   486  			v, comment := f(c)
   487  			values = append(values, v)
   488  			if comment != nil {
   489  				comments = append(comments, comment.CheckCommentString())
   490  			}
   491  		}
   492  		return r(values...), check.Commentf("%v", strings.Join(comments, ", "))
   493  	}
   494  }
   495  
   496  func sumAsIntegers(vals ...interface{}) interface{} {
   497  	var s int
   498  	for _, v := range vals {
   499  		s += v.(int)
   500  	}
   501  	return s
   502  }