浏览代码

Introduce a `cli` package for test-integration

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
Vincent Demeester 8 年之前
父节点
当前提交
50c4475df6
共有 33 个文件被更改,包括 446 次插入288 次删除
  1. 3 9
      integration-cli/check_test.go
  2. 31 0
      integration-cli/cli/build/build.go
  3. 129 0
      integration-cli/cli/cli.go
  4. 2 1
      integration-cli/docker_api_containers_test.go
  5. 6 4
      integration-cli/docker_api_images_test.go
  6. 125 125
      integration-cli/docker_cli_build_test.go
  7. 3 2
      integration-cli/docker_cli_by_digest_test.go
  8. 5 4
      integration-cli/docker_cli_commit_test.go
  9. 3 2
      integration-cli/docker_cli_create_test.go
  10. 11 11
      integration-cli/docker_cli_daemon_test.go
  11. 4 3
      integration-cli/docker_cli_events_test.go
  12. 3 2
      integration-cli/docker_cli_events_unix_test.go
  13. 2 1
      integration-cli/docker_cli_exec_test.go
  14. 5 8
      integration-cli/docker_cli_health_test.go
  15. 2 1
      integration-cli/docker_cli_history_test.go
  16. 14 13
      integration-cli/docker_cli_images_test.go
  17. 0 10
      integration-cli/docker_cli_nat_test.go
  18. 4 3
      integration-cli/docker_cli_ps_test.go
  19. 5 4
      integration-cli/docker_cli_pull_local_test.go
  20. 2 1
      integration-cli/docker_cli_pull_trusted_test.go
  21. 2 1
      integration-cli/docker_cli_push_test.go
  22. 3 2
      integration-cli/docker_cli_rm_test.go
  23. 6 5
      integration-cli/docker_cli_rmi_test.go
  24. 11 10
      integration-cli/docker_cli_run_test.go
  25. 2 1
      integration-cli/docker_cli_run_unix_test.go
  26. 3 2
      integration-cli/docker_cli_save_load_test.go
  27. 2 1
      integration-cli/docker_cli_save_load_unix_test.go
  28. 7 10
      integration-cli/docker_cli_swarm_test.go
  29. 2 1
      integration-cli/docker_cli_tag_test.go
  30. 4 3
      integration-cli/docker_cli_volume_test.go
  31. 8 45
      integration-cli/docker_utils_test.go
  32. 34 1
      integration-cli/environment/environment.go
  33. 3 2
      pkg/testutil/cmd/command.go

+ 3 - 9
integration-cli/check_test.go

