瀏覽代碼

Merge pull request #36832 from vdemeester/integration-daemon-api-helpers

More integration-cli/integration refactoring + request package
Vincent Demeester 7 年之前
父節點
當前提交
25ff68a80f
共有 63 個文件被更改,包括 274 次插入266 次删除
  1. 0 36
      integration-cli/daemon/daemon.go
  2. 1 1
      integration-cli/docker_api_attach_test.go
  3. 1 1
      integration-cli/docker_api_build_test.go
  4. 3 3
      integration-cli/docker_api_containers_test.go
  5. 1 1
      integration-cli/docker_api_create_test.go
  6. 1 1
      integration-cli/docker_api_exec_resize_test.go
  7. 1 1
      integration-cli/docker_api_exec_test.go
  8. 1 1
      integration-cli/docker_api_images_test.go
  9. 1 1
      integration-cli/docker_api_logs_test.go
  10. 1 1
      integration-cli/docker_api_network_test.go
  11. 1 1
      integration-cli/docker_api_stats_test.go
  12. 1 1
      integration-cli/docker_api_swarm_node_test.go
  13. 1 1
      integration-cli/docker_api_swarm_service_test.go
  14. 7 7
      integration-cli/docker_api_swarm_test.go
  15. 1 1
      integration-cli/docker_api_test.go
  16. 4 8
      integration-cli/docker_cli_daemon_test.go
  17. 3 3
      integration-cli/docker_cli_swarm_test.go
  18. 1 1
      integration-cli/docker_cli_update_unix_test.go
  19. 1 1
      integration-cli/docker_deprecated_api_v124_test.go
  20. 1 1
      integration-cli/docker_deprecated_api_v124_unix_test.go
  21. 1 1
      integration-cli/docker_utils_test.go
  22. 7 6
      integration/build/build_session_test.go
  23. 1 1
      integration/build/build_test.go
  24. 1 1
      integration/container/create_test.go
  25. 1 1
      integration/container/diff_test.go
  26. 1 1
      integration/container/exec_test.go
  27. 1 1
      integration/container/export_test.go
  28. 1 1
      integration/container/health_test.go
  29. 1 1
      integration/container/inspect_test.go
  30. 1 1
      integration/container/kill_test.go
  31. 1 1
      integration/container/links_linux_test.go
  32. 1 1
      integration/container/logs_test.go
  33. 1 1
      integration/container/mounts_linux_test.go
  34. 1 1
      integration/container/nat_test.go
  35. 1 1
      integration/container/pause_test.go
  36. 1 1
      integration/container/ps_test.go
  37. 1 1
      integration/container/remove_test.go
  38. 1 1
      integration/container/rename_test.go
  39. 2 2
      integration/container/resize_test.go
  40. 1 1
      integration/container/stats_test.go
  41. 1 1
      integration/container/stop_test.go
  42. 1 1
      integration/container/update_linux_test.go
  43. 1 1
      integration/container/update_test.go
  44. 1 1
      integration/image/commit_test.go
  45. 1 1
      integration/image/import_test.go
  46. 1 1
      integration/image/remove_test.go
  47. 1 1
      integration/image/tag_test.go
  48. 0 42
      integration/internal/request/client.go
  49. 1 1
      integration/network/delete_test.go
  50. 5 5
      integration/session/session_test.go
  51. 2 2
      integration/system/event_test.go
  52. 2 2
      integration/system/info_linux_test.go
  53. 1 1
      integration/system/info_test.go
  54. 1 1
      integration/system/login_test.go
  55. 1 1
      integration/system/version_test.go
  56. 1 1
      integration/volume/volume_test.go
  57. 33 0
      internal/test/daemon/container.go
  58. 2 2
      internal/test/daemon/daemon.go
  59. 1 1
      internal/test/fakestorage/storage.go
  60. 1 1
      internal/test/request/npipe.go
  61. 1 1
      internal/test/request/npipe_windows.go
  62. 78 0
      internal/test/request/ops.go
  63. 78 100
      internal/test/request/request.go

+ 0 - 36
integration-cli/daemon/daemon.go

@@ -70,18 +70,6 @@ func (d *Daemon) GetIDByName(name string) (string, error) {
 	return d.inspectFieldWithError(name, "Id")
 }
 
-// ActiveContainers returns the list of ids of the currently running containers
-func (d *Daemon) ActiveContainers() (ids []string) {
-	// FIXME(vdemeester) shouldn't ignore the error
-	out, _ := d.Cmd("ps", "-q")
-	for _, id := range strings.Split(out, "\n") {
-		if id = strings.TrimSpace(id); id != "" {
-			ids = append(ids, id)
-		}
-	}
-	return
-}
-
 // InspectField returns the field filter by 'filter'
 func (d *Daemon) InspectField(name, filter string) (string, error) {
 	return d.inspectFilter(name, filter)
@@ -100,15 +88,6 @@ func (d *Daemon) inspectFieldWithError(name, field string) (string, error) {
 	return d.inspectFilter(name, fmt.Sprintf(".%s", field))
 }
 
-// FindContainerIP returns the ip of the specified container
-func (d *Daemon) FindContainerIP(id string) (string, error) {
-	out, err := d.Cmd("inspect", "--format='{{ .NetworkSettings.Networks.bridge.IPAddress }}'", id)
-	if err != nil {
-		return "", err
-	}
-	return strings.Trim(out, " \r\n'"), nil
-}
-
 // BuildImageWithOut builds an image with the specified dockerfile and options and returns the output
 func (d *Daemon) BuildImageWithOut(name, dockerfile string, useCache bool, buildFlags ...string) (string, int, error) {
 	buildCmd := BuildImageCmdWithHost(d.dockerBinary, name, dockerfile, d.Sock(), useCache, buildFlags...)
@@ -139,21 +118,6 @@ func (d *Daemon) WaitRun(contID string) error {
 	return WaitInspectWithArgs(d.dockerBinary, contID, "{{.State.Running}}", "true", 10*time.Second, args...)
 }
 
-// CmdRetryOutOfSequence tries the specified command against the current daemon for 10 times
-func (d *Daemon) CmdRetryOutOfSequence(args ...string) (string, error) {
-	for i := 0; ; i++ {
-		out, err := d.Cmd(args...)
-		if err != nil {
-			if strings.Contains(out, "update out of sequence") {
-				if i < 10 {
-					continue
-				}
-			}
-		}
-		return out, err
-	}
-}
-
 // WaitInspectWithArgs waits for the specified expression to be equals to the specified expected string in the given time.
 // Deprecated: use cli.WaitCmd instead
 func WaitInspectWithArgs(dockerBinary, name, expr, expected string, timeout time.Duration, arg ...string) error {

+ 1 - 1
integration-cli/docker_api_attach_test.go

@@ -15,7 +15,7 @@ import (
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/client"
 	"github.com/docker/docker/integration-cli/checker"
-	"github.com/docker/docker/integration-cli/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/docker/docker/pkg/stdcopy"
 	"github.com/go-check/check"
 	"golang.org/x/net/websocket"

+ 1 - 1
integration-cli/docker_api_build_test.go

@@ -13,10 +13,10 @@ import (
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/integration-cli/checker"
-	"github.com/docker/docker/integration-cli/request"
 	"github.com/docker/docker/internal/test/fakecontext"
 	"github.com/docker/docker/internal/test/fakegit"
 	"github.com/docker/docker/internal/test/fakestorage"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/go-check/check"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"

+ 3 - 3
integration-cli/docker_api_containers_test.go

@@ -24,7 +24,7 @@ import (
 	"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/docker/docker/internal/test/request"
 	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/docker/pkg/mount"
 	"github.com/docker/docker/pkg/stringid"
@@ -1254,13 +1254,13 @@ func (s *DockerSuite) TestContainerAPIChunkedEncoding(c *check.C) {
 		"OpenStdin": true,
 	}
 
-	resp, _, err := request.Post("/containers/create", request.JSONBody(config), func(req *http.Request) error {
+	resp, _, err := request.Post("/containers/create", request.JSONBody(config), request.With(func(req *http.Request) error {
 		// This is a cheat to make the http request do chunked encoding
 		// Otherwise (just setting the Content-Encoding to chunked) net/http will overwrite
 		// https://golang.org/src/pkg/net/http/request.go?s=11980:12172
 		req.ContentLength = -1
 		return nil
-	})
+	}))
 	c.Assert(err, checker.IsNil, check.Commentf("error creating container with chunked encoding"))
 	defer resp.Body.Close()
 	c.Assert(resp.StatusCode, checker.Equals, http.StatusCreated)

+ 1 - 1
integration-cli/docker_api_create_test.go

@@ -7,7 +7,7 @@ import (
 
 	"github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/integration-cli/checker"
-	"github.com/docker/docker/integration-cli/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/go-check/check"
 )
 

+ 1 - 1
integration-cli/docker_api_exec_resize_test.go

@@ -10,7 +10,7 @@ import (
 	"sync"
 
 	"github.com/docker/docker/integration-cli/checker"
-	"github.com/docker/docker/integration-cli/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/go-check/check"
 )
 

+ 1 - 1
integration-cli/docker_api_exec_test.go

@@ -15,7 +15,7 @@ import (
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/client"
 	"github.com/docker/docker/integration-cli/checker"
-	"github.com/docker/docker/integration-cli/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/go-check/check"
 	"golang.org/x/net/context"
 )

+ 1 - 1
integration-cli/docker_api_images_test.go

@@ -11,7 +11,7 @@ import (
 	"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/docker/docker/internal/test/request"
 	"github.com/go-check/check"
 	"golang.org/x/net/context"
 )

+ 1 - 1
integration-cli/docker_api_logs_test.go

@@ -14,7 +14,7 @@ import (
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/client"
 	"github.com/docker/docker/integration-cli/checker"
-	"github.com/docker/docker/integration-cli/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/docker/docker/pkg/stdcopy"
 	"github.com/go-check/check"
 	"golang.org/x/net/context"

+ 1 - 1
integration-cli/docker_api_network_test.go

@@ -12,7 +12,7 @@ import (
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/api/types/network"
 	"github.com/docker/docker/integration-cli/checker"
-	"github.com/docker/docker/integration-cli/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/go-check/check"
 )
 

+ 1 - 1
integration-cli/docker_api_stats_test.go

@@ -15,7 +15,7 @@ import (
 	"github.com/docker/docker/api/types/versions"
 	"github.com/docker/docker/client"
 	"github.com/docker/docker/integration-cli/checker"
-	"github.com/docker/docker/integration-cli/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/go-check/check"
 	"golang.org/x/net/context"
 )

+ 1 - 1
integration-cli/docker_api_swarm_node_test.go

@@ -111,7 +111,7 @@ func (s *DockerSwarmSuite) TestAPISwarmNodeDrainPause(c *check.C) {
 	waitAndAssert(c, defaultReconciliationTimeout, d1.CheckActiveContainerCount, checker.GreaterThan, 0)
 	waitAndAssert(c, defaultReconciliationTimeout*2, reducedCheck(sumAsIntegers, d1.CheckActiveContainerCount, d2.CheckActiveContainerCount), checker.Equals, instances)
 
-	d2ContainerCount := len(d2.ActiveContainers())
+	d2ContainerCount := len(d2.ActiveContainers(c))
 
 	// set d2 to paused, scale service up, only d1 gets new tasks
 	d1.UpdateNode(c, d2.NodeID(), func(n *swarm.Node) {

+ 1 - 1
integration-cli/docker_api_swarm_service_test.go

@@ -556,7 +556,7 @@ func (s *DockerSwarmSuite) TestAPISwarmServicesStateReporting(c *check.C) {
 	getContainers := func() map[string]*daemon.Daemon {
 		m := make(map[string]*daemon.Daemon)
 		for _, d := range []*daemon.Daemon{d1, d2, d3} {
-			for _, id := range d.ActiveContainers() {
+			for _, id := range d.ActiveContainers(c) {
 				m[id] = d
 			}
 		}

+ 7 - 7
integration-cli/docker_api_swarm_test.go

@@ -22,8 +22,8 @@ import (
 	"github.com/docker/docker/client"
 	"github.com/docker/docker/integration-cli/checker"
 	"github.com/docker/docker/integration-cli/daemon"
-	"github.com/docker/docker/integration-cli/request"
 	testdaemon "github.com/docker/docker/internal/test/daemon"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/docker/swarmkit/ca"
 	"github.com/go-check/check"
 	"github.com/gotestyourself/gotestyourself/assert"
@@ -242,7 +242,7 @@ func (s *DockerSwarmSuite) TestAPISwarmPromoteDemote(c *check.C) {
 	node := d1.GetNode(c, d1.NodeID())
 	node.Spec.Role = swarm.NodeRoleWorker
 	url := fmt.Sprintf("/nodes/%s/update?version=%d", node.ID, node.Version.Index)
-	res, body, err := request.DoOnHost(d1.Sock(), url, request.Method("POST"), request.JSONBody(node.Spec))
+	res, body, err := request.Post(url, request.Host(d1.Sock()), request.JSONBody(node.Spec))
 	c.Assert(err, checker.IsNil)
 	b, err := request.ReadBody(body)
 	c.Assert(err, checker.IsNil)
@@ -507,11 +507,11 @@ func (s *DockerSwarmSuite) TestAPISwarmScaleNoRollingUpdate(c *check.C) {
 	id := d.CreateService(c, simpleTestService, setInstances(instances))
 
 	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances)
-	containers := d.ActiveContainers()
+	containers := d.ActiveContainers(c)
 	instances = 4
 	d.UpdateService(c, d.GetService(c, id), setInstances(instances))
 	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances)
-	containers2 := d.ActiveContainers()
+	containers2 := d.ActiveContainers(c)
 
 loop0:
 	for _, c1 := range containers {
@@ -529,7 +529,7 @@ func (s *DockerSwarmSuite) TestAPISwarmInvalidAddress(c *check.C) {
 	req := swarm.InitRequest{
 		ListenAddr: "",
 	}
-	res, _, err := request.DoOnHost(d.Sock(), "/swarm/init", request.Method("POST"), request.JSONBody(req))
+	res, _, err := request.Post("/swarm/init", request.Host(d.Sock()), request.JSONBody(req))
 	c.Assert(err, checker.IsNil)
 	c.Assert(res.StatusCode, checker.Equals, http.StatusBadRequest)
 
@@ -537,7 +537,7 @@ func (s *DockerSwarmSuite) TestAPISwarmInvalidAddress(c *check.C) {
 		ListenAddr:  "0.0.0.0:2377",
 		RemoteAddrs: []string{""},
 	}
-	res, _, err = request.DoOnHost(d.Sock(), "/swarm/join", request.Method("POST"), request.JSONBody(req2))
+	res, _, err = request.Post("/swarm/join", request.Host(d.Sock()), request.JSONBody(req2))
 	c.Assert(err, checker.IsNil)
 	c.Assert(res.StatusCode, checker.Equals, http.StatusBadRequest)
 }
@@ -943,7 +943,7 @@ func (s *DockerSwarmSuite) TestAPISwarmHealthcheckNone(c *check.C) {
 
 	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, instances)
 
-	containers := d.ActiveContainers()
+	containers := d.ActiveContainers(c)
 
 	out, err = d.Cmd("exec", containers[0], "ping", "-c1", "-W3", "top")
 	c.Assert(err, checker.IsNil, check.Commentf(out))

+ 1 - 1
integration-cli/docker_api_test.go

@@ -10,7 +10,7 @@ import (
 
 	"github.com/docker/docker/api"
 	"github.com/docker/docker/integration-cli/checker"
-	"github.com/docker/docker/integration-cli/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/go-check/check"
 )
 

+ 4 - 8
integration-cli/docker_cli_daemon_test.go

@@ -604,8 +604,7 @@ func (s *DockerDaemonSuite) TestDaemonBridgeExternal(c *check.C) {
 	_, err = d.Cmd("run", "-d", "--name", "ExtContainer", "busybox", "top")
 	c.Assert(err, check.IsNil)
 
-	containerIP, err := d.FindContainerIP("ExtContainer")
-	c.Assert(err, checker.IsNil)
+	containerIP := d.FindContainerIP(c, "ExtContainer")
 	ip := net.ParseIP(containerIP)
 	c.Assert(bridgeIPNet.Contains(ip), check.Equals, true,
 		check.Commentf("Container IP-Address must be in the same subnet range : %s",
@@ -676,8 +675,7 @@ func (s *DockerDaemonSuite) TestDaemonBridgeIP(c *check.C) {
 	_, err := d.Cmd("run", "-d", "--name", "test", "busybox", "top")
 	c.Assert(err, check.IsNil)
 
-	containerIP, err := d.FindContainerIP("test")
-	c.Assert(err, checker.IsNil)
+	containerIP := d.FindContainerIP(c, "test")
 	ip = net.ParseIP(containerIP)
 	c.Assert(bridgeIPNet.Contains(ip), check.Equals, true,
 		check.Commentf("Container IP-Address must be in the same subnet range : %s",
@@ -947,10 +945,8 @@ func (s *DockerDaemonSuite) TestDaemonLinksIpTablesRulesWhenLinkAndUnlink(c *che
 	_, err = s.d.Cmd("run", "-d", "--name", "parent", "--link", "child:http", "busybox", "top")
 	c.Assert(err, check.IsNil)
 
-	childIP, err := s.d.FindContainerIP("child")
-	c.Assert(err, checker.IsNil)
-	parentIP, err := s.d.FindContainerIP("parent")
-	c.Assert(err, checker.IsNil)
+	childIP := s.d.FindContainerIP(c, "child")
+	parentIP := s.d.FindContainerIP(c, "parent")
 
 	sourceRule := []string{"-i", bridgeName, "-o", bridgeName, "-p", "tcp", "-s", childIP, "--sport", "80", "-d", parentIP, "-j", "ACCEPT"}
 	destinationRule := []string{"-i", bridgeName, "-o", bridgeName, "-p", "tcp", "-s", parentIP, "--dport", "80", "-d", childIP, "-j", "ACCEPT"}

+ 3 - 3
integration-cli/docker_cli_swarm_test.go

@@ -177,7 +177,7 @@ func (s *DockerSwarmSuite) TestSwarmServiceTemplatingHostname(c *check.C) {
 	// make sure task has been deployed.
 	waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
 
-	containers := d.ActiveContainers()
+	containers := d.ActiveContainers(c)
 	out, err = d.Cmd("inspect", "--type", "container", "--format", "{{.Config.Hostname}}", containers[0])
 	c.Assert(err, checker.IsNil, check.Commentf(out))
 	c.Assert(strings.Split(out, "\n")[0], checker.Equals, "test-1-"+strings.Split(hostname, "\n")[0], check.Commentf("hostname with templating invalid"))
@@ -1675,7 +1675,7 @@ func (s *DockerSwarmSuite) TestSwarmReadonlyRootfs(c *check.C) {
 	c.Assert(err, checker.IsNil, check.Commentf(out))
 	c.Assert(strings.TrimSpace(out), checker.Equals, "true")
 
-	containers := d.ActiveContainers()
+	containers := d.ActiveContainers(c)
 	out, err = d.Cmd("inspect", "--type", "container", "--format", "{{.HostConfig.ReadonlyRootfs}}", containers[0])
 	c.Assert(err, checker.IsNil, check.Commentf(out))
 	c.Assert(strings.TrimSpace(out), checker.Equals, "true")
@@ -1762,7 +1762,7 @@ func (s *DockerSwarmSuite) TestSwarmStopSignal(c *check.C) {
 	c.Assert(err, checker.IsNil, check.Commentf(out))
 	c.Assert(strings.TrimSpace(out), checker.Equals, "SIGHUP")
 
-	containers := d.ActiveContainers()
+	containers := d.ActiveContainers(c)
 	out, err = d.Cmd("inspect", "--type", "container", "--format", "{{.Config.StopSignal}}", containers[0])
 	c.Assert(err, checker.IsNil, check.Commentf(out))
 	c.Assert(strings.TrimSpace(out), checker.Equals, "SIGHUP")

+ 1 - 1
integration-cli/docker_cli_update_unix_test.go

@@ -13,7 +13,7 @@ import (
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/client"
 	"github.com/docker/docker/integration-cli/checker"
-	"github.com/docker/docker/integration-cli/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/docker/docker/pkg/parsers/kernel"
 	"github.com/go-check/check"
 	"github.com/kr/pty"

+ 1 - 1
integration-cli/docker_deprecated_api_v124_test.go

@@ -8,7 +8,7 @@ import (
 	"strings"
 
 	"github.com/docker/docker/integration-cli/checker"
-	"github.com/docker/docker/integration-cli/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/go-check/check"
 )
 

+ 1 - 1
integration-cli/docker_deprecated_api_v124_unix_test.go

@@ -6,7 +6,7 @@ import (
 	"fmt"
 
 	"github.com/docker/docker/integration-cli/checker"
-	"github.com/docker/docker/integration-cli/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/go-check/check"
 )
 

+ 1 - 1
integration-cli/docker_utils_test.go

@@ -18,7 +18,7 @@ import (
 	"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/integration-cli/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/go-check/check"
 	"github.com/gotestyourself/gotestyourself/icmd"
 	"golang.org/x/net/context"

+ 7 - 6
integration/build/build_session_test.go

@@ -8,9 +8,9 @@ import (
 	"testing"
 
 	dclient "github.com/docker/docker/client"
-	"github.com/docker/docker/integration-cli/request"
 	"github.com/docker/docker/internal/test/daemon"
 	"github.com/docker/docker/internal/test/fakecontext"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
 	"github.com/moby/buildkit/session"
@@ -65,8 +65,9 @@ func TestBuildWithSession(t *testing.T) {
 	// rebuild with regular tar, confirm cache still applies
 	fctx.Add("Dockerfile", dockerfile)
 	// FIXME(vdemeester) use sock here
-	res, body, err := request.DoOnHost(d.Sock(),
+	res, body, err := request.Do(
 		"/build",
+		request.Host(d.Sock()),
 		request.Method(http.MethodPost),
 		request.RawContent(fctx.AsTarReader(t)),
 		request.ContentType("application/x-tar"))
@@ -103,14 +104,14 @@ func testBuildWithSession(t *testing.T, client dclient.APIClient, daemonSock str
 
 	g.Go(func() error {
 		// FIXME use sock here
-		res, body, err := request.DoOnHost(
-			daemonSock,
+		res, body, err := request.Do(
 			"/build?remote=client-session&session="+sess.ID(),
+			request.Host(daemonSock),
 			request.Method(http.MethodPost),
-			func(req *http.Request) error {
+			request.With(func(req *http.Request) error {
 				req.Body = ioutil.NopCloser(strings.NewReader(dockerfile))
 				return nil
-			},
+			}),
 		)
 		if err != nil {
 			return err

+ 1 - 1
integration/build/build_test.go

@@ -13,8 +13,8 @@ import (
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/api/types/versions"
-	"github.com/docker/docker/integration/internal/request"
 	"github.com/docker/docker/internal/test/fakecontext"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/docker/docker/pkg/jsonmessage"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"

+ 1 - 1
integration/container/create_test.go

@@ -7,7 +7,7 @@ import (
 
 	"github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/api/types/network"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/docker/docker/internal/testutil"
 	"github.com/gotestyourself/gotestyourself/skip"
 )

+ 1 - 1
integration/container/diff_test.go

@@ -7,7 +7,7 @@ import (
 
 	containertypes "github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/integration/internal/container"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/docker/docker/pkg/archive"
 	"github.com/gotestyourself/gotestyourself/assert"
 	"github.com/gotestyourself/gotestyourself/poll"

+ 1 - 1
integration/container/exec_test.go

@@ -8,7 +8,7 @@ import (
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/strslice"
 	"github.com/docker/docker/integration/internal/container"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
 )

+ 1 - 1
integration/container/export_test.go

@@ -9,8 +9,8 @@ import (
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/integration/internal/container"
-	"github.com/docker/docker/integration/internal/request"
 	"github.com/docker/docker/internal/test/daemon"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/docker/docker/pkg/jsonmessage"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"

+ 1 - 1
integration/container/health_test.go

@@ -9,7 +9,7 @@ import (
 	containertypes "github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/client"
 	"github.com/docker/docker/integration/internal/container"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/gotestyourself/gotestyourself/poll"
 )
 

+ 1 - 1
integration/container/inspect_test.go

@@ -8,7 +8,7 @@ import (
 
 	"github.com/docker/docker/client"
 	"github.com/docker/docker/integration/internal/container"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
 	"github.com/gotestyourself/gotestyourself/poll"

+ 1 - 1
integration/container/kill_test.go

@@ -8,7 +8,7 @@ import (
 	containertypes "github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/client"
 	"github.com/docker/docker/integration/internal/container"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
 	"github.com/gotestyourself/gotestyourself/poll"

+ 1 - 1
integration/container/links_linux_test.go

@@ -9,7 +9,7 @@ import (
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/integration/internal/container"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
 	"github.com/gotestyourself/gotestyourself/skip"

+ 1 - 1
integration/container/logs_test.go

@@ -7,7 +7,7 @@ import (
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/integration/internal/container"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/docker/docker/pkg/stdcopy"
 	"github.com/gotestyourself/gotestyourself/assert"
 	"github.com/gotestyourself/gotestyourself/skip"

+ 1 - 1
integration/container/mounts_linux_test.go

@@ -11,7 +11,7 @@ import (
 	"github.com/docker/docker/api/types/mount"
 	"github.com/docker/docker/api/types/network"
 	"github.com/docker/docker/client"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/docker/docker/pkg/system"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"

+ 1 - 1
integration/container/nat_test.go

@@ -13,7 +13,7 @@ import (
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/integration/internal/container"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/docker/go-connections/nat"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"

+ 1 - 1
integration/container/pause_test.go

@@ -10,7 +10,7 @@ import (
 	"github.com/docker/docker/api/types/events"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/integration/internal/container"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/docker/docker/internal/testutil"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"

+ 1 - 1
integration/container/ps_test.go

@@ -7,7 +7,7 @@ import (
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/integration/internal/container"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
 )

+ 1 - 1
integration/container/remove_test.go

@@ -9,7 +9,7 @@ import (
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/integration/internal/container"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/docker/docker/internal/testutil"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"

+ 1 - 1
integration/container/rename_test.go

@@ -9,7 +9,7 @@ import (
 	containertypes "github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/api/types/network"
 	"github.com/docker/docker/integration/internal/container"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/docker/docker/internal/testutil"
 	"github.com/docker/docker/pkg/stringid"
 	"github.com/gotestyourself/gotestyourself/assert"

+ 2 - 2
integration/container/resize_test.go

@@ -7,9 +7,9 @@ import (
 	"time"
 
 	"github.com/docker/docker/api/types"
-	req "github.com/docker/docker/integration-cli/request"
 	"github.com/docker/docker/integration/internal/container"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
+	req "github.com/docker/docker/internal/test/request"
 	"github.com/docker/docker/internal/testutil"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"

+ 1 - 1
integration/container/stats_test.go

@@ -9,7 +9,7 @@ import (
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/integration/internal/container"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
 	"github.com/gotestyourself/gotestyourself/poll"

+ 1 - 1
integration/container/stop_test.go

@@ -9,7 +9,7 @@ import (
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/integration/internal/container"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/gotestyourself/gotestyourself/assert"
 	"github.com/gotestyourself/gotestyourself/icmd"
 	"github.com/gotestyourself/gotestyourself/poll"

+ 1 - 1
integration/container/update_linux_test.go

@@ -9,7 +9,7 @@ import (
 
 	containertypes "github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/integration/internal/container"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
 	"github.com/gotestyourself/gotestyourself/poll"

+ 1 - 1
integration/container/update_test.go

@@ -7,7 +7,7 @@ import (
 
 	containertypes "github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/integration/internal/container"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/docker/docker/internal/testutil"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"

+ 1 - 1
integration/image/commit_test.go

@@ -6,7 +6,7 @@ import (
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/integration/internal/container"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
 )

+ 1 - 1
integration/image/import_test.go

@@ -9,7 +9,7 @@ import (
 	"testing"
 
 	"github.com/docker/docker/api/types"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/docker/docker/internal/testutil"
 )
 

+ 1 - 1
integration/image/remove_test.go

@@ -6,7 +6,7 @@ import (
 
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/integration/internal/container"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/docker/docker/internal/testutil"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"

+ 1 - 1
integration/image/tag_test.go

@@ -5,7 +5,7 @@ import (
 	"fmt"
 	"testing"
 
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/docker/docker/internal/testutil"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"

+ 0 - 42
integration/internal/request/client.go

@@ -1,42 +0,0 @@
-package request // import "github.com/docker/docker/integration/internal/request"
-
-import (
-	"fmt"
-	"testing"
-	"time"
-
-	"golang.org/x/net/context"
-
-	"github.com/docker/docker/client"
-	"github.com/docker/docker/internal/test/environment"
-	"github.com/gotestyourself/gotestyourself/assert"
-)
-
-// NewAPIClient returns a docker API client configured from environment variables
-func NewAPIClient(t *testing.T, ops ...func(*client.Client) error) client.APIClient {
-	ops = append([]func(*client.Client) error{client.FromEnv}, ops...)
-	clt, err := client.NewClientWithOpts(ops...)
-	assert.NilError(t, err)
-	return clt
-}
-
-// DaemonTime provides the current time on the daemon host
-func DaemonTime(ctx context.Context, t *testing.T, client client.APIClient, testEnv *environment.Execution) time.Time {
-	if testEnv.IsLocalDaemon() {
-		return time.Now()
-	}
-
-	info, err := client.Info(ctx)
-	assert.NilError(t, err)
-
-	dt, err := time.Parse(time.RFC3339Nano, info.SystemTime)
-	assert.NilError(t, err, "invalid time format in GET /info response")
-	return dt
-}
-
-// DaemonUnixTime returns the current time on the daemon host with nanoseconds precision.
-// It return the time formatted how the client sends timestamps to the server.
-func DaemonUnixTime(ctx context.Context, t *testing.T, client client.APIClient, testEnv *environment.Execution) string {
-	dt := DaemonTime(ctx, t, client, testEnv)
-	return fmt.Sprintf("%d.%09d", dt.Unix(), int64(dt.Nanosecond()))
-}

+ 1 - 1
integration/network/delete_test.go

@@ -5,7 +5,7 @@ import (
 	"testing"
 
 	"github.com/docker/docker/api/types"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
 )

+ 5 - 5
integration/session/session_test.go

@@ -4,7 +4,7 @@ import (
 	"net/http"
 	"testing"
 
-	req "github.com/docker/docker/integration-cli/request"
+	req "github.com/docker/docker/internal/test/request"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
 	"github.com/gotestyourself/gotestyourself/skip"
@@ -15,11 +15,11 @@ func TestSessionCreate(t *testing.T) {
 
 	defer setupTest(t)()
 
-	res, body, err := req.Post("/session", func(r *http.Request) error {
+	res, body, err := req.Post("/session", req.With(func(r *http.Request) error {
 		r.Header.Set("X-Docker-Expose-Session-Uuid", "testsessioncreate") // so we don't block default name if something else is using it
 		r.Header.Set("Upgrade", "h2c")
 		return nil
-	})
+	}))
 	assert.NilError(t, err)
 	assert.NilError(t, body.Close())
 	assert.Check(t, is.DeepEqual(res.StatusCode, http.StatusSwitchingProtocols))
@@ -36,10 +36,10 @@ func TestSessionCreateWithBadUpgrade(t *testing.T) {
 	assert.NilError(t, err)
 	assert.Check(t, is.Contains(string(buf), "no upgrade"))
 
-	res, body, err = req.Post("/session", func(r *http.Request) error {
+	res, body, err = req.Post("/session", req.With(func(r *http.Request) error {
 		r.Header.Set("Upgrade", "foo")
 		return nil
-	})
+	}))
 	assert.NilError(t, err)
 	assert.Check(t, is.DeepEqual(res.StatusCode, http.StatusBadRequest))
 	buf, err = req.ReadBody(body)

+ 2 - 2
integration/system/event_test.go

@@ -13,9 +13,9 @@ import (
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/api/types/strslice"
-	req "github.com/docker/docker/integration-cli/request"
 	"github.com/docker/docker/integration/internal/container"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
+	req "github.com/docker/docker/internal/test/request"
 	"github.com/docker/docker/pkg/jsonmessage"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"

+ 2 - 2
integration/system/info_linux_test.go

@@ -6,8 +6,8 @@ import (
 	"net/http"
 	"testing"
 
-	req "github.com/docker/docker/integration-cli/request"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
+	req "github.com/docker/docker/internal/test/request"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
 	"golang.org/x/net/context"

+ 1 - 1
integration/system/info_test.go

@@ -4,7 +4,7 @@ import (
 	"fmt"
 	"testing"
 
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
 	"golang.org/x/net/context"

+ 1 - 1
integration/system/login_test.go

@@ -4,8 +4,8 @@ import (
 	"testing"
 
 	"github.com/docker/docker/api/types"
-	"github.com/docker/docker/integration/internal/request"
 	"github.com/docker/docker/integration/internal/requirement"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
 	"github.com/gotestyourself/gotestyourself/skip"

+ 1 - 1
integration/system/version_test.go

@@ -3,7 +3,7 @@ package system // import "github.com/docker/docker/integration/system"
 import (
 	"testing"
 
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/gotestyourself/gotestyourself/assert"
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
 	"golang.org/x/net/context"

+ 1 - 1
integration/volume/volume_test.go

@@ -11,7 +11,7 @@ import (
 	"github.com/docker/docker/api/types/filters"
 	volumetypes "github.com/docker/docker/api/types/volume"
 	"github.com/docker/docker/integration/internal/container"
-	"github.com/docker/docker/integration/internal/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/docker/docker/internal/testutil"
 	"github.com/google/go-cmp/cmp/cmpopts"
 	"github.com/gotestyourself/gotestyourself/assert"

+ 33 - 0
internal/test/daemon/container.go

@@ -0,0 +1,33 @@
+package daemon
+
+import (
+	"context"
+
+	"github.com/docker/docker/api/types"
+	"github.com/gotestyourself/gotestyourself/assert"
+)
+
+// ActiveContainers returns the list of ids of the currently running containers
+func (d *Daemon) ActiveContainers(t assert.TestingT) []string {
+	cli := d.NewClientT(t)
+	defer cli.Close()
+
+	containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
+	assert.NilError(t, err)
+
+	ids := make([]string, len(containers))
+	for i, c := range containers {
+		ids[i] = c.ID
+	}
+	return ids
+}
+
+// FindContainerIP returns the ip of the specified container
+func (d *Daemon) FindContainerIP(t assert.TestingT, id string) string {
+	cli := d.NewClientT(t)
+	defer cli.Close()
+
+	i, err := cli.ContainerInspect(context.Background(), id)
+	assert.NilError(t, err)
+	return i.NetworkSettings.IPAddress
+}

+ 2 - 2
internal/test/daemon/daemon.go

@@ -16,7 +16,7 @@ import (
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/events"
 	"github.com/docker/docker/client"
-	"github.com/docker/docker/integration-cli/request"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/docker/docker/opts"
 	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/docker/pkg/stringid"
@@ -479,7 +479,7 @@ func (d *Daemon) ReloadConfig() error {
 	errCh := make(chan error)
 	started := make(chan struct{})
 	go func() {
-		_, body, err := request.DoOnHost(d.Sock(), "/events", request.Method(http.MethodGet))
+		_, body, err := request.Get("/events", request.Host(d.Sock()))
 		close(started)
 		if err != nil {
 			errCh <- err

+ 1 - 1
internal/test/fakestorage/storage.go

@@ -14,9 +14,9 @@ import (
 	"github.com/docker/docker/api/types"
 	containertypes "github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/client"
-	"github.com/docker/docker/integration-cli/request"
 	"github.com/docker/docker/internal/test/environment"
 	"github.com/docker/docker/internal/test/fakecontext"
+	"github.com/docker/docker/internal/test/request"
 	"github.com/docker/docker/internal/testutil"
 	"github.com/docker/go-connections/nat"
 	"github.com/gotestyourself/gotestyourself/assert"

+ 1 - 1
integration-cli/request/npipe.go → internal/test/request/npipe.go

@@ -1,6 +1,6 @@
 // +build !windows
 
-package request // import "github.com/docker/docker/integration-cli/request"
+package request
 
 import (
 	"net"

+ 1 - 1
integration-cli/request/npipe_windows.go → internal/test/request/npipe_windows.go

@@ -1,4 +1,4 @@
-package request // import "github.com/docker/docker/integration-cli/request"
+package request
 
 import (
 	"net"

+ 78 - 0
internal/test/request/ops.go

@@ -0,0 +1,78 @@
+package request
+
+import (
+	"bytes"
+	"encoding/json"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"strings"
+)
+
+// Options defines request options, like request modifiers and which host to target
+type Options struct {
+	host             string
+	requestModifiers []func(*http.Request) error
+}
+
+// Host creates a modifier that sets the specified host as the request URL host
+func Host(host string) func(*Options) {
+	return func(o *Options) {
+		o.host = host
+	}
+}
+
+// With adds a request modifier to the options
+func With(f func(*http.Request) error) func(*Options) {
+	return func(o *Options) {
+		o.requestModifiers = append(o.requestModifiers, f)
+	}
+}
+
+// Method creates a modifier that sets the specified string as the request method
+func Method(method string) func(*Options) {
+	return With(func(req *http.Request) error {
+		req.Method = method
+		return nil
+	})
+}
+
+// RawString sets the specified string as body for the request
+func RawString(content string) func(*Options) {
+	return RawContent(ioutil.NopCloser(strings.NewReader(content)))
+}
+
+// RawContent sets the specified reader as body for the request
+func RawContent(reader io.ReadCloser) func(*Options) {
+	return With(func(req *http.Request) error {
+		req.Body = reader
+		return nil
+	})
+}
+
+// ContentType sets the specified Content-Type request header
+func ContentType(contentType string) func(*Options) {
+	return With(func(req *http.Request) error {
+		req.Header.Set("Content-Type", contentType)
+		return nil
+	})
+}
+
+// JSON sets the Content-Type request header to json
+func JSON(o *Options) {
+	ContentType("application/json")(o)
+}
+
+// JSONBody creates a modifier that encodes the specified data to a JSON string and set it as request body. It also sets
+// the Content-Type header of the request.
+func JSONBody(data interface{}) func(*Options) {
+	return With(func(req *http.Request) error {
+		jsonData := bytes.NewBuffer(nil)
+		if err := json.NewEncoder(jsonData).Encode(data); err != nil {
+			return err
+		}
+		req.Body = ioutil.NopCloser(jsonData)
+		req.Header.Set("Content-Type", "application/json")
+		return nil
+	})
+}

+ 78 - 100
integration-cli/request/request.go → internal/test/request/request.go

@@ -1,9 +1,9 @@
-package request // import "github.com/docker/docker/integration-cli/request"
+package request // import "github.com/docker/docker/internal/test/request"
 
 import (
-	"bytes"
+	"context"
 	"crypto/tls"
-	"encoding/json"
+	"fmt"
 	"io"
 	"io/ioutil"
 	"net"
@@ -11,92 +11,75 @@ import (
 	"net/url"
 	"os"
 	"path/filepath"
-	"strings"
 	"time"
 
-	dclient "github.com/docker/docker/client"
+	"github.com/docker/docker/client"
+	"github.com/docker/docker/internal/test/environment"
 	"github.com/docker/docker/opts"
 	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/go-connections/sockets"
 	"github.com/docker/go-connections/tlsconfig"
+	"github.com/gotestyourself/gotestyourself/assert"
 	"github.com/pkg/errors"
 )
 
-// Method creates a modifier that sets the specified string as the request method
-func Method(method string) func(*http.Request) error {
-	return func(req *http.Request) error {
-		req.Method = method
-		return nil
-	}
-}
-
-// RawString sets the specified string as body for the request
-func RawString(content string) func(*http.Request) error {
-	return RawContent(ioutil.NopCloser(strings.NewReader(content)))
+// NewAPIClient returns a docker API client configured from environment variables
+func NewAPIClient(t assert.TestingT, ops ...func(*client.Client) error) client.APIClient {
+	ops = append([]func(*client.Client) error{client.FromEnv}, ops...)
+	clt, err := client.NewClientWithOpts(ops...)
+	assert.NilError(t, err)
+	return clt
 }
 
-// RawContent sets the specified reader as body for the request
-func RawContent(reader io.ReadCloser) func(*http.Request) error {
-	return func(req *http.Request) error {
-		req.Body = reader
-		return nil
+// DaemonTime provides the current time on the daemon host
+func DaemonTime(ctx context.Context, t assert.TestingT, client client.APIClient, testEnv *environment.Execution) time.Time {
+	if testEnv.IsLocalDaemon() {
+		return time.Now()
 	}
-}
 
-// ContentType sets the specified Content-Type request header
-func ContentType(contentType string) func(*http.Request) error {
-	return func(req *http.Request) error {
-		req.Header.Set("Content-Type", contentType)
-		return nil
-	}
-}
+	info, err := client.Info(ctx)
+	assert.NilError(t, err)
 
-// JSON sets the Content-Type request header to json
-func JSON(req *http.Request) error {
-	return ContentType("application/json")(req)
+	dt, err := time.Parse(time.RFC3339Nano, info.SystemTime)
+	assert.NilError(t, err, "invalid time format in GET /info response")
+	return dt
 }
 
-// JSONBody creates a modifier that encodes the specified data to a JSON string and set it as request body. It also sets
-// the Content-Type header of the request.
-func JSONBody(data interface{}) func(*http.Request) error {
-	return func(req *http.Request) error {
-		jsonData := bytes.NewBuffer(nil)
-		if err := json.NewEncoder(jsonData).Encode(data); err != nil {
-			return err
-		}
-		req.Body = ioutil.NopCloser(jsonData)
-		req.Header.Set("Content-Type", "application/json")
-		return nil
-	}
+// DaemonUnixTime returns the current time on the daemon host with nanoseconds precision.
+// It return the time formatted how the client sends timestamps to the server.
+func DaemonUnixTime(ctx context.Context, t assert.TestingT, client client.APIClient, testEnv *environment.Execution) string {
+	dt := DaemonTime(ctx, t, client, testEnv)
+	return fmt.Sprintf("%d.%09d", dt.Unix(), int64(dt.Nanosecond()))
 }
 
 // Post creates and execute a POST request on the specified host and endpoint, with the specified request modifiers
-func Post(endpoint string, modifiers ...func(*http.Request) error) (*http.Response, io.ReadCloser, error) {
+func Post(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) {
 	return Do(endpoint, append(modifiers, Method(http.MethodPost))...)
 }
 
 // Delete creates and execute a DELETE request on the specified host and endpoint, with the specified request modifiers
-func Delete(endpoint string, modifiers ...func(*http.Request) error) (*http.Response, io.ReadCloser, error) {
+func Delete(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) {
 	return Do(endpoint, append(modifiers, Method(http.MethodDelete))...)
 }
 
 // Get creates and execute a GET request on the specified host and endpoint, with the specified request modifiers
-func Get(endpoint string, modifiers ...func(*http.Request) error) (*http.Response, io.ReadCloser, error) {
+func Get(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) {
 	return Do(endpoint, modifiers...)
 }
 
 // Do creates and execute a request on the specified endpoint, with the specified request modifiers
-func Do(endpoint string, modifiers ...func(*http.Request) error) (*http.Response, io.ReadCloser, error) {
-	return DoOnHost(DaemonHost(), endpoint, modifiers...)
-}
-
-// DoOnHost creates and execute a request on the specified host and endpoint, with the specified request modifiers
-func DoOnHost(host, endpoint string, modifiers ...func(*http.Request) error) (*http.Response, io.ReadCloser, error) {
-	req, err := newRequest(host, endpoint, modifiers...)
+func Do(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) {
+	opts := &Options{
+		host: DaemonHost(),
+	}
+	for _, mod := range modifiers {
+		mod(opts)
+	}
+	req, err := newRequest(endpoint, opts)
 	if err != nil {
 		return nil, nil, err
 	}
-	client, err := newHTTPClient(host)
+	client, err := newHTTPClient(opts.host)
 	if err != nil {
 		return nil, nil, err
 	}
@@ -111,11 +94,17 @@ func DoOnHost(host, endpoint string, modifiers ...func(*http.Request) error) (*h
 	return resp, body, err
 }
 
+// ReadBody read the specified ReadCloser content and returns it
+func ReadBody(b io.ReadCloser) ([]byte, error) {
+	defer b.Close()
+	return ioutil.ReadAll(b)
+}
+
 // newRequest creates a new http Request to the specified host and endpoint, with the specified request modifiers
-func newRequest(host, endpoint string, modifiers ...func(*http.Request) error) (*http.Request, error) {
-	hostUrl, err := dclient.ParseHostURL(host)
+func newRequest(endpoint string, opts *Options) (*http.Request, error) {
+	hostURL, err := client.ParseHostURL(opts.host)
 	if err != nil {
-		return nil, errors.Wrapf(err, "failed parsing url %q", host)
+		return nil, errors.Wrapf(err, "failed parsing url %q", opts.host)
 	}
 	req, err := http.NewRequest("GET", endpoint, nil)
 	if err != nil {
@@ -127,13 +116,14 @@ func newRequest(host, endpoint string, modifiers ...func(*http.Request) error) (
 	} else {
 		req.URL.Scheme = "http"
 	}
-	req.URL.Host = hostUrl.Host
+	req.URL.Host = hostURL.Host
 
-	for _, config := range modifiers {
+	for _, config := range opts.requestModifiers {
 		if err := config(req); err != nil {
 			return nil, err
 		}
 	}
+
 	return req, nil
 }
 
@@ -141,12 +131,12 @@ func newRequest(host, endpoint string, modifiers ...func(*http.Request) error) (
 // TODO: Share more code with client.defaultHTTPClient
 func newHTTPClient(host string) (*http.Client, error) {
 	// FIXME(vdemeester) 10*time.Second timeout of SockRequest… ?
-	hostUrl, err := dclient.ParseHostURL(host)
+	hostURL, err := client.ParseHostURL(host)
 	if err != nil {
 		return nil, err
 	}
 	transport := new(http.Transport)
-	if hostUrl.Scheme == "tcp" && os.Getenv("DOCKER_TLS_VERIFY") != "" {
+	if hostURL.Scheme == "tcp" && os.Getenv("DOCKER_TLS_VERIFY") != "" {
 		// Setup the socket TLS configuration.
 		tlsConfig, err := getTLSConfig()
 		if err != nil {
@@ -155,20 +145,37 @@ func newHTTPClient(host string) (*http.Client, error) {
 		transport = &http.Transport{TLSClientConfig: tlsConfig}
 	}
 	transport.DisableKeepAlives = true
-	err = sockets.ConfigureTransport(transport, hostUrl.Scheme, hostUrl.Host)
+	err = sockets.ConfigureTransport(transport, hostURL.Scheme, hostURL.Host)
 	return &http.Client{Transport: transport}, err
 }
 
-// NewClient returns a new Docker API client
-// Deprecated: Use Execution.APIClient()
-func NewClient() (dclient.APIClient, error) {
-	return dclient.NewClientWithOpts(dclient.WithHost(DaemonHost()))
+func getTLSConfig() (*tls.Config, error) {
+	dockerCertPath := os.Getenv("DOCKER_CERT_PATH")
+
+	if dockerCertPath == "" {
+		return nil, errors.New("DOCKER_TLS_VERIFY specified, but no DOCKER_CERT_PATH environment variable")
+	}
+
+	option := &tlsconfig.Options{
+		CAFile:   filepath.Join(dockerCertPath, "ca.pem"),
+		CertFile: filepath.Join(dockerCertPath, "cert.pem"),
+		KeyFile:  filepath.Join(dockerCertPath, "key.pem"),
+	}
+	tlsConfig, err := tlsconfig.Client(*option)
+	if err != nil {
+		return nil, err
+	}
+
+	return tlsConfig, nil
 }
 
-// ReadBody read the specified ReadCloser content and returns it
-func ReadBody(b io.ReadCloser) ([]byte, error) {
-	defer b.Close()
-	return ioutil.ReadAll(b)
+// 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
 }
 
 // SockConn opens a connection on the specified socket
@@ -199,32 +206,3 @@ func SockConn(timeout time.Duration, daemon string) (net.Conn, error) {
 		return c, errors.Errorf("unknown scheme %v (%s)", daemonURL.Scheme, daemon)
 	}
 }
-
-func getTLSConfig() (*tls.Config, error) {
-	dockerCertPath := os.Getenv("DOCKER_CERT_PATH")
-
-	if dockerCertPath == "" {
-		return nil, errors.New("DOCKER_TLS_VERIFY specified, but no DOCKER_CERT_PATH environment variable")
-	}
-
-	option := &tlsconfig.Options{
-		CAFile:   filepath.Join(dockerCertPath, "ca.pem"),
-		CertFile: filepath.Join(dockerCertPath, "cert.pem"),
-		KeyFile:  filepath.Join(dockerCertPath, "key.pem"),
-	}
-	tlsConfig, err := tlsconfig.Client(*option)
-	if err != nil {
-		return nil, err
-	}
-
-	return tlsConfig, nil
-}
-
-// 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
-}