@@ -13,6 +13,7 @@ import (
 
 	"github.com/docker/docker/api/types/swarm"
 	cliconfig "github.com/docker/docker/cli/config"
+	"github.com/docker/docker/integration-cli/cli"
 	"github.com/docker/docker/integration-cli/daemon"
 	"github.com/docker/docker/integration-cli/environment"
 	"github.com/docker/docker/integration-cli/registry"
@@ -51,15 +52,7 @@ func init() {
 }
 
 func TestMain(m *testing.M) {
-	var err error
-	if dockerBin := os.Getenv("DOCKER_BINARY"); dockerBin != "" {
-		dockerBinary = dockerBin
-	}
-	dockerBinary, err = exec.LookPath(dockerBinary)
-	if err != nil {
-		fmt.Printf("ERROR: couldn't resolve full path to the Docker binary (%v)\n", err)
-		os.Exit(1)
-	}
+	dockerBinary = testEnv.DockerBinary()
 
 	if testEnv.LocalDaemon() {
 		fmt.Println("INFO: Testing against a local daemon")
@@ -71,6 +64,7 @@ func TestMain(m *testing.M) {
 }
 
 func Test(t *testing.T) {
+	cli.EnsureTestEnvIsLoaded(t)
 	cmd := exec.Command(dockerBinary, "images", "-f", "dangling=false", "--format", "{{.Repository}}:{{.Tag}}")
 	cmd.Env = appendBaseEnv(true)
 	out, err := cmd.CombinedOutput()

+ 31 - 0
integration-cli/cli/build/build.go

@@ -0,0 +1,31 @@
+package build
+
+import (
+	"strings"
+
+	icmd "github.com/docker/docker/pkg/testutil/cmd"
+)
+
+// WithDockerfile creates / returns a CmdOperator to set the Dockerfile for a build operation
+func WithDockerfile(dockerfile string) func(*icmd.Cmd) func() {
+	return func(cmd *icmd.Cmd) func() {
+		cmd.Command = append(cmd.Command, "-")
+		cmd.Stdin = strings.NewReader(dockerfile)
+		return nil
+	}
+}
+
+// WithoutCache makes the build ignore cache
+func WithoutCache(cmd *icmd.Cmd) func() {
+	cmd.Command = append(cmd.Command, "--no-cache")
+	return nil
+}
+
+// WithContextPath set the build context path
+func WithContextPath(path string) func(*icmd.Cmd) func() {
+	// WithContextPath sets the build context path
+	return func(cmd *icmd.Cmd) func() {
+		cmd.Command = append(cmd.Command, path)
+		return nil
+	}
+}

+ 129 - 0
integration-cli/cli/cli.go

@@ -0,0 +1,129 @@
+package cli
+
+import (
+	"fmt"
+	"sync"
+	"time"
+
+	"github.com/docker/docker/integration-cli/daemon"
+	"github.com/docker/docker/integration-cli/environment"
+	icmd "github.com/docker/docker/pkg/testutil/cmd"
+)
+
+var (
+	testEnv  *environment.Execution
+	onlyOnce sync.Once
+)
+
+// EnsureTestEnvIsLoaded make sure the test environment is loaded for this package
+func EnsureTestEnvIsLoaded(t testingT) {
+	var doIt bool
+	var err error
+	onlyOnce.Do(func() {
+		doIt = true
+	})
+
+	if !doIt {
+		return
+	}
+	testEnv, err = environment.New()
+	if err != nil {
+		t.Fatalf("error loading testenv : %v", err)
+	}
+}
+
+// CmdOperator defines functions that can modify a command
+type CmdOperator func(*icmd.Cmd) func()
+
+type testingT interface {
+	Fatalf(string, ...interface{})
+}
+
+// DockerCmd executes the specified docker command and expect a success
+func DockerCmd(t testingT, command string, args ...string) *icmd.Result {
+	return Docker(Cmd(command, args...)).Assert(t, icmd.Success)
+}
+
+// BuildCmd executes the specified docker build command and expect a success
+func BuildCmd(t testingT, name string, cmdOperators ...CmdOperator) *icmd.Result {
+	return Docker(Build(name), cmdOperators...).Assert(t, icmd.Success)
+}
+
+// InspectCmd executes the specified docker inspect command and expect a success
+func InspectCmd(t testingT, name string, cmdOperators ...CmdOperator) *icmd.Result {
+	return Docker(Inspect(name), cmdOperators...).Assert(t, icmd.Success)
+}
+
+// Docker executes the specified docker command
+func Docker(cmd icmd.Cmd, cmdOperators ...CmdOperator) *icmd.Result {
+	for _, op := range cmdOperators {
+		deferFn := op(&cmd)
+		if deferFn != nil {
+			defer deferFn()
+		}
+	}
+	appendDocker(&cmd)
+	return icmd.RunCmd(cmd)
+}
+
+// Build executes the specified docker build command
+func Build(name string) icmd.Cmd {
+	return icmd.Command("build", "-t", name)
+}
+
+// Inspect executes the specified docker inspect command
+func Inspect(name string) icmd.Cmd {
+	return icmd.Command("inspect", name)
+}
+
+// Format sets the specified format with --format flag
+func Format(format string) func(*icmd.Cmd) func() {
+	return func(cmd *icmd.Cmd) func() {
+		cmd.Command = append(
+			[]string{cmd.Command[0]},
+			append([]string{"--format", fmt.Sprintf("{{%s}}", format)}, cmd.Command[1:]...)...,
+		)
+		return nil
+	}
+}
+
+func appendDocker(cmd *icmd.Cmd) {
+	cmd.Command = append([]string{testEnv.DockerBinary()}, cmd.Command...)
+}
+
+// Cmd build an icmd.Cmd struct from the specified command and arguments
+func Cmd(command string, args ...string) icmd.Cmd {
+	return icmd.Command(command, args...)
+}
+
+// Daemon points to the specified daemon
+func Daemon(d *daemon.Daemon) func(*icmd.Cmd) func() {
+	return func(cmd *icmd.Cmd) func() {
+		cmd.Command = append([]string{"--host", d.Sock()}, cmd.Command...)
+		return nil
+	}
+}
+
+// WithTimeout sets the timeout for the command to run
+func WithTimeout(timeout time.Duration) func(cmd *icmd.Cmd) func() {
+	return func(cmd *icmd.Cmd) func() {
+		cmd.Timeout = timeout
+		return nil
+	}
+}
+
+// WithEnvironmentVariables sets the specified environment variables for the command to run
+func WithEnvironmentVariables(envs ...string) func(cmd *icmd.Cmd) func() {
+	return func(cmd *icmd.Cmd) func() {
+		cmd.Env = envs
+		return nil
+	}
+}
+
+// WithFlags sets the specified flags for the command to run
+func WithFlags(flags ...string) func(*icmd.Cmd) func() {
+	return func(cmd *icmd.Cmd) func() {
+		cmd.Command = append(cmd.Command, flags...)
+		return nil
+	}
+}

+ 2 - 1
integration-cli/docker_api_containers_test.go

@@ -21,6 +21,7 @@ import (
 	mounttypes "github.com/docker/docker/api/types/mount"
 	networktypes "github.com/docker/docker/api/types/network"
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli/build"
 	"github.com/docker/docker/integration-cli/request"
 	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/docker/pkg/mount"
@@ -1768,7 +1769,7 @@ func (s *DockerSuite) TestContainersAPICreateMountsCreate(c *check.C) {
 	)
 	if testEnv.DaemonPlatform() != "windows" {
 		testImg = "test-mount-config"
-		buildImageSuccessfully(c, testImg, withDockerfile(`
+		buildImageSuccessfully(c, testImg, build.WithDockerfile(`
 	FROM busybox
 	RUN mkdir `+destPath+` && touch `+destPath+slash+`bar
 	CMD cat `+destPath+slash+`bar

+ 6 - 4
integration-cli/docker_api_images_test.go

@@ -9,6 +9,8 @@ import (
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/image"
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli"
+	"github.com/docker/docker/integration-cli/cli/build"
 	"github.com/docker/docker/integration-cli/request"
 	"github.com/go-check/check"
 )
@@ -53,7 +55,7 @@ func (s *DockerSuite) TestAPIImagesSaveAndLoad(c *check.C) {
 	// TODO Windows to Windows CI: Investigate further why this test fails.
 	testRequires(c, Network)
 	testRequires(c, DaemonIsLinux)
-	buildImageSuccessfully(c, "saveandload", withDockerfile("FROM busybox\nENV FOO bar"))
+	buildImageSuccessfully(c, "saveandload", build.WithDockerfile("FROM busybox\nENV FOO bar"))
 	id := getIDByName(c, "saveandload")
 
 	res, body, err := request.Get("/images/" + id + "/get")
@@ -68,7 +70,7 @@ func (s *DockerSuite) TestAPIImagesSaveAndLoad(c *check.C) {
 	defer loadBody.Close()
 	c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
 
-	inspectOut := inspectField(c, id, "Id")
+	inspectOut := cli.InspectCmd(c, id, cli.Format(".Id")).Combined()
 	c.Assert(strings.TrimSpace(string(inspectOut)), checker.Equals, id, check.Commentf("load did not work properly"))
 }
 
@@ -77,7 +79,7 @@ func (s *DockerSuite) TestAPIImagesDelete(c *check.C) {
 		testRequires(c, Network)
 	}
 	name := "test-api-images-delete"
-	buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nENV FOO bar"))
+	buildImageSuccessfully(c, name, build.WithDockerfile("FROM busybox\nENV FOO bar"))
 	id := getIDByName(c, name)
 
 	dockerCmd(c, "tag", name, "test:tag1")
@@ -100,7 +102,7 @@ func (s *DockerSuite) TestAPIImagesHistory(c *check.C) {
 		testRequires(c, Network)
 	}
 	name := "test-api-images-history"
-	buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nENV FOO bar"))
+	buildImageSuccessfully(c, name, build.WithDockerfile("FROM busybox\nENV FOO bar"))
 	id := getIDByName(c, name)
 
 	status, body, err := request.SockRequest("GET", "/images/"+id+"/history", nil, daemonHost())

文件差异内容过多而无法显示
+ 125 - 125
integration-cli/docker_cli_build_test.go


+ 3 - 2
integration-cli/docker_cli_by_digest_test.go

@@ -12,6 +12,7 @@ import (
 	"github.com/docker/distribution/manifest/schema2"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli/build"
 	"github.com/docker/docker/pkg/stringutils"
 	"github.com/go-check/check"
 	"github.com/opencontainers/go-digest"
@@ -196,7 +197,7 @@ func (s *DockerRegistrySuite) TestBuildByDigest(c *check.C) {
 
 	// do the build
 	name := "buildbydigest"
-	buildImageSuccessfully(c, name, withDockerfile(fmt.Sprintf(
+	buildImageSuccessfully(c, name, build.WithDockerfile(fmt.Sprintf(
 		`FROM %s
      CMD ["/bin/echo", "Hello World"]`, imageReference)))
 	c.Assert(err, checker.IsNil)
@@ -419,7 +420,7 @@ func (s *DockerRegistrySuite) TestPsListContainersFilterAncestorImageByDigest(c
 
 	// build an image from it
 	imageName1 := "images_ps_filter_test"
-	buildImageSuccessfully(c, imageName1, withDockerfile(fmt.Sprintf(
+	buildImageSuccessfully(c, imageName1, build.WithDockerfile(fmt.Sprintf(
 		`FROM %s
 		 LABEL match me 1`, imageReference)))
 

+ 5 - 4
integration-cli/docker_cli_commit_test.go

@@ -4,21 +4,22 @@ import (
 	"strings"
 
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli"
 	"github.com/go-check/check"
 )
 
 func (s *DockerSuite) TestCommitAfterContainerIsDone(c *check.C) {
-	out, _ := dockerCmd(c, "run", "-i", "-a", "stdin", "busybox", "echo", "foo")
+	out := cli.DockerCmd(c, "run", "-i", "-a", "stdin", "busybox", "echo", "foo").Combined()
 
 	cleanedContainerID := strings.TrimSpace(out)
 
-	dockerCmd(c, "wait", cleanedContainerID)
+	cli.DockerCmd(c, "wait", cleanedContainerID)
 
-	out, _ = dockerCmd(c, "commit", cleanedContainerID)
+	out = cli.DockerCmd(c, "commit", cleanedContainerID).Combined()
 
 	cleanedImageID := strings.TrimSpace(out)
 
-	dockerCmd(c, "inspect", cleanedImageID)
+	cli.DockerCmd(c, "inspect", cleanedImageID)
 }
 
 func (s *DockerSuite) TestCommitWithoutPause(c *check.C) {

+ 3 - 2
integration-cli/docker_cli_create_test.go

@@ -10,6 +10,7 @@ import (
 	"time"
 
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli/build"
 	"github.com/docker/docker/pkg/stringid"
 	"github.com/docker/docker/pkg/testutil"
 	icmd "github.com/docker/docker/pkg/testutil/cmd"
@@ -204,7 +205,7 @@ func (s *DockerSuite) TestCreateLabels(c *check.C) {
 
 func (s *DockerSuite) TestCreateLabelFromImage(c *check.C) {
 	imageName := "testcreatebuildlabel"
-	buildImageSuccessfully(c, imageName, withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, imageName, build.WithDockerfile(`FROM busybox
 		LABEL k1=v1 k2=v2`))
 
 	name := "test_create_labels_from_image"
@@ -259,7 +260,7 @@ func (s *DockerSuite) TestCreateModeIpcContainer(c *check.C) {
 
 func (s *DockerSuite) TestCreateByImageID(c *check.C) {
 	imageName := "testcreatebyimageid"
-	buildImageSuccessfully(c, imageName, withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, imageName, build.WithDockerfile(`FROM busybox
 		MAINTAINER dockerio`))
 	imageID := getIDByName(c, imageName)
 	truncatedImageID := stringid.TruncateID(imageID)

+ 11 - 11
integration-cli/docker_cli_daemon_test.go

@@ -22,6 +22,7 @@ import (
 	"time"
 
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli"
 	"github.com/docker/docker/integration-cli/daemon"
 	"github.com/docker/docker/pkg/mount"
 	"github.com/docker/docker/pkg/stringid"
@@ -47,21 +48,20 @@ func (s *DockerDaemonSuite) TestLegacyDaemonCommand(c *check.C) {
 func (s *DockerDaemonSuite) TestDaemonRestartWithRunningContainersPorts(c *check.C) {
 	s.d.StartWithBusybox(c)
 
-	if out, err := s.d.Cmd("run", "-d", "--name", "top1", "-p", "1234:80", "--restart", "always", "busybox:latest", "top"); err != nil {
-		c.Fatalf("Could not run top1: err=%v\n%s", err, out)
-	}
-	// --restart=no by default
-	if out, err := s.d.Cmd("run", "-d", "--name", "top2", "-p", "80", "busybox:latest", "top"); err != nil {
-		c.Fatalf("Could not run top2: err=%v\n%s", err, out)
-	}
+	cli.Docker(
+		cli.Cmd("run", "-d", "--name", "top1", "-p", "1234:80", "--restart", "always", "busybox:latest", "top"),
+		cli.Daemon(s.d),
+	).Assert(c, icmd.Success)
+
+	cli.Docker(
+		cli.Cmd("run", "-d", "--name", "top2", "-p", "80", "busybox:latest", "top"),
+		cli.Daemon(s.d),
+	).Assert(c, icmd.Success)
 
 	testRun := func(m map[string]bool, prefix string) {
 		var format string
 		for cont, shouldRun := range m {
-			out, err := s.d.Cmd("ps")
-			if err != nil {
-				c.Fatalf("Could not run ps: err=%v\n%q", err, out)
-			}
+			out := cli.Docker(cli.Cmd("ps"), cli.Daemon(s.d)).Assert(c, icmd.Success).Combined()
 			if shouldRun {
 				format = "%scontainer %q is not running"
 			} else {

+ 4 - 3
integration-cli/docker_cli_events_test.go

@@ -15,6 +15,7 @@ import (
 	eventtypes "github.com/docker/docker/api/types/events"
 	eventstestutils "github.com/docker/docker/daemon/events/testutils"
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli/build"
 	"github.com/docker/docker/integration-cli/request"
 	"github.com/docker/docker/pkg/testutil"
 	icmd "github.com/docker/docker/pkg/testutil/cmd"
@@ -384,7 +385,7 @@ func (s *DockerSuite) TestEventsFilterImageLabels(c *check.C) {
 	label := "io.docker.testing=image"
 
 	// Build a test image.
-	buildImageSuccessfully(c, name, withDockerfile(fmt.Sprintf(`
+	buildImageSuccessfully(c, name, build.WithDockerfile(fmt.Sprintf(`
 		FROM busybox:latest
 		LABEL %s`, label)))
 	dockerCmd(c, "tag", name, "labelfiltertest:tag1")
@@ -465,7 +466,7 @@ func (s *DockerSuite) TestEventsCommit(c *check.C) {
 
 func (s *DockerSuite) TestEventsCopy(c *check.C) {
 	// Build a test image.
-	buildImageSuccessfully(c, "cpimg", withDockerfile(`
+	buildImageSuccessfully(c, "cpimg", build.WithDockerfile(`
 		  FROM busybox
 		  RUN echo HI > /file`))
 	id := getIDByName(c, "cpimg")
@@ -598,7 +599,7 @@ func (s *DockerSuite) TestEventsFilterType(c *check.C) {
 	label := "io.docker.testing=image"
 
 	// Build a test image.
-	buildImageSuccessfully(c, name, withDockerfile(fmt.Sprintf(`
+	buildImageSuccessfully(c, name, build.WithDockerfile(fmt.Sprintf(`
 		FROM busybox:latest
 		LABEL %s`, label)))
 	dockerCmd(c, "tag", name, "labelfiltertest:tag1")

+ 3 - 2
integration-cli/docker_cli_events_unix_test.go

@@ -15,6 +15,7 @@ import (
 	"unicode"
 
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli/build"
 	"github.com/go-check/check"
 	"github.com/kr/pty"
 )
@@ -111,7 +112,7 @@ func (s *DockerSuite) TestEventsOOMDisableTrue(c *check.C) {
 	case <-time.After(20 * time.Second):
 		observer.CheckEventError(c, containerID, "oom", matcher)
 	case <-testActions["oom"]:
-		// ignore, done
+	// ignore, done
 	case errRun := <-errChan:
 		if errRun != nil {
 			c.Fatalf("%v", errRun)
@@ -310,7 +311,7 @@ func (s *DockerSuite) TestEventsImageUntagDelete(c *check.C) {
 	defer observer.Stop()
 
 	name := "testimageevents"
-	buildImageSuccessfully(c, name, withDockerfile(`FROM scratch
+	buildImageSuccessfully(c, name, build.WithDockerfile(`FROM scratch
 		MAINTAINER "docker"`))
 	imageID := getIDByName(c, name)
 	c.Assert(deleteImages(name), checker.IsNil)

+ 2 - 1
integration-cli/docker_cli_exec_test.go

@@ -16,6 +16,7 @@ import (
 	"time"
 
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli/build"
 	"github.com/docker/docker/integration-cli/request"
 	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/go-check/check"
@@ -470,7 +471,7 @@ func (s *DockerSuite) TestExecWithImageUser(c *check.C) {
 	// Not applicable on Windows
 	testRequires(c, DaemonIsLinux)
 	name := "testbuilduser"
-	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, name, build.WithDockerfile(`FROM busybox
 		RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
 		USER dockerio`))
 	dockerCmd(c, "run", "-d", "--name", "dockerioexec", name, "top")

+ 5 - 8
integration-cli/docker_cli_health_test.go

@@ -2,13 +2,13 @@ package main
 
 import (
 	"encoding/json"
-
 	"strconv"
 	"strings"
 	"time"
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli/build"
 	"github.com/go-check/check"
 )
 
@@ -40,7 +40,7 @@ func (s *DockerSuite) TestHealth(c *check.C) {
 	testRequires(c, DaemonIsLinux) // busybox doesn't work on Windows
 
 	imageName := "testhealth"
-	buildImageSuccessfully(c, imageName, withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, imageName, build.WithDockerfile(`FROM busybox
 		RUN echo OK > /status
 		CMD ["/bin/sleep", "120"]
 		STOPSIGNAL SIGKILL
@@ -55,10 +55,7 @@ func (s *DockerSuite) TestHealth(c *check.C) {
 
 	// Inspect the options
 	out, _ = dockerCmd(c, "inspect",
-		"--format=timeout={{.Config.Healthcheck.Timeout}} "+
-			"interval={{.Config.Healthcheck.Interval}} "+
-			"retries={{.Config.Healthcheck.Retries}} "+
-			"test={{.Config.Healthcheck.Test}}", name)
+		"--format=timeout={{.Config.Healthcheck.Timeout}} interval={{.Config.Healthcheck.Interval}} retries={{.Config.Healthcheck.Retries}} test={{.Config.Healthcheck.Test}}", name)
 	c.Check(out, checker.Equals, "timeout=30s interval=1s retries=0 test=[CMD-SHELL cat /status]\n")
 
 	// Start
@@ -87,7 +84,7 @@ func (s *DockerSuite) TestHealth(c *check.C) {
 	dockerCmd(c, "rm", "noh")
 
 	// Disable the check with a new build
-	buildImageSuccessfully(c, "no_healthcheck", withDockerfile(`FROM testhealth
+	buildImageSuccessfully(c, "no_healthcheck", build.WithDockerfile(`FROM testhealth
 		HEALTHCHECK NONE`))
 
 	out, _ = dockerCmd(c, "inspect", "--format={{.ContainerConfig.Healthcheck.Test}}", "no_healthcheck")
@@ -131,7 +128,7 @@ func (s *DockerSuite) TestHealth(c *check.C) {
 	dockerCmd(c, "rm", "-f", "test")
 
 	// Check JSON-format
-	buildImageSuccessfully(c, imageName, withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, imageName, build.WithDockerfile(`FROM busybox
 		RUN echo OK > /status
 		CMD ["/bin/sleep", "120"]
 		STOPSIGNAL SIGKILL

+ 2 - 1
integration-cli/docker_cli_history_test.go

@@ -7,6 +7,7 @@ import (
 	"strings"
 
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli/build"
 	"github.com/go-check/check"
 )
 
@@ -14,7 +15,7 @@ import (
 // sort is not predictable it doesn't always fail.
 func (s *DockerSuite) TestBuildHistory(c *check.C) {
 	name := "testbuildhistory"
-	buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+`
+	buildImageSuccessfully(c, name, build.WithDockerfile(`FROM `+minimalBaseImage()+`
 LABEL label.A="A"
 LABEL label.B="B"
 LABEL label.C="C"

+ 14 - 13
integration-cli/docker_cli_images_test.go

@@ -11,6 +11,7 @@ import (
 	"time"
 
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli/build"
 	"github.com/docker/docker/pkg/stringid"
 	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/go-check/check"
@@ -46,15 +47,15 @@ func (s *DockerSuite) TestImagesEnsureImageWithBadTagIsNotListed(c *check.C) {
 }
 
 func (s *DockerSuite) TestImagesOrderedByCreationDate(c *check.C) {
-	buildImageSuccessfully(c, "order:test_a", withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, "order:test_a", build.WithDockerfile(`FROM busybox
                 MAINTAINER dockerio1`))
 	id1 := getIDByName(c, "order:test_a")
 	time.Sleep(1 * time.Second)
-	buildImageSuccessfully(c, "order:test_c", withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, "order:test_c", build.WithDockerfile(`FROM busybox
                 MAINTAINER dockerio2`))
 	id2 := getIDByName(c, "order:test_c")
 	time.Sleep(1 * time.Second)
-	buildImageSuccessfully(c, "order:test_b", withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, "order:test_b", build.WithDockerfile(`FROM busybox
                 MAINTAINER dockerio3`))
 	id3 := getIDByName(c, "order:test_b")
 
@@ -75,15 +76,15 @@ func (s *DockerSuite) TestImagesFilterLabelMatch(c *check.C) {
 	imageName1 := "images_filter_test1"
 	imageName2 := "images_filter_test2"
 	imageName3 := "images_filter_test3"
-	buildImageSuccessfully(c, imageName1, withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, imageName1, build.WithDockerfile(`FROM busybox
                  LABEL match me`))
 	image1ID := getIDByName(c, imageName1)
 
-	buildImageSuccessfully(c, imageName2, withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, imageName2, build.WithDockerfile(`FROM busybox
                  LABEL match="me too"`))
 	image2ID := getIDByName(c, imageName2)
 
-	buildImageSuccessfully(c, imageName3, withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, imageName3, build.WithDockerfile(`FROM busybox
                  LABEL nomatch me`))
 	image3ID := getIDByName(c, imageName3)
 
@@ -112,13 +113,13 @@ func (s *DockerSuite) TestImagesFilterLabelWithCommit(c *check.C) {
 }
 
 func (s *DockerSuite) TestImagesFilterSinceAndBefore(c *check.C) {
-	buildImageSuccessfully(c, "image:1", withDockerfile(`FROM `+minimalBaseImage()+`
+	buildImageSuccessfully(c, "image:1", build.WithDockerfile(`FROM `+minimalBaseImage()+`
 LABEL number=1`))
 	imageID1 := getIDByName(c, "image:1")
-	buildImageSuccessfully(c, "image:2", withDockerfile(`FROM `+minimalBaseImage()+`
+	buildImageSuccessfully(c, "image:2", build.WithDockerfile(`FROM `+minimalBaseImage()+`
 LABEL number=2`))
 	imageID2 := getIDByName(c, "image:2")
-	buildImageSuccessfully(c, "image:3", withDockerfile(`FROM `+minimalBaseImage()+`
+	buildImageSuccessfully(c, "image:3", build.WithDockerfile(`FROM `+minimalBaseImage()+`
 LABEL number=3`))
 	imageID3 := getIDByName(c, "image:3")
 
@@ -184,7 +185,7 @@ func assertImageList(out string, expected []string) bool {
 func (s *DockerSuite) TestImagesFilterSpaceTrimCase(c *check.C) {
 	imageName := "images_filter_test"
 	// Build a image and fail to build so that we have dangling images ?
-	buildImage(imageName, withDockerfile(`FROM busybox
+	buildImage(imageName, build.WithDockerfile(`FROM busybox
                  RUN touch /test/foo
                  RUN touch /test/bar
                  RUN touch /test/baz`)).Assert(c, icmd.Expected{
@@ -261,7 +262,7 @@ func (s *DockerSuite) TestImagesEnsureOnlyHeadsImagesShown(c *check.C) {
         MAINTAINER docker
         ENV foo bar`
 	name := "scratch-image"
-	result := buildImage(name, withDockerfile(dockerfile))
+	result := buildImage(name, build.WithDockerfile(dockerfile))
 	result.Assert(c, icmd.Success)
 	id := getIDByName(c, name)
 
@@ -285,7 +286,7 @@ func (s *DockerSuite) TestImagesEnsureImagesFromScratchShown(c *check.C) {
         MAINTAINER docker`
 
 	name := "scratch-image"
-	buildImageSuccessfully(c, name, withDockerfile(dockerfile))
+	buildImageSuccessfully(c, name, build.WithDockerfile(dockerfile))
 	id := getIDByName(c, name)
 
 	out, _ := dockerCmd(c, "images")
@@ -301,7 +302,7 @@ func (s *DockerSuite) TestImagesEnsureImagesFromBusyboxShown(c *check.C) {
         MAINTAINER docker`
 	name := "busybox-image"
 
-	buildImageSuccessfully(c, name, withDockerfile(dockerfile))
+	buildImageSuccessfully(c, name, build.WithDockerfile(dockerfile))
 	id := getIDByName(c, name)
 
 	out, _ := dockerCmd(c, "images")

+ 0 - 10
integration-cli/docker_cli_nat_test.go

@@ -38,16 +38,6 @@ func getExternalAddress(c *check.C) net.IP {
 	return ifaceIP
 }
 
-func getContainerLogs(c *check.C, containerID string) string {
-	out, _ := dockerCmd(c, "logs", containerID)
-	return strings.Trim(out, "\r\n")
-}
-
-func getContainerStatus(c *check.C, containerID string) string {
-	out := inspectField(c, containerID, "State.Running")
-	return out
-}
-
 func (s *DockerSuite) TestNetworkNat(c *check.C) {
 	testRequires(c, DaemonIsLinux, SameHostDaemon)
 	msg := "it works"

+ 4 - 3
integration-cli/docker_cli_ps_test.go

@@ -11,6 +11,7 @@ import (
 	"time"
 
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli/build"
 	"github.com/docker/docker/pkg/stringid"
 	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/go-check/check"
@@ -305,17 +306,17 @@ func (s *DockerSuite) TestPsListContainersFilterName(c *check.C) {
 func (s *DockerSuite) TestPsListContainersFilterAncestorImage(c *check.C) {
 	// Build images
 	imageName1 := "images_ps_filter_test1"
-	buildImageSuccessfully(c, imageName1, withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, imageName1, build.WithDockerfile(`FROM busybox
 		 LABEL match me 1`))
 	imageID1 := getIDByName(c, imageName1)
 
 	imageName1Tagged := "images_ps_filter_test1:tag"
-	buildImageSuccessfully(c, imageName1Tagged, withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, imageName1Tagged, build.WithDockerfile(`FROM busybox
 		 LABEL match me 1 tagged`))
 	imageID1Tagged := getIDByName(c, imageName1Tagged)
 
 	imageName2 := "images_ps_filter_test2"
-	buildImageSuccessfully(c, imageName2, withDockerfile(fmt.Sprintf(`FROM %s
+	buildImageSuccessfully(c, imageName2, build.WithDockerfile(fmt.Sprintf(`FROM %s
 		 LABEL match me 2`, imageName1)))
 	imageID2 := getIDByName(c, imageName2)
 

+ 5 - 4
integration-cli/docker_cli_pull_local_test.go

@@ -14,6 +14,7 @@ import (
 	"github.com/docker/distribution/manifest/manifestlist"
 	"github.com/docker/distribution/manifest/schema2"
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli/build"
 	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/go-check/check"
 	"github.com/opencontainers/go-digest"
@@ -65,7 +66,7 @@ func testConcurrentPullWholeRepo(c *check.C) {
 	repos := []string{}
 	for _, tag := range []string{"recent", "fresh", "todays"} {
 		repo := fmt.Sprintf("%v:%v", repoName, tag)
-		buildImageSuccessfully(c, repo, withDockerfile(fmt.Sprintf(`
+		buildImageSuccessfully(c, repo, build.WithDockerfile(fmt.Sprintf(`
 		    FROM busybox
 		    ENTRYPOINT ["/bin/echo"]
 		    ENV FOO foo
@@ -153,7 +154,7 @@ func testConcurrentPullMultipleTags(c *check.C) {
 	repos := []string{}
 	for _, tag := range []string{"recent", "fresh", "todays"} {
 		repo := fmt.Sprintf("%v:%v", repoName, tag)
-		buildImageSuccessfully(c, repo, withDockerfile(fmt.Sprintf(`
+		buildImageSuccessfully(c, repo, build.WithDockerfile(fmt.Sprintf(`
 		    FROM busybox
 		    ENTRYPOINT ["/bin/echo"]
 		    ENV FOO foo
@@ -207,7 +208,7 @@ func testPullIDStability(c *check.C) {
 	derivedImage := privateRegistryURL + "/dockercli/id-stability"
 	baseImage := "busybox"
 
-	buildImageSuccessfully(c, derivedImage, withDockerfile(fmt.Sprintf(`
+	buildImageSuccessfully(c, derivedImage, build.WithDockerfile(fmt.Sprintf(`
 	    FROM %s
 	    ENV derived true
 	    ENV asdf true
@@ -266,7 +267,7 @@ func (s *DockerSchema1RegistrySuite) TestPullIDStability(c *check.C) {
 func testPullNoLayers(c *check.C) {
 	repoName := fmt.Sprintf("%v/dockercli/scratch", privateRegistryURL)
 
-	buildImageSuccessfully(c, repoName, withDockerfile(`
+	buildImageSuccessfully(c, repoName, build.WithDockerfile(`
 	FROM scratch
 	ENV foo bar`))
 	dockerCmd(c, "push", repoName)

+ 2 - 1
integration-cli/docker_cli_pull_trusted_test.go

@@ -6,6 +6,7 @@ import (
 	"time"
 
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli/build"
 	"github.com/docker/docker/pkg/testutil"
 	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/go-check/check"
@@ -149,7 +150,7 @@ func (s *DockerTrustSuite) TestTrustedOfflinePull(c *check.C) {
 func (s *DockerTrustSuite) TestTrustedPullDelete(c *check.C) {
 	repoName := fmt.Sprintf("%v/dockercli/%s:latest", privateRegistryURL, "trusted-pull-delete")
 	// tag the image and upload it to the private registry
-	buildImageSuccessfully(c, repoName, withDockerfile(`
+	buildImageSuccessfully(c, repoName, build.WithDockerfile(`
                     FROM busybox
                     CMD echo trustedpulldelete
                 `))

+ 2 - 1
integration-cli/docker_cli_push_test.go

@@ -15,6 +15,7 @@ import (
 	"github.com/docker/distribution/reference"
 	cliconfig "github.com/docker/docker/cli/config"
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli/build"
 	"github.com/docker/docker/pkg/testutil"
 	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/go-check/check"
@@ -161,7 +162,7 @@ func testConcurrentPush(c *check.C) {
 	repos := []string{}
 	for _, tag := range []string{"push1", "push2", "push3"} {
 		repo := fmt.Sprintf("%v:%v", repoName, tag)
-		buildImageSuccessfully(c, repo, withDockerfile(fmt.Sprintf(`
+		buildImageSuccessfully(c, repo, build.WithDockerfile(fmt.Sprintf(`
 	FROM busybox
 	ENTRYPOINT ["/bin/echo"]
 	ENV FOO foo

+ 3 - 2
integration-cli/docker_cli_rm_test.go

@@ -5,6 +5,7 @@ import (
 	"os"
 
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli/build"
 	"github.com/go-check/check"
 )
 
@@ -60,12 +61,12 @@ func (s *DockerSuite) TestRmContainerOrphaning(c *check.C) {
 	MAINTAINER Integration Tests`
 
 	// build first dockerfile
-	buildImageSuccessfully(c, img, withDockerfile(dockerfile1))
+	buildImageSuccessfully(c, img, build.WithDockerfile(dockerfile1))
 	img1 := getIDByName(c, img)
 	// run container on first image
 	dockerCmd(c, "run", img)
 	// rebuild dockerfile with a small addition at the end
-	buildImageSuccessfully(c, img, withDockerfile(dockerfile2))
+	buildImageSuccessfully(c, img, build.WithDockerfile(dockerfile2))
 	// try to remove the image, should not error out.
 	out, _, err := dockerCmdWithError("rmi", img)
 	c.Assert(err, check.IsNil, check.Commentf("Expected to removing the image, but failed: %s", out))

+ 6 - 5
integration-cli/docker_cli_rmi_test.go

@@ -6,6 +6,7 @@ import (
 	"time"
 
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli/build"
 	"github.com/docker/docker/pkg/stringid"
 	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/go-check/check"
@@ -147,7 +148,7 @@ func (s *DockerSuite) TestRmiImgIDForce(c *check.C) {
 // See https://github.com/docker/docker/issues/14116
 func (s *DockerSuite) TestRmiImageIDForceWithRunningContainersAndMultipleTags(c *check.C) {
 	dockerfile := "FROM busybox\nRUN echo test 14116\n"
-	buildImageSuccessfully(c, "test-14116", withDockerfile(dockerfile))
+	buildImageSuccessfully(c, "test-14116", build.WithDockerfile(dockerfile))
 	imgID := getIDByName(c, "test-14116")
 
 	newTag := "newtag"
@@ -205,7 +206,7 @@ func (s *DockerSuite) TestRmiForceWithMultipleRepositories(c *check.C) {
 	tag1 := imageName + ":tag1"
 	tag2 := imageName + ":tag2"
 
-	buildImageSuccessfully(c, tag1, withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, tag1, build.WithDockerfile(`FROM busybox
 		MAINTAINER "docker"`))
 	dockerCmd(c, "tag", tag1, tag2)
 
@@ -234,7 +235,7 @@ func (s *DockerSuite) TestRmiContainerImageNotFound(c *check.C) {
 	imageIds := make([]string, 2)
 	for i, name := range imageNames {
 		dockerfile := fmt.Sprintf("FROM busybox\nMAINTAINER %s\nRUN echo %s\n", name, name)
-		buildImageSuccessfully(c, name, withoutCache, withDockerfile(dockerfile))
+		buildImageSuccessfully(c, name, build.WithoutCache, build.WithDockerfile(dockerfile))
 		id := getIDByName(c, name)
 		imageIds[i] = id
 	}
@@ -263,7 +264,7 @@ RUN echo 0 #layer0
 RUN echo 1 #layer1
 RUN echo 2 #layer2
 `
-	buildImageSuccessfully(c, image, withoutCache, withDockerfile(dockerfile))
+	buildImageSuccessfully(c, image, build.WithoutCache, build.WithDockerfile(dockerfile))
 	out, _ := dockerCmd(c, "history", "-q", image)
 	ids := strings.Split(out, "\n")
 	idToTag := ids[2]
@@ -299,7 +300,7 @@ RUN echo 2 #layer2
 }
 
 func (*DockerSuite) TestRmiParentImageFail(c *check.C) {
-	buildImageSuccessfully(c, "test", withDockerfile(`
+	buildImageSuccessfully(c, "test", build.WithDockerfile(`
 	FROM busybox
 	RUN echo hello`))
 

+ 11 - 10
integration-cli/docker_cli_run_test.go

@@ -22,6 +22,7 @@ import (
 	"time"
 
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli/build"
 	"github.com/docker/docker/pkg/mount"
 	"github.com/docker/docker/pkg/stringid"
 	"github.com/docker/docker/pkg/stringutils"
@@ -410,7 +411,7 @@ func (s *DockerSuite) TestRunCreateVolumesInSymlinkDir(c *check.C) {
 		containerPath = "/test/test"
 		cmd = "true"
 	}
-	buildImageSuccessfully(c, name, withDockerfile(dockerFile))
+	buildImageSuccessfully(c, name, build.WithDockerfile(dockerFile))
 	dockerCmd(c, "run", "-v", containerPath, name, cmd)
 }
 
@@ -435,7 +436,7 @@ func (s *DockerSuite) TestRunCreateVolumesInSymlinkDir2(c *check.C) {
 		containerPath = "/test/test"
 		cmd = "true"
 	}
-	buildImageSuccessfully(c, name, withDockerfile(dockerFile))
+	buildImageSuccessfully(c, name, build.WithDockerfile(dockerFile))
 	dockerCmd(c, "run", "-v", containerPath, name, cmd)
 }
 
@@ -1658,7 +1659,7 @@ func (s *DockerSuite) TestRunCopyVolumeUIDGID(c *check.C) {
 	// Not applicable on Windows as it does not support uid or gid in this way
 	testRequires(c, DaemonIsLinux)
 	name := "testrunvolumesuidgid"
-	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, name, build.WithDockerfile(`FROM busybox
 		RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
 		RUN echo 'dockerio:x:1001:' >> /etc/group
 		RUN mkdir -p /hello && touch /hello/test && chown dockerio.dockerio /hello`))
@@ -1677,7 +1678,7 @@ func (s *DockerSuite) TestRunCopyVolumeContent(c *check.C) {
 	// that copies from the image to the volume.
 	testRequires(c, DaemonIsLinux)
 	name := "testruncopyvolumecontent"
-	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, name, build.WithDockerfile(`FROM busybox
 		RUN mkdir -p /hello/local && echo hello > /hello/local/world`))
 
 	// Test that the content is copied from the image to the volume
@@ -1689,7 +1690,7 @@ func (s *DockerSuite) TestRunCopyVolumeContent(c *check.C) {
 
 func (s *DockerSuite) TestRunCleanupCmdOnEntrypoint(c *check.C) {
 	name := "testrunmdcleanuponentrypoint"
-	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, name, build.WithDockerfile(`FROM busybox
 		ENTRYPOINT ["echo"]
 		CMD ["testingpoint"]`))
 
@@ -2173,7 +2174,7 @@ func (s *DockerSuite) TestVolumesNoCopyData(c *check.C) {
 	// are pre-populated such as is built in the dockerfile used in this test.
 	testRequires(c, DaemonIsLinux)
 	prefix, slash := getPrefixAndSlashFromDaemonPlatform()
-	buildImageSuccessfully(c, "dataimage", withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, "dataimage", build.WithDockerfile(`FROM busybox
 		RUN ["mkdir", "-p", "/foo"]
 		RUN ["touch", "/foo/bar"]`))
 	dockerCmd(c, "run", "--name", "test", "-v", prefix+slash+"foo", "busybox")
@@ -2204,7 +2205,7 @@ func (s *DockerSuite) TestRunNoOutputFromPullInStdout(c *check.C) {
 func (s *DockerSuite) TestRunVolumesCleanPaths(c *check.C) {
 	testRequires(c, SameHostDaemon)
 	prefix, slash := getPrefixAndSlashFromDaemonPlatform()
-	buildImageSuccessfully(c, "run_volumes_clean_paths", withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, "run_volumes_clean_paths", build.WithDockerfile(`FROM busybox
 		VOLUME `+prefix+`/foo/`))
 	dockerCmd(c, "run", "-v", prefix+"/foo", "-v", prefix+"/bar/", "--name", "dark_helmet", "run_volumes_clean_paths")
 
@@ -3843,7 +3844,7 @@ func (s *DockerSuite) TestRunInitLayerPathOwnership(c *check.C) {
 	// Not applicable on Windows as it does not support Linux uid/gid ownership
 	testRequires(c, DaemonIsLinux)
 	name := "testetcfileownership"
-	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, name, build.WithDockerfile(`FROM busybox
 		RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
 		RUN echo 'dockerio:x:1001:' >> /etc/group
 		RUN chown dockerio:dockerio /etc`))
@@ -3975,7 +3976,7 @@ func (s *DockerSuite) TestRunNamedVolumeCopyImageData(c *check.C) {
 	testRequires(c, DaemonIsLinux)
 
 	testImg := "testvolumecopy"
-	buildImageSuccessfully(c, testImg, withDockerfile(`
+	buildImageSuccessfully(c, testImg, build.WithDockerfile(`
 	FROM busybox
 	RUN mkdir -p /foo && echo hello > /foo/hello
 	`))
@@ -4054,7 +4055,7 @@ func (s *DockerSuite) TestRunVolumeWithOneCharacter(c *check.C) {
 
 func (s *DockerSuite) TestRunVolumeCopyFlag(c *check.C) {
 	testRequires(c, DaemonIsLinux) // Windows does not support copying data from image to the volume
-	buildImageSuccessfully(c, "volumecopy", withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, "volumecopy", build.WithDockerfile(`FROM busybox
 		RUN mkdir /foo && echo hello > /foo/bar
 		CMD cat /foo/bar`))
 	dockerCmd(c, "volume", "create", "test")

+ 2 - 1
integration-cli/docker_cli_run_unix_test.go

@@ -17,6 +17,7 @@ import (
 	"time"
 
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli/build"
 	"github.com/docker/docker/pkg/homedir"
 	"github.com/docker/docker/pkg/mount"
 	"github.com/docker/docker/pkg/parsers"
@@ -828,7 +829,7 @@ func (s *DockerSuite) TestRunTmpfsMounts(c *check.C) {
 
 func (s *DockerSuite) TestRunTmpfsMountsOverrideImageVolumes(c *check.C) {
 	name := "img-with-volumes"
-	buildImageSuccessfully(c, name, withDockerfile(`
+	buildImageSuccessfully(c, name, build.WithDockerfile(`
     FROM busybox
     VOLUME /run
     RUN touch /run/stuff

+ 3 - 2
integration-cli/docker_cli_save_load_test.go

@@ -14,6 +14,7 @@ import (
 	"time"
 
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli/build"
 	"github.com/docker/docker/pkg/testutil"
 	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/go-check/check"
@@ -265,7 +266,7 @@ func (s *DockerSuite) TestSaveDirectoryPermissions(c *check.C) {
 	os.Mkdir(extractionDirectory, 0777)
 
 	defer os.RemoveAll(tmpDir)
-	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, name, build.WithDockerfile(`FROM busybox
 	RUN adduser -D user && mkdir -p /opt/a/b && chown -R user:user /opt/a
 	RUN touch /opt/a/b/c && chown user:user /opt/a/b/c`))
 
@@ -360,7 +361,7 @@ func (s *DockerSuite) TestSaveLoadNoTag(c *check.C) {
 
 	name := "saveloadnotag"
 
-	buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nENV foo=bar"))
+	buildImageSuccessfully(c, name, build.WithDockerfile("FROM busybox\nENV foo=bar"))
 	id := inspectField(c, name, "Id")
 
 	// Test to make sure that save w/o name just shows imageID during load

+ 2 - 1
integration-cli/docker_cli_save_load_unix_test.go

@@ -12,6 +12,7 @@ import (
 	"time"
 
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli/build"
 	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/go-check/check"
 	"github.com/kr/pty"
@@ -71,7 +72,7 @@ func (s *DockerSuite) TestSaveAndLoadRepoStdout(c *check.C) {
 
 func (s *DockerSuite) TestSaveAndLoadWithProgressBar(c *check.C) {
 	name := "test-load"
-	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, name, build.WithDockerfile(`FROM busybox
 	RUN touch aa
 	`))
 

+ 7 - 10
integration-cli/docker_cli_swarm_test.go

@@ -17,6 +17,7 @@ import (
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/swarm"
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli"
 	"github.com/docker/docker/integration-cli/daemon"
 	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/docker/libnetwork/driverapi"
@@ -57,8 +58,8 @@ func (s *DockerSwarmSuite) TestSwarmInit(c *check.C) {
 		return sw.Spec
 	}
 
-	out, err := d.Cmd("swarm", "init", "--cert-expiry", "30h", "--dispatcher-heartbeat", "11s")
-	c.Assert(err, checker.IsNil, check.Commentf("out: %v", out))
+	cli.Docker(cli.Cmd("swarm", "init", "--cert-expiry", "30h", "--dispatcher-heartbeat", "11s"),
+		cli.Daemon(d.Daemon)).Assert(c, icmd.Success)
 
 	spec := getSpec()
 	c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 30*time.Hour)
@@ -66,8 +67,7 @@ func (s *DockerSwarmSuite) TestSwarmInit(c *check.C) {
 
 	c.Assert(d.Leave(true), checker.IsNil)
 	time.Sleep(500 * time.Millisecond) // https://github.com/docker/swarmkit/issues/1421
-	out, err = d.Cmd("swarm", "init")
-	c.Assert(err, checker.IsNil, check.Commentf("out: %v", out))
+	cli.Docker(cli.Cmd("swarm", "init"), cli.Daemon(d.Daemon)).Assert(c, icmd.Success)
 
 	spec = getSpec()
 	c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 90*24*time.Hour)
@@ -77,15 +77,12 @@ func (s *DockerSwarmSuite) TestSwarmInit(c *check.C) {
 func (s *DockerSwarmSuite) TestSwarmInitIPv6(c *check.C) {
 	testRequires(c, IPv6)
 	d1 := s.AddDaemon(c, false, false)
-	out, err := d1.Cmd("swarm", "init", "--listen-addr", "::1")
-	c.Assert(err, checker.IsNil, check.Commentf("out: %v", out))
+	cli.Docker(cli.Cmd("swarm", "init", "--listen-add", "::1"), cli.Daemon(d1.Daemon)).Assert(c, icmd.Success)
 
 	d2 := s.AddDaemon(c, false, false)
-	out, err = d2.Cmd("swarm", "join", "::1")
-	c.Assert(err, checker.IsNil, check.Commentf("out: %v", out))
+	cli.Docker(cli.Cmd("swarm", "join", "::1"), cli.Daemon(d2.Daemon)).Assert(c, icmd.Success)
 
-	out, err = d2.Cmd("info")
-	c.Assert(err, checker.IsNil, check.Commentf("out: %v", out))
+	out := cli.Docker(cli.Cmd("info"), cli.Daemon(d2.Daemon)).Assert(c, icmd.Success).Combined()
 	c.Assert(out, checker.Contains, "Swarm: active")
 }
 

+ 2 - 1
integration-cli/docker_cli_tag_test.go

@@ -5,6 +5,7 @@ import (
 	"strings"
 
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli/build"
 	"github.com/docker/docker/pkg/stringid"
 	"github.com/docker/docker/pkg/stringutils"
 	"github.com/go-check/check"
@@ -142,7 +143,7 @@ func (s *DockerSuite) TestTagInvalidRepoName(c *check.C) {
 
 // ensure tags cannot create ambiguity with image ids
 func (s *DockerSuite) TestTagTruncationAmbiguity(c *check.C) {
-	buildImageSuccessfully(c, "notbusybox:latest", withDockerfile(`FROM busybox
+	buildImageSuccessfully(c, "notbusybox:latest", build.WithDockerfile(`FROM busybox
 		MAINTAINER dockerio`))
 	imageID := getIDByName(c, "notbusybox:latest")
 	truncatedImageID := stringid.TruncateID(imageID)

+ 4 - 3
integration-cli/docker_cli_volume_test.go

@@ -10,6 +10,7 @@ import (
 	"strings"
 
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli/build"
 	"github.com/docker/docker/integration-cli/request"
 	icmd "github.com/docker/docker/pkg/testutil/cmd"
 	"github.com/go-check/check"
@@ -497,7 +498,7 @@ func (s *DockerSuite) TestDuplicateMountpointsForVolumesFrom(c *check.C) {
 	testRequires(c, DaemonIsLinux)
 
 	image := "vimage"
-	buildImageSuccessfully(c, image, withDockerfile(`
+	buildImageSuccessfully(c, image, build.WithDockerfile(`
 		FROM busybox
 		VOLUME ["/tmp/data"]`))
 
@@ -539,7 +540,7 @@ func (s *DockerSuite) TestDuplicateMountpointsForVolumesFromAndBind(c *check.C)
 	testRequires(c, DaemonIsLinux)
 
 	image := "vimage"
-	buildImageSuccessfully(c, image, withDockerfile(`
+	buildImageSuccessfully(c, image, build.WithDockerfile(`
                 FROM busybox
                 VOLUME ["/tmp/data"]`))
 
@@ -583,7 +584,7 @@ func (s *DockerSuite) TestDuplicateMountpointsForVolumesFromAndMounts(c *check.C
 	testRequires(c, SameHostDaemon, DaemonIsLinux)
 
 	image := "vimage"
-	buildImageSuccessfully(c, image, withDockerfile(`
+	buildImageSuccessfully(c, image, build.WithDockerfile(`
                 FROM busybox
                 VOLUME ["/tmp/data"]`))
 

+ 8 - 45
integration-cli/docker_utils_test.go

@@ -21,6 +21,8 @@ import (
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/integration-cli/checker"
+	"github.com/docker/docker/integration-cli/cli"
+	"github.com/docker/docker/integration-cli/cli/build"
 	"github.com/docker/docker/integration-cli/daemon"
 	"github.com/docker/docker/integration-cli/registry"
 	"github.com/docker/docker/integration-cli/request"
@@ -351,7 +353,7 @@ func newRemoteFileServer(c *check.C, ctx *FakeContext) *remoteFileServer {
 	// Build the image
 	fakeContextAddDockerfile(c, ctx, `FROM httpserver
 COPY . /static`)
-	buildImageSuccessfully(c, image, withoutCache, withExternalBuildContext(ctx))
+	buildImageSuccessfully(c, image, build.WithoutCache, withExternalBuildContext(ctx))
 
 	// Start the container
 	dockerCmd(c, "run", "-d", "-P", "--name", container, image)
@@ -484,26 +486,14 @@ func getIDByName(c *check.C, name string) string {
 	return id
 }
 
-func buildImageSuccessfully(c *check.C, name string, cmdOperators ...func(*icmd.Cmd) func()) {
+// Deprecated: use cli.Build
+func buildImageSuccessfully(c *check.C, name string, cmdOperators ...cli.CmdOperator) {
 	buildImage(name, cmdOperators...).Assert(c, icmd.Success)
 }
 
-func buildImage(name string, cmdOperators ...func(*icmd.Cmd) func()) *icmd.Result {
-	cmd := icmd.Command(dockerBinary, "build", "-t", name)
-	for _, op := range cmdOperators {
-		deferFn := op(&cmd)
-		if deferFn != nil {
-			defer deferFn()
-		}
-	}
-	return icmd.RunCmd(cmd)
-}
-
-func withBuildContextPath(path string) func(*icmd.Cmd) func() {
-	return func(cmd *icmd.Cmd) func() {
-		cmd.Command = append(cmd.Command, path)
-		return nil
-	}
+// Deprecated: use cli.Build
+func buildImage(name string, cmdOperators ...cli.CmdOperator) *icmd.Result {
+	return cli.Docker(cli.Build(name), cmdOperators...)
 }
 
 func withExternalBuildContext(ctx *FakeContext) func(*icmd.Cmd) func() {
@@ -528,18 +518,6 @@ func withBuildContext(c *check.C, contextOperators ...func(*FakeContext) error)
 	}
 }
 
-func withBuildFlags(flags ...string) func(*icmd.Cmd) func() {
-	return func(cmd *icmd.Cmd) func() {
-		cmd.Command = append(cmd.Command, flags...)
-		return nil
-	}
-}
-
-func withoutCache(cmd *icmd.Cmd) func() {
-	cmd.Command = append(cmd.Command, "--no-cache")
-	return nil
-}
-
 func withFile(name, content string) func(*FakeContext) error {
 	return func(ctx *FakeContext) error {
 		return ctx.Add(name, content)
@@ -554,26 +532,11 @@ func closeBuildContext(c *check.C, ctx *FakeContext) func() {
 	}
 }
 
-func withDockerfile(dockerfile string) func(*icmd.Cmd) func() {
-	return func(cmd *icmd.Cmd) func() {
-		cmd.Command = append(cmd.Command, "-")
-		cmd.Stdin = strings.NewReader(dockerfile)
-		return nil
-	}
-}
-
 func trustedBuild(cmd *icmd.Cmd) func() {
 	trustedCmd(cmd)
 	return nil
 }
 
-func withEnvironmentVariales(envs ...string) func(cmd *icmd.Cmd) func() {
-	return func(cmd *icmd.Cmd) func() {
-		cmd.Env = envs
-		return nil
-	}
-}
-
 type gitServer interface {
 	URL() string
 	Close() error

+ 34 - 1
integration-cli/environment/environment.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"io/ioutil"
 	"os"
+	"os/exec"
 	"path/filepath"
 	"strconv"
 	"strings"
@@ -11,9 +12,15 @@ import (
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/client"
+	"github.com/docker/docker/opts"
 	"golang.org/x/net/context"
 )
 
+const (
+	// DefaultDockerBinary is the name of the docker binary
+	DefaultDockerBinary = "docker"
+)
+
 // Execution holds informations about the test execution environment.
 type Execution struct {
 	daemonPlatform      string
@@ -31,7 +38,8 @@ type Execution struct {
 	containerStoragePath string
 	// baseImage is the name of the base image for testing
 	// Environment variable WINDOWS_BASE_IMAGE can override this
-	baseImage string
+	baseImage    string
+	dockerBinary string
 
 	protectedElements protectedElements
 }
@@ -90,6 +98,16 @@ func New() (*Execution, error) {
 			daemonPid = int(p)
 		}
 	}
+
+	var dockerBinary = DefaultDockerBinary
+	if dockerBin := os.Getenv("DOCKER_BINARY"); dockerBin != "" {
+		dockerBinary = dockerBin
+	}
+	dockerBinary, err = exec.LookPath(dockerBinary)
+	if err != nil {
+		return nil, err
+	}
+
 	return &Execution{
 		localDaemon:          localDaemon,
 		daemonPlatform:       daemonPlatform,
@@ -102,6 +120,7 @@ func New() (*Execution, error) {
 		daemonPid:            daemonPid,
 		experimentalDaemon:   info.ExperimentalBuild,
 		baseImage:            baseImage,
+		dockerBinary:         dockerBinary,
 		protectedElements: protectedElements{
 			images: map[string]struct{}{},
 		},
@@ -190,3 +209,17 @@ func (e *Execution) DaemonKernelVersionNumeric() int {
 	v, _ := strconv.Atoi(strings.Split(e.daemonKernelVersion, " ")[1])
 	return v
 }
+
+// DockerBinary returns the docker binary for this testing environment
+func (e *Execution) DockerBinary() string {
+	return e.dockerBinary
+}
+
+// DaemonHost return the daemon host string for this test execution
+func DaemonHost() string {
+	daemonURLStr := "unix://" + opts.DefaultUnixSocket
+	if daemonHostVar := os.Getenv("DOCKER_HOST"); daemonHostVar != "" {
+		daemonURLStr = daemonHostVar
+	}
+	return daemonURLStr
+}

+ 3 - 2
pkg/testutil/cmd/command.go

@@ -54,10 +54,10 @@ type Result struct {
 
 // Assert compares the Result against the Expected struct, and fails the test if
 // any of the expcetations are not met.
-func (r *Result) Assert(t testingT, exp Expected) {
+func (r *Result) Assert(t testingT, exp Expected) *Result {
 	err := r.Compare(exp)
 	if err == nil {
-		return
+		return r
 	}
 	_, file, line, ok := runtime.Caller(1)
 	if ok {
@@ -65,6 +65,7 @@ func (r *Result) Assert(t testingT, exp Expected) {
 	} else {
 		t.Fatalf("(no file/line info) - %s", err.Error())
 	}
+	return nil
 }
 
 // Compare returns a formatted error with the command, stdout, stderr, exit

部分文件因为文件数量过多而无法显示