Browse code

Move integration-cli/request to internal/test/request…

… and change a bit the method signature

Signed-off-by: Vincent Demeester <vincent@sbr.pm>

Vincent Demeester authored on 2018/04/17 17:22:04
Showing 62 changed files
... ...
@@ -118,21 +118,6 @@ func (d *Daemon) WaitRun(contID string) error {
118 118
 	return WaitInspectWithArgs(d.dockerBinary, contID, "{{.State.Running}}", "true", 10*time.Second, args...)
119 119
 }
120 120
 
121
-// CmdRetryOutOfSequence tries the specified command against the current daemon for 10 times
122
-func (d *Daemon) CmdRetryOutOfSequence(args ...string) (string, error) {
123
-	for i := 0; ; i++ {
124
-		out, err := d.Cmd(args...)
125
-		if err != nil {
126
-			if strings.Contains(out, "update out of sequence") {
127
-				if i < 10 {
128
-					continue
129
-				}
130
-			}
131
-		}
132
-		return out, err
133
-	}
134
-}
135
-
136 121
 // WaitInspectWithArgs waits for the specified expression to be equals to the specified expected string in the given time.
137 122
 // Deprecated: use cli.WaitCmd instead
138 123
 func WaitInspectWithArgs(dockerBinary, name, expr, expected string, timeout time.Duration, arg ...string) error {
... ...
@@ -15,7 +15,7 @@ import (
15 15
 	"github.com/docker/docker/api/types"
16 16
 	"github.com/docker/docker/client"
17 17
 	"github.com/docker/docker/integration-cli/checker"
18
-	"github.com/docker/docker/integration-cli/request"
18
+	"github.com/docker/docker/internal/test/request"
19 19
 	"github.com/docker/docker/pkg/stdcopy"
20 20
 	"github.com/go-check/check"
21 21
 	"golang.org/x/net/websocket"
... ...
@@ -13,10 +13,10 @@ import (
13 13
 
14 14
 	"github.com/docker/docker/api/types"
15 15
 	"github.com/docker/docker/integration-cli/checker"
16
-	"github.com/docker/docker/integration-cli/request"
17 16
 	"github.com/docker/docker/internal/test/fakecontext"
18 17
 	"github.com/docker/docker/internal/test/fakegit"
19 18
 	"github.com/docker/docker/internal/test/fakestorage"
19
+	"github.com/docker/docker/internal/test/request"
20 20
 	"github.com/go-check/check"
21 21
 	"github.com/gotestyourself/gotestyourself/assert"
22 22
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
... ...
@@ -24,7 +24,7 @@ import (
24 24
 	"github.com/docker/docker/integration-cli/checker"
25 25
 	"github.com/docker/docker/integration-cli/cli"
26 26
 	"github.com/docker/docker/integration-cli/cli/build"
27
-	"github.com/docker/docker/integration-cli/request"
27
+	"github.com/docker/docker/internal/test/request"
28 28
 	"github.com/docker/docker/pkg/ioutils"
29 29
 	"github.com/docker/docker/pkg/mount"
30 30
 	"github.com/docker/docker/pkg/stringid"
... ...
@@ -1254,13 +1254,13 @@ func (s *DockerSuite) TestContainerAPIChunkedEncoding(c *check.C) {
1254 1254
 		"OpenStdin": true,
1255 1255
 	}
1256 1256
 
1257
-	resp, _, err := request.Post("/containers/create", request.JSONBody(config), func(req *http.Request) error {
1257
+	resp, _, err := request.Post("/containers/create", request.JSONBody(config), request.With(func(req *http.Request) error {
1258 1258
 		// This is a cheat to make the http request do chunked encoding
1259 1259
 		// Otherwise (just setting the Content-Encoding to chunked) net/http will overwrite
1260 1260
 		// https://golang.org/src/pkg/net/http/request.go?s=11980:12172
1261 1261
 		req.ContentLength = -1
1262 1262
 		return nil
1263
-	})
1263
+	}))
1264 1264
 	c.Assert(err, checker.IsNil, check.Commentf("error creating container with chunked encoding"))
1265 1265
 	defer resp.Body.Close()
1266 1266
 	c.Assert(resp.StatusCode, checker.Equals, http.StatusCreated)
... ...
@@ -7,7 +7,7 @@ import (
7 7
 
8 8
 	"github.com/docker/docker/api/types/container"
9 9
 	"github.com/docker/docker/integration-cli/checker"
10
-	"github.com/docker/docker/integration-cli/request"
10
+	"github.com/docker/docker/internal/test/request"
11 11
 	"github.com/go-check/check"
12 12
 )
13 13
 
... ...
@@ -10,7 +10,7 @@ import (
10 10
 	"sync"
11 11
 
12 12
 	"github.com/docker/docker/integration-cli/checker"
13
-	"github.com/docker/docker/integration-cli/request"
13
+	"github.com/docker/docker/internal/test/request"
14 14
 	"github.com/go-check/check"
15 15
 )
16 16
 
... ...
@@ -15,7 +15,7 @@ import (
15 15
 	"github.com/docker/docker/api/types"
16 16
 	"github.com/docker/docker/client"
17 17
 	"github.com/docker/docker/integration-cli/checker"
18
-	"github.com/docker/docker/integration-cli/request"
18
+	"github.com/docker/docker/internal/test/request"
19 19
 	"github.com/go-check/check"
20 20
 	"golang.org/x/net/context"
21 21
 )
... ...
@@ -11,7 +11,7 @@ import (
11 11
 	"github.com/docker/docker/integration-cli/checker"
12 12
 	"github.com/docker/docker/integration-cli/cli"
13 13
 	"github.com/docker/docker/integration-cli/cli/build"
14
-	"github.com/docker/docker/integration-cli/request"
14
+	"github.com/docker/docker/internal/test/request"
15 15
 	"github.com/go-check/check"
16 16
 	"golang.org/x/net/context"
17 17
 )
... ...
@@ -14,7 +14,7 @@ import (
14 14
 	"github.com/docker/docker/api/types"
15 15
 	"github.com/docker/docker/client"
16 16
 	"github.com/docker/docker/integration-cli/checker"
17
-	"github.com/docker/docker/integration-cli/request"
17
+	"github.com/docker/docker/internal/test/request"
18 18
 	"github.com/docker/docker/pkg/stdcopy"
19 19
 	"github.com/go-check/check"
20 20
 	"golang.org/x/net/context"
... ...
@@ -12,7 +12,7 @@ import (
12 12
 	"github.com/docker/docker/api/types/filters"
13 13
 	"github.com/docker/docker/api/types/network"
14 14
 	"github.com/docker/docker/integration-cli/checker"
15
-	"github.com/docker/docker/integration-cli/request"
15
+	"github.com/docker/docker/internal/test/request"
16 16
 	"github.com/go-check/check"
17 17
 )
18 18
 
... ...
@@ -15,7 +15,7 @@ import (
15 15
 	"github.com/docker/docker/api/types/versions"
16 16
 	"github.com/docker/docker/client"
17 17
 	"github.com/docker/docker/integration-cli/checker"
18
-	"github.com/docker/docker/integration-cli/request"
18
+	"github.com/docker/docker/internal/test/request"
19 19
 	"github.com/go-check/check"
20 20
 	"golang.org/x/net/context"
21 21
 )
... ...
@@ -22,8 +22,8 @@ import (
22 22
 	"github.com/docker/docker/client"
23 23
 	"github.com/docker/docker/integration-cli/checker"
24 24
 	"github.com/docker/docker/integration-cli/daemon"
25
-	"github.com/docker/docker/integration-cli/request"
26 25
 	testdaemon "github.com/docker/docker/internal/test/daemon"
26
+	"github.com/docker/docker/internal/test/request"
27 27
 	"github.com/docker/swarmkit/ca"
28 28
 	"github.com/go-check/check"
29 29
 	"github.com/gotestyourself/gotestyourself/assert"
... ...
@@ -242,7 +242,7 @@ func (s *DockerSwarmSuite) TestAPISwarmPromoteDemote(c *check.C) {
242 242
 	node := d1.GetNode(c, d1.NodeID())
243 243
 	node.Spec.Role = swarm.NodeRoleWorker
244 244
 	url := fmt.Sprintf("/nodes/%s/update?version=%d", node.ID, node.Version.Index)
245
-	res, body, err := request.DoOnHost(d1.Sock(), url, request.Method("POST"), request.JSONBody(node.Spec))
245
+	res, body, err := request.Post(url, request.Host(d1.Sock()), request.JSONBody(node.Spec))
246 246
 	c.Assert(err, checker.IsNil)
247 247
 	b, err := request.ReadBody(body)
248 248
 	c.Assert(err, checker.IsNil)
... ...
@@ -529,7 +529,7 @@ func (s *DockerSwarmSuite) TestAPISwarmInvalidAddress(c *check.C) {
529 529
 	req := swarm.InitRequest{
530 530
 		ListenAddr: "",
531 531
 	}
532
-	res, _, err := request.DoOnHost(d.Sock(), "/swarm/init", request.Method("POST"), request.JSONBody(req))
532
+	res, _, err := request.Post("/swarm/init", request.Host(d.Sock()), request.JSONBody(req))
533 533
 	c.Assert(err, checker.IsNil)
534 534
 	c.Assert(res.StatusCode, checker.Equals, http.StatusBadRequest)
535 535
 
... ...
@@ -537,7 +537,7 @@ func (s *DockerSwarmSuite) TestAPISwarmInvalidAddress(c *check.C) {
537 537
 		ListenAddr:  "0.0.0.0:2377",
538 538
 		RemoteAddrs: []string{""},
539 539
 	}
540
-	res, _, err = request.DoOnHost(d.Sock(), "/swarm/join", request.Method("POST"), request.JSONBody(req2))
540
+	res, _, err = request.Post("/swarm/join", request.Host(d.Sock()), request.JSONBody(req2))
541 541
 	c.Assert(err, checker.IsNil)
542 542
 	c.Assert(res.StatusCode, checker.Equals, http.StatusBadRequest)
543 543
 }
... ...
@@ -10,7 +10,7 @@ import (
10 10
 
11 11
 	"github.com/docker/docker/api"
12 12
 	"github.com/docker/docker/integration-cli/checker"
13
-	"github.com/docker/docker/integration-cli/request"
13
+	"github.com/docker/docker/internal/test/request"
14 14
 	"github.com/go-check/check"
15 15
 )
16 16
 
... ...
@@ -13,7 +13,7 @@ import (
13 13
 	"github.com/docker/docker/api/types"
14 14
 	"github.com/docker/docker/client"
15 15
 	"github.com/docker/docker/integration-cli/checker"
16
-	"github.com/docker/docker/integration-cli/request"
16
+	"github.com/docker/docker/internal/test/request"
17 17
 	"github.com/docker/docker/pkg/parsers/kernel"
18 18
 	"github.com/go-check/check"
19 19
 	"github.com/kr/pty"
... ...
@@ -8,7 +8,7 @@ import (
8 8
 	"strings"
9 9
 
10 10
 	"github.com/docker/docker/integration-cli/checker"
11
-	"github.com/docker/docker/integration-cli/request"
11
+	"github.com/docker/docker/internal/test/request"
12 12
 	"github.com/go-check/check"
13 13
 )
14 14
 
... ...
@@ -6,7 +6,7 @@ import (
6 6
 	"fmt"
7 7
 
8 8
 	"github.com/docker/docker/integration-cli/checker"
9
-	"github.com/docker/docker/integration-cli/request"
9
+	"github.com/docker/docker/internal/test/request"
10 10
 	"github.com/go-check/check"
11 11
 )
12 12
 
... ...
@@ -18,7 +18,7 @@ import (
18 18
 	"github.com/docker/docker/integration-cli/checker"
19 19
 	"github.com/docker/docker/integration-cli/cli"
20 20
 	"github.com/docker/docker/integration-cli/daemon"
21
-	"github.com/docker/docker/integration-cli/request"
21
+	"github.com/docker/docker/internal/test/request"
22 22
 	"github.com/go-check/check"
23 23
 	"github.com/gotestyourself/gotestyourself/icmd"
24 24
 	"golang.org/x/net/context"
25 25
deleted file mode 100644
... ...
@@ -1,12 +0,0 @@
1
-// +build !windows
2
-
3
-package request // import "github.com/docker/docker/integration-cli/request"
4
-
5
-import (
6
-	"net"
7
-	"time"
8
-)
9
-
10
-func npipeDial(path string, timeout time.Duration) (net.Conn, error) {
11
-	panic("npipe protocol only supported on Windows")
12
-}
13 1
deleted file mode 100644
... ...
@@ -1,12 +0,0 @@
1
-package request // import "github.com/docker/docker/integration-cli/request"
2
-
3
-import (
4
-	"net"
5
-	"time"
6
-
7
-	"github.com/Microsoft/go-winio"
8
-)
9
-
10
-func npipeDial(path string, timeout time.Duration) (net.Conn, error) {
11
-	return winio.DialPipe(path, &timeout)
12
-}
13 1
deleted file mode 100644
... ...
@@ -1,230 +0,0 @@
1
-package request // import "github.com/docker/docker/integration-cli/request"
2
-
3
-import (
4
-	"bytes"
5
-	"crypto/tls"
6
-	"encoding/json"
7
-	"io"
8
-	"io/ioutil"
9
-	"net"
10
-	"net/http"
11
-	"net/url"
12
-	"os"
13
-	"path/filepath"
14
-	"strings"
15
-	"time"
16
-
17
-	dclient "github.com/docker/docker/client"
18
-	"github.com/docker/docker/opts"
19
-	"github.com/docker/docker/pkg/ioutils"
20
-	"github.com/docker/go-connections/sockets"
21
-	"github.com/docker/go-connections/tlsconfig"
22
-	"github.com/pkg/errors"
23
-)
24
-
25
-// Method creates a modifier that sets the specified string as the request method
26
-func Method(method string) func(*http.Request) error {
27
-	return func(req *http.Request) error {
28
-		req.Method = method
29
-		return nil
30
-	}
31
-}
32
-
33
-// RawString sets the specified string as body for the request
34
-func RawString(content string) func(*http.Request) error {
35
-	return RawContent(ioutil.NopCloser(strings.NewReader(content)))
36
-}
37
-
38
-// RawContent sets the specified reader as body for the request
39
-func RawContent(reader io.ReadCloser) func(*http.Request) error {
40
-	return func(req *http.Request) error {
41
-		req.Body = reader
42
-		return nil
43
-	}
44
-}
45
-
46
-// ContentType sets the specified Content-Type request header
47
-func ContentType(contentType string) func(*http.Request) error {
48
-	return func(req *http.Request) error {
49
-		req.Header.Set("Content-Type", contentType)
50
-		return nil
51
-	}
52
-}
53
-
54
-// JSON sets the Content-Type request header to json
55
-func JSON(req *http.Request) error {
56
-	return ContentType("application/json")(req)
57
-}
58
-
59
-// JSONBody creates a modifier that encodes the specified data to a JSON string and set it as request body. It also sets
60
-// the Content-Type header of the request.
61
-func JSONBody(data interface{}) func(*http.Request) error {
62
-	return func(req *http.Request) error {
63
-		jsonData := bytes.NewBuffer(nil)
64
-		if err := json.NewEncoder(jsonData).Encode(data); err != nil {
65
-			return err
66
-		}
67
-		req.Body = ioutil.NopCloser(jsonData)
68
-		req.Header.Set("Content-Type", "application/json")
69
-		return nil
70
-	}
71
-}
72
-
73
-// Post creates and execute a POST request on the specified host and endpoint, with the specified request modifiers
74
-func Post(endpoint string, modifiers ...func(*http.Request) error) (*http.Response, io.ReadCloser, error) {
75
-	return Do(endpoint, append(modifiers, Method(http.MethodPost))...)
76
-}
77
-
78
-// Delete creates and execute a DELETE request on the specified host and endpoint, with the specified request modifiers
79
-func Delete(endpoint string, modifiers ...func(*http.Request) error) (*http.Response, io.ReadCloser, error) {
80
-	return Do(endpoint, append(modifiers, Method(http.MethodDelete))...)
81
-}
82
-
83
-// Get creates and execute a GET request on the specified host and endpoint, with the specified request modifiers
84
-func Get(endpoint string, modifiers ...func(*http.Request) error) (*http.Response, io.ReadCloser, error) {
85
-	return Do(endpoint, modifiers...)
86
-}
87
-
88
-// Do creates and execute a request on the specified endpoint, with the specified request modifiers
89
-func Do(endpoint string, modifiers ...func(*http.Request) error) (*http.Response, io.ReadCloser, error) {
90
-	return DoOnHost(DaemonHost(), endpoint, modifiers...)
91
-}
92
-
93
-// DoOnHost creates and execute a request on the specified host and endpoint, with the specified request modifiers
94
-func DoOnHost(host, endpoint string, modifiers ...func(*http.Request) error) (*http.Response, io.ReadCloser, error) {
95
-	req, err := newRequest(host, endpoint, modifiers...)
96
-	if err != nil {
97
-		return nil, nil, err
98
-	}
99
-	client, err := newHTTPClient(host)
100
-	if err != nil {
101
-		return nil, nil, err
102
-	}
103
-	resp, err := client.Do(req)
104
-	var body io.ReadCloser
105
-	if resp != nil {
106
-		body = ioutils.NewReadCloserWrapper(resp.Body, func() error {
107
-			defer resp.Body.Close()
108
-			return nil
109
-		})
110
-	}
111
-	return resp, body, err
112
-}
113
-
114
-// newRequest creates a new http Request to the specified host and endpoint, with the specified request modifiers
115
-func newRequest(host, endpoint string, modifiers ...func(*http.Request) error) (*http.Request, error) {
116
-	hostUrl, err := dclient.ParseHostURL(host)
117
-	if err != nil {
118
-		return nil, errors.Wrapf(err, "failed parsing url %q", host)
119
-	}
120
-	req, err := http.NewRequest("GET", endpoint, nil)
121
-	if err != nil {
122
-		return nil, errors.Wrap(err, "failed to create request")
123
-	}
124
-
125
-	if os.Getenv("DOCKER_TLS_VERIFY") != "" {
126
-		req.URL.Scheme = "https"
127
-	} else {
128
-		req.URL.Scheme = "http"
129
-	}
130
-	req.URL.Host = hostUrl.Host
131
-
132
-	for _, config := range modifiers {
133
-		if err := config(req); err != nil {
134
-			return nil, err
135
-		}
136
-	}
137
-	return req, nil
138
-}
139
-
140
-// newHTTPClient creates an http client for the specific host
141
-// TODO: Share more code with client.defaultHTTPClient
142
-func newHTTPClient(host string) (*http.Client, error) {
143
-	// FIXME(vdemeester) 10*time.Second timeout of SockRequest… ?
144
-	hostUrl, err := dclient.ParseHostURL(host)
145
-	if err != nil {
146
-		return nil, err
147
-	}
148
-	transport := new(http.Transport)
149
-	if hostUrl.Scheme == "tcp" && os.Getenv("DOCKER_TLS_VERIFY") != "" {
150
-		// Setup the socket TLS configuration.
151
-		tlsConfig, err := getTLSConfig()
152
-		if err != nil {
153
-			return nil, err
154
-		}
155
-		transport = &http.Transport{TLSClientConfig: tlsConfig}
156
-	}
157
-	transport.DisableKeepAlives = true
158
-	err = sockets.ConfigureTransport(transport, hostUrl.Scheme, hostUrl.Host)
159
-	return &http.Client{Transport: transport}, err
160
-}
161
-
162
-// NewClient returns a new Docker API client
163
-// Deprecated: Use Execution.APIClient()
164
-func NewClient() (dclient.APIClient, error) {
165
-	return dclient.NewClientWithOpts(dclient.WithHost(DaemonHost()))
166
-}
167
-
168
-// ReadBody read the specified ReadCloser content and returns it
169
-func ReadBody(b io.ReadCloser) ([]byte, error) {
170
-	defer b.Close()
171
-	return ioutil.ReadAll(b)
172
-}
173
-
174
-// SockConn opens a connection on the specified socket
175
-func SockConn(timeout time.Duration, daemon string) (net.Conn, error) {
176
-	daemonURL, err := url.Parse(daemon)
177
-	if err != nil {
178
-		return nil, errors.Wrapf(err, "could not parse url %q", daemon)
179
-	}
180
-
181
-	var c net.Conn
182
-	switch daemonURL.Scheme {
183
-	case "npipe":
184
-		return npipeDial(daemonURL.Path, timeout)
185
-	case "unix":
186
-		return net.DialTimeout(daemonURL.Scheme, daemonURL.Path, timeout)
187
-	case "tcp":
188
-		if os.Getenv("DOCKER_TLS_VERIFY") != "" {
189
-			// Setup the socket TLS configuration.
190
-			tlsConfig, err := getTLSConfig()
191
-			if err != nil {
192
-				return nil, err
193
-			}
194
-			dialer := &net.Dialer{Timeout: timeout}
195
-			return tls.DialWithDialer(dialer, daemonURL.Scheme, daemonURL.Host, tlsConfig)
196
-		}
197
-		return net.DialTimeout(daemonURL.Scheme, daemonURL.Host, timeout)
198
-	default:
199
-		return c, errors.Errorf("unknown scheme %v (%s)", daemonURL.Scheme, daemon)
200
-	}
201
-}
202
-
203
-func getTLSConfig() (*tls.Config, error) {
204
-	dockerCertPath := os.Getenv("DOCKER_CERT_PATH")
205
-
206
-	if dockerCertPath == "" {
207
-		return nil, errors.New("DOCKER_TLS_VERIFY specified, but no DOCKER_CERT_PATH environment variable")
208
-	}
209
-
210
-	option := &tlsconfig.Options{
211
-		CAFile:   filepath.Join(dockerCertPath, "ca.pem"),
212
-		CertFile: filepath.Join(dockerCertPath, "cert.pem"),
213
-		KeyFile:  filepath.Join(dockerCertPath, "key.pem"),
214
-	}
215
-	tlsConfig, err := tlsconfig.Client(*option)
216
-	if err != nil {
217
-		return nil, err
218
-	}
219
-
220
-	return tlsConfig, nil
221
-}
222
-
223
-// DaemonHost return the daemon host string for this test execution
224
-func DaemonHost() string {
225
-	daemonURLStr := "unix://" + opts.DefaultUnixSocket
226
-	if daemonHostVar := os.Getenv("DOCKER_HOST"); daemonHostVar != "" {
227
-		daemonURLStr = daemonHostVar
228
-	}
229
-	return daemonURLStr
230
-}
... ...
@@ -8,9 +8,9 @@ import (
8 8
 	"testing"
9 9
 
10 10
 	dclient "github.com/docker/docker/client"
11
-	"github.com/docker/docker/integration-cli/request"
12 11
 	"github.com/docker/docker/internal/test/daemon"
13 12
 	"github.com/docker/docker/internal/test/fakecontext"
13
+	"github.com/docker/docker/internal/test/request"
14 14
 	"github.com/gotestyourself/gotestyourself/assert"
15 15
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
16 16
 	"github.com/moby/buildkit/session"
... ...
@@ -65,8 +65,9 @@ func TestBuildWithSession(t *testing.T) {
65 65
 	// rebuild with regular tar, confirm cache still applies
66 66
 	fctx.Add("Dockerfile", dockerfile)
67 67
 	// FIXME(vdemeester) use sock here
68
-	res, body, err := request.DoOnHost(d.Sock(),
68
+	res, body, err := request.Do(
69 69
 		"/build",
70
+		request.Host(d.Sock()),
70 71
 		request.Method(http.MethodPost),
71 72
 		request.RawContent(fctx.AsTarReader(t)),
72 73
 		request.ContentType("application/x-tar"))
... ...
@@ -103,14 +104,14 @@ func testBuildWithSession(t *testing.T, client dclient.APIClient, daemonSock str
103 103
 
104 104
 	g.Go(func() error {
105 105
 		// FIXME use sock here
106
-		res, body, err := request.DoOnHost(
107
-			daemonSock,
106
+		res, body, err := request.Do(
108 107
 			"/build?remote=client-session&session="+sess.ID(),
108
+			request.Host(daemonSock),
109 109
 			request.Method(http.MethodPost),
110
-			func(req *http.Request) error {
110
+			request.With(func(req *http.Request) error {
111 111
 				req.Body = ioutil.NopCloser(strings.NewReader(dockerfile))
112 112
 				return nil
113
-			},
113
+			}),
114 114
 		)
115 115
 		if err != nil {
116 116
 			return err
... ...
@@ -13,8 +13,8 @@ import (
13 13
 	"github.com/docker/docker/api/types"
14 14
 	"github.com/docker/docker/api/types/filters"
15 15
 	"github.com/docker/docker/api/types/versions"
16
-	"github.com/docker/docker/integration/internal/request"
17 16
 	"github.com/docker/docker/internal/test/fakecontext"
17
+	"github.com/docker/docker/internal/test/request"
18 18
 	"github.com/docker/docker/pkg/jsonmessage"
19 19
 	"github.com/gotestyourself/gotestyourself/assert"
20 20
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
... ...
@@ -7,7 +7,7 @@ import (
7 7
 
8 8
 	"github.com/docker/docker/api/types/container"
9 9
 	"github.com/docker/docker/api/types/network"
10
-	"github.com/docker/docker/integration/internal/request"
10
+	"github.com/docker/docker/internal/test/request"
11 11
 	"github.com/docker/docker/internal/testutil"
12 12
 	"github.com/gotestyourself/gotestyourself/skip"
13 13
 )
... ...
@@ -7,7 +7,7 @@ import (
7 7
 
8 8
 	containertypes "github.com/docker/docker/api/types/container"
9 9
 	"github.com/docker/docker/integration/internal/container"
10
-	"github.com/docker/docker/integration/internal/request"
10
+	"github.com/docker/docker/internal/test/request"
11 11
 	"github.com/docker/docker/pkg/archive"
12 12
 	"github.com/gotestyourself/gotestyourself/assert"
13 13
 	"github.com/gotestyourself/gotestyourself/poll"
... ...
@@ -8,7 +8,7 @@ import (
8 8
 	"github.com/docker/docker/api/types"
9 9
 	"github.com/docker/docker/api/types/strslice"
10 10
 	"github.com/docker/docker/integration/internal/container"
11
-	"github.com/docker/docker/integration/internal/request"
11
+	"github.com/docker/docker/internal/test/request"
12 12
 	"github.com/gotestyourself/gotestyourself/assert"
13 13
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
14 14
 )
... ...
@@ -9,8 +9,8 @@ import (
9 9
 	"github.com/docker/docker/api/types"
10 10
 	"github.com/docker/docker/api/types/filters"
11 11
 	"github.com/docker/docker/integration/internal/container"
12
-	"github.com/docker/docker/integration/internal/request"
13 12
 	"github.com/docker/docker/internal/test/daemon"
13
+	"github.com/docker/docker/internal/test/request"
14 14
 	"github.com/docker/docker/pkg/jsonmessage"
15 15
 	"github.com/gotestyourself/gotestyourself/assert"
16 16
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
... ...
@@ -9,7 +9,7 @@ import (
9 9
 	containertypes "github.com/docker/docker/api/types/container"
10 10
 	"github.com/docker/docker/client"
11 11
 	"github.com/docker/docker/integration/internal/container"
12
-	"github.com/docker/docker/integration/internal/request"
12
+	"github.com/docker/docker/internal/test/request"
13 13
 	"github.com/gotestyourself/gotestyourself/poll"
14 14
 )
15 15
 
... ...
@@ -8,7 +8,7 @@ import (
8 8
 
9 9
 	"github.com/docker/docker/client"
10 10
 	"github.com/docker/docker/integration/internal/container"
11
-	"github.com/docker/docker/integration/internal/request"
11
+	"github.com/docker/docker/internal/test/request"
12 12
 	"github.com/gotestyourself/gotestyourself/assert"
13 13
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
14 14
 	"github.com/gotestyourself/gotestyourself/poll"
... ...
@@ -8,7 +8,7 @@ import (
8 8
 	containertypes "github.com/docker/docker/api/types/container"
9 9
 	"github.com/docker/docker/client"
10 10
 	"github.com/docker/docker/integration/internal/container"
11
-	"github.com/docker/docker/integration/internal/request"
11
+	"github.com/docker/docker/internal/test/request"
12 12
 	"github.com/gotestyourself/gotestyourself/assert"
13 13
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
14 14
 	"github.com/gotestyourself/gotestyourself/poll"
... ...
@@ -9,7 +9,7 @@ import (
9 9
 	"github.com/docker/docker/api/types"
10 10
 	"github.com/docker/docker/api/types/filters"
11 11
 	"github.com/docker/docker/integration/internal/container"
12
-	"github.com/docker/docker/integration/internal/request"
12
+	"github.com/docker/docker/internal/test/request"
13 13
 	"github.com/gotestyourself/gotestyourself/assert"
14 14
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
15 15
 	"github.com/gotestyourself/gotestyourself/skip"
... ...
@@ -7,7 +7,7 @@ import (
7 7
 
8 8
 	"github.com/docker/docker/api/types"
9 9
 	"github.com/docker/docker/integration/internal/container"
10
-	"github.com/docker/docker/integration/internal/request"
10
+	"github.com/docker/docker/internal/test/request"
11 11
 	"github.com/docker/docker/pkg/stdcopy"
12 12
 	"github.com/gotestyourself/gotestyourself/assert"
13 13
 	"github.com/gotestyourself/gotestyourself/skip"
... ...
@@ -11,7 +11,7 @@ import (
11 11
 	"github.com/docker/docker/api/types/mount"
12 12
 	"github.com/docker/docker/api/types/network"
13 13
 	"github.com/docker/docker/client"
14
-	"github.com/docker/docker/integration/internal/request"
14
+	"github.com/docker/docker/internal/test/request"
15 15
 	"github.com/docker/docker/pkg/system"
16 16
 	"github.com/gotestyourself/gotestyourself/assert"
17 17
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
... ...
@@ -13,7 +13,7 @@ import (
13 13
 
14 14
 	"github.com/docker/docker/api/types"
15 15
 	"github.com/docker/docker/integration/internal/container"
16
-	"github.com/docker/docker/integration/internal/request"
16
+	"github.com/docker/docker/internal/test/request"
17 17
 	"github.com/docker/go-connections/nat"
18 18
 	"github.com/gotestyourself/gotestyourself/assert"
19 19
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
... ...
@@ -10,7 +10,7 @@ import (
10 10
 	"github.com/docker/docker/api/types/events"
11 11
 	"github.com/docker/docker/api/types/filters"
12 12
 	"github.com/docker/docker/integration/internal/container"
13
-	"github.com/docker/docker/integration/internal/request"
13
+	"github.com/docker/docker/internal/test/request"
14 14
 	"github.com/docker/docker/internal/testutil"
15 15
 	"github.com/gotestyourself/gotestyourself/assert"
16 16
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
... ...
@@ -7,7 +7,7 @@ import (
7 7
 	"github.com/docker/docker/api/types"
8 8
 	"github.com/docker/docker/api/types/filters"
9 9
 	"github.com/docker/docker/integration/internal/container"
10
-	"github.com/docker/docker/integration/internal/request"
10
+	"github.com/docker/docker/internal/test/request"
11 11
 	"github.com/gotestyourself/gotestyourself/assert"
12 12
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
13 13
 )
... ...
@@ -9,7 +9,7 @@ import (
9 9
 	"github.com/docker/docker/api/types"
10 10
 	"github.com/docker/docker/api/types/filters"
11 11
 	"github.com/docker/docker/integration/internal/container"
12
-	"github.com/docker/docker/integration/internal/request"
12
+	"github.com/docker/docker/internal/test/request"
13 13
 	"github.com/docker/docker/internal/testutil"
14 14
 	"github.com/gotestyourself/gotestyourself/assert"
15 15
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
... ...
@@ -9,7 +9,7 @@ import (
9 9
 	containertypes "github.com/docker/docker/api/types/container"
10 10
 	"github.com/docker/docker/api/types/network"
11 11
 	"github.com/docker/docker/integration/internal/container"
12
-	"github.com/docker/docker/integration/internal/request"
12
+	"github.com/docker/docker/internal/test/request"
13 13
 	"github.com/docker/docker/internal/testutil"
14 14
 	"github.com/docker/docker/pkg/stringid"
15 15
 	"github.com/gotestyourself/gotestyourself/assert"
... ...
@@ -7,9 +7,9 @@ import (
7 7
 	"time"
8 8
 
9 9
 	"github.com/docker/docker/api/types"
10
-	req "github.com/docker/docker/integration-cli/request"
11 10
 	"github.com/docker/docker/integration/internal/container"
12
-	"github.com/docker/docker/integration/internal/request"
11
+	"github.com/docker/docker/internal/test/request"
12
+	req "github.com/docker/docker/internal/test/request"
13 13
 	"github.com/docker/docker/internal/testutil"
14 14
 	"github.com/gotestyourself/gotestyourself/assert"
15 15
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
... ...
@@ -9,7 +9,7 @@ import (
9 9
 
10 10
 	"github.com/docker/docker/api/types"
11 11
 	"github.com/docker/docker/integration/internal/container"
12
-	"github.com/docker/docker/integration/internal/request"
12
+	"github.com/docker/docker/internal/test/request"
13 13
 	"github.com/gotestyourself/gotestyourself/assert"
14 14
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
15 15
 	"github.com/gotestyourself/gotestyourself/poll"
... ...
@@ -9,7 +9,7 @@ import (
9 9
 
10 10
 	"github.com/docker/docker/api/types"
11 11
 	"github.com/docker/docker/integration/internal/container"
12
-	"github.com/docker/docker/integration/internal/request"
12
+	"github.com/docker/docker/internal/test/request"
13 13
 	"github.com/gotestyourself/gotestyourself/assert"
14 14
 	"github.com/gotestyourself/gotestyourself/icmd"
15 15
 	"github.com/gotestyourself/gotestyourself/poll"
... ...
@@ -9,7 +9,7 @@ import (
9 9
 
10 10
 	containertypes "github.com/docker/docker/api/types/container"
11 11
 	"github.com/docker/docker/integration/internal/container"
12
-	"github.com/docker/docker/integration/internal/request"
12
+	"github.com/docker/docker/internal/test/request"
13 13
 	"github.com/gotestyourself/gotestyourself/assert"
14 14
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
15 15
 	"github.com/gotestyourself/gotestyourself/poll"
... ...
@@ -7,7 +7,7 @@ import (
7 7
 
8 8
 	containertypes "github.com/docker/docker/api/types/container"
9 9
 	"github.com/docker/docker/integration/internal/container"
10
-	"github.com/docker/docker/integration/internal/request"
10
+	"github.com/docker/docker/internal/test/request"
11 11
 	"github.com/docker/docker/internal/testutil"
12 12
 	"github.com/gotestyourself/gotestyourself/assert"
13 13
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
... ...
@@ -6,7 +6,7 @@ import (
6 6
 
7 7
 	"github.com/docker/docker/api/types"
8 8
 	"github.com/docker/docker/integration/internal/container"
9
-	"github.com/docker/docker/integration/internal/request"
9
+	"github.com/docker/docker/internal/test/request"
10 10
 	"github.com/gotestyourself/gotestyourself/assert"
11 11
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
12 12
 )
... ...
@@ -9,7 +9,7 @@ import (
9 9
 	"testing"
10 10
 
11 11
 	"github.com/docker/docker/api/types"
12
-	"github.com/docker/docker/integration/internal/request"
12
+	"github.com/docker/docker/internal/test/request"
13 13
 	"github.com/docker/docker/internal/testutil"
14 14
 )
15 15
 
... ...
@@ -6,7 +6,7 @@ import (
6 6
 
7 7
 	"github.com/docker/docker/api/types"
8 8
 	"github.com/docker/docker/integration/internal/container"
9
-	"github.com/docker/docker/integration/internal/request"
9
+	"github.com/docker/docker/internal/test/request"
10 10
 	"github.com/docker/docker/internal/testutil"
11 11
 	"github.com/gotestyourself/gotestyourself/assert"
12 12
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
... ...
@@ -5,7 +5,7 @@ import (
5 5
 	"fmt"
6 6
 	"testing"
7 7
 
8
-	"github.com/docker/docker/integration/internal/request"
8
+	"github.com/docker/docker/internal/test/request"
9 9
 	"github.com/docker/docker/internal/testutil"
10 10
 	"github.com/gotestyourself/gotestyourself/assert"
11 11
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
12 12
deleted file mode 100644
... ...
@@ -1,42 +0,0 @@
1
-package request // import "github.com/docker/docker/integration/internal/request"
2
-
3
-import (
4
-	"fmt"
5
-	"testing"
6
-	"time"
7
-
8
-	"golang.org/x/net/context"
9
-
10
-	"github.com/docker/docker/client"
11
-	"github.com/docker/docker/internal/test/environment"
12
-	"github.com/gotestyourself/gotestyourself/assert"
13
-)
14
-
15
-// NewAPIClient returns a docker API client configured from environment variables
16
-func NewAPIClient(t *testing.T, ops ...func(*client.Client) error) client.APIClient {
17
-	ops = append([]func(*client.Client) error{client.FromEnv}, ops...)
18
-	clt, err := client.NewClientWithOpts(ops...)
19
-	assert.NilError(t, err)
20
-	return clt
21
-}
22
-
23
-// DaemonTime provides the current time on the daemon host
24
-func DaemonTime(ctx context.Context, t *testing.T, client client.APIClient, testEnv *environment.Execution) time.Time {
25
-	if testEnv.IsLocalDaemon() {
26
-		return time.Now()
27
-	}
28
-
29
-	info, err := client.Info(ctx)
30
-	assert.NilError(t, err)
31
-
32
-	dt, err := time.Parse(time.RFC3339Nano, info.SystemTime)
33
-	assert.NilError(t, err, "invalid time format in GET /info response")
34
-	return dt
35
-}
36
-
37
-// DaemonUnixTime returns the current time on the daemon host with nanoseconds precision.
38
-// It return the time formatted how the client sends timestamps to the server.
39
-func DaemonUnixTime(ctx context.Context, t *testing.T, client client.APIClient, testEnv *environment.Execution) string {
40
-	dt := DaemonTime(ctx, t, client, testEnv)
41
-	return fmt.Sprintf("%d.%09d", dt.Unix(), int64(dt.Nanosecond()))
42
-}
... ...
@@ -5,7 +5,7 @@ import (
5 5
 	"testing"
6 6
 
7 7
 	"github.com/docker/docker/api/types"
8
-	"github.com/docker/docker/integration/internal/request"
8
+	"github.com/docker/docker/internal/test/request"
9 9
 	"github.com/gotestyourself/gotestyourself/assert"
10 10
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
11 11
 )
... ...
@@ -4,7 +4,7 @@ import (
4 4
 	"net/http"
5 5
 	"testing"
6 6
 
7
-	req "github.com/docker/docker/integration-cli/request"
7
+	req "github.com/docker/docker/internal/test/request"
8 8
 	"github.com/gotestyourself/gotestyourself/assert"
9 9
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
10 10
 	"github.com/gotestyourself/gotestyourself/skip"
... ...
@@ -15,11 +15,11 @@ func TestSessionCreate(t *testing.T) {
15 15
 
16 16
 	defer setupTest(t)()
17 17
 
18
-	res, body, err := req.Post("/session", func(r *http.Request) error {
18
+	res, body, err := req.Post("/session", req.With(func(r *http.Request) error {
19 19
 		r.Header.Set("X-Docker-Expose-Session-Uuid", "testsessioncreate") // so we don't block default name if something else is using it
20 20
 		r.Header.Set("Upgrade", "h2c")
21 21
 		return nil
22
-	})
22
+	}))
23 23
 	assert.NilError(t, err)
24 24
 	assert.NilError(t, body.Close())
25 25
 	assert.Check(t, is.DeepEqual(res.StatusCode, http.StatusSwitchingProtocols))
... ...
@@ -36,10 +36,10 @@ func TestSessionCreateWithBadUpgrade(t *testing.T) {
36 36
 	assert.NilError(t, err)
37 37
 	assert.Check(t, is.Contains(string(buf), "no upgrade"))
38 38
 
39
-	res, body, err = req.Post("/session", func(r *http.Request) error {
39
+	res, body, err = req.Post("/session", req.With(func(r *http.Request) error {
40 40
 		r.Header.Set("Upgrade", "foo")
41 41
 		return nil
42
-	})
42
+	}))
43 43
 	assert.NilError(t, err)
44 44
 	assert.Check(t, is.DeepEqual(res.StatusCode, http.StatusBadRequest))
45 45
 	buf, err = req.ReadBody(body)
... ...
@@ -13,9 +13,9 @@ import (
13 13
 	"github.com/docker/docker/api/types"
14 14
 	"github.com/docker/docker/api/types/filters"
15 15
 	"github.com/docker/docker/api/types/strslice"
16
-	req "github.com/docker/docker/integration-cli/request"
17 16
 	"github.com/docker/docker/integration/internal/container"
18
-	"github.com/docker/docker/integration/internal/request"
17
+	"github.com/docker/docker/internal/test/request"
18
+	req "github.com/docker/docker/internal/test/request"
19 19
 	"github.com/docker/docker/pkg/jsonmessage"
20 20
 	"github.com/gotestyourself/gotestyourself/assert"
21 21
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
... ...
@@ -6,8 +6,8 @@ import (
6 6
 	"net/http"
7 7
 	"testing"
8 8
 
9
-	req "github.com/docker/docker/integration-cli/request"
10
-	"github.com/docker/docker/integration/internal/request"
9
+	"github.com/docker/docker/internal/test/request"
10
+	req "github.com/docker/docker/internal/test/request"
11 11
 	"github.com/gotestyourself/gotestyourself/assert"
12 12
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
13 13
 	"golang.org/x/net/context"
... ...
@@ -4,7 +4,7 @@ import (
4 4
 	"fmt"
5 5
 	"testing"
6 6
 
7
-	"github.com/docker/docker/integration/internal/request"
7
+	"github.com/docker/docker/internal/test/request"
8 8
 	"github.com/gotestyourself/gotestyourself/assert"
9 9
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
10 10
 	"golang.org/x/net/context"
... ...
@@ -4,8 +4,8 @@ import (
4 4
 	"testing"
5 5
 
6 6
 	"github.com/docker/docker/api/types"
7
-	"github.com/docker/docker/integration/internal/request"
8 7
 	"github.com/docker/docker/integration/internal/requirement"
8
+	"github.com/docker/docker/internal/test/request"
9 9
 	"github.com/gotestyourself/gotestyourself/assert"
10 10
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
11 11
 	"github.com/gotestyourself/gotestyourself/skip"
... ...
@@ -3,7 +3,7 @@ package system // import "github.com/docker/docker/integration/system"
3 3
 import (
4 4
 	"testing"
5 5
 
6
-	"github.com/docker/docker/integration/internal/request"
6
+	"github.com/docker/docker/internal/test/request"
7 7
 	"github.com/gotestyourself/gotestyourself/assert"
8 8
 	is "github.com/gotestyourself/gotestyourself/assert/cmp"
9 9
 	"golang.org/x/net/context"
... ...
@@ -11,7 +11,7 @@ import (
11 11
 	"github.com/docker/docker/api/types/filters"
12 12
 	volumetypes "github.com/docker/docker/api/types/volume"
13 13
 	"github.com/docker/docker/integration/internal/container"
14
-	"github.com/docker/docker/integration/internal/request"
14
+	"github.com/docker/docker/internal/test/request"
15 15
 	"github.com/docker/docker/internal/testutil"
16 16
 	"github.com/google/go-cmp/cmp/cmpopts"
17 17
 	"github.com/gotestyourself/gotestyourself/assert"
... ...
@@ -8,7 +8,7 @@ import (
8 8
 )
9 9
 
10 10
 // ActiveContainers returns the list of ids of the currently running containers
11
-func (d *Daemon) ActiveContainers(t testingT) []string {
11
+func (d *Daemon) ActiveContainers(t assert.TestingT) []string {
12 12
 	cli := d.NewClientT(t)
13 13
 	defer cli.Close()
14 14
 
... ...
@@ -23,7 +23,7 @@ func (d *Daemon) ActiveContainers(t testingT) []string {
23 23
 }
24 24
 
25 25
 // FindContainerIP returns the ip of the specified container
26
-func (d *Daemon) FindContainerIP(t testingT, id string) string {
26
+func (d *Daemon) FindContainerIP(t assert.TestingT, id string) string {
27 27
 	cli := d.NewClientT(t)
28 28
 	defer cli.Close()
29 29
 
... ...
@@ -16,7 +16,7 @@ import (
16 16
 	"github.com/docker/docker/api/types"
17 17
 	"github.com/docker/docker/api/types/events"
18 18
 	"github.com/docker/docker/client"
19
-	"github.com/docker/docker/integration-cli/request"
19
+	"github.com/docker/docker/internal/test/request"
20 20
 	"github.com/docker/docker/opts"
21 21
 	"github.com/docker/docker/pkg/ioutils"
22 22
 	"github.com/docker/docker/pkg/stringid"
... ...
@@ -479,7 +479,7 @@ func (d *Daemon) ReloadConfig() error {
479 479
 	errCh := make(chan error)
480 480
 	started := make(chan struct{})
481 481
 	go func() {
482
-		_, body, err := request.DoOnHost(d.Sock(), "/events", request.Method(http.MethodGet))
482
+		_, body, err := request.Get("/events", request.Host(d.Sock()))
483 483
 		close(started)
484 484
 		if err != nil {
485 485
 			errCh <- err
... ...
@@ -14,9 +14,9 @@ import (
14 14
 	"github.com/docker/docker/api/types"
15 15
 	containertypes "github.com/docker/docker/api/types/container"
16 16
 	"github.com/docker/docker/client"
17
-	"github.com/docker/docker/integration-cli/request"
18 17
 	"github.com/docker/docker/internal/test/environment"
19 18
 	"github.com/docker/docker/internal/test/fakecontext"
19
+	"github.com/docker/docker/internal/test/request"
20 20
 	"github.com/docker/docker/internal/testutil"
21 21
 	"github.com/docker/go-connections/nat"
22 22
 	"github.com/gotestyourself/gotestyourself/assert"
23 23
new file mode 100644
... ...
@@ -0,0 +1,12 @@
0
+// +build !windows
1
+
2
+package request
3
+
4
+import (
5
+	"net"
6
+	"time"
7
+)
8
+
9
+func npipeDial(path string, timeout time.Duration) (net.Conn, error) {
10
+	panic("npipe protocol only supported on Windows")
11
+}
0 12
new file mode 100644
... ...
@@ -0,0 +1,12 @@
0
+package request
1
+
2
+import (
3
+	"net"
4
+	"time"
5
+
6
+	"github.com/Microsoft/go-winio"
7
+)
8
+
9
+func npipeDial(path string, timeout time.Duration) (net.Conn, error) {
10
+	return winio.DialPipe(path, &timeout)
11
+}
0 12
new file mode 100644
... ...
@@ -0,0 +1,78 @@
0
+package request
1
+
2
+import (
3
+	"bytes"
4
+	"encoding/json"
5
+	"io"
6
+	"io/ioutil"
7
+	"net/http"
8
+	"strings"
9
+)
10
+
11
+// Options defines request options, like request modifiers and which host to target
12
+type Options struct {
13
+	host             string
14
+	requestModifiers []func(*http.Request) error
15
+}
16
+
17
+// Host creates a modifier that sets the specified host as the request URL host
18
+func Host(host string) func(*Options) {
19
+	return func(o *Options) {
20
+		o.host = host
21
+	}
22
+}
23
+
24
+// With adds a request modifier to the options
25
+func With(f func(*http.Request) error) func(*Options) {
26
+	return func(o *Options) {
27
+		o.requestModifiers = append(o.requestModifiers, f)
28
+	}
29
+}
30
+
31
+// Method creates a modifier that sets the specified string as the request method
32
+func Method(method string) func(*Options) {
33
+	return With(func(req *http.Request) error {
34
+		req.Method = method
35
+		return nil
36
+	})
37
+}
38
+
39
+// RawString sets the specified string as body for the request
40
+func RawString(content string) func(*Options) {
41
+	return RawContent(ioutil.NopCloser(strings.NewReader(content)))
42
+}
43
+
44
+// RawContent sets the specified reader as body for the request
45
+func RawContent(reader io.ReadCloser) func(*Options) {
46
+	return With(func(req *http.Request) error {
47
+		req.Body = reader
48
+		return nil
49
+	})
50
+}
51
+
52
+// ContentType sets the specified Content-Type request header
53
+func ContentType(contentType string) func(*Options) {
54
+	return With(func(req *http.Request) error {
55
+		req.Header.Set("Content-Type", contentType)
56
+		return nil
57
+	})
58
+}
59
+
60
+// JSON sets the Content-Type request header to json
61
+func JSON(o *Options) {
62
+	ContentType("application/json")(o)
63
+}
64
+
65
+// JSONBody creates a modifier that encodes the specified data to a JSON string and set it as request body. It also sets
66
+// the Content-Type header of the request.
67
+func JSONBody(data interface{}) func(*Options) {
68
+	return With(func(req *http.Request) error {
69
+		jsonData := bytes.NewBuffer(nil)
70
+		if err := json.NewEncoder(jsonData).Encode(data); err != nil {
71
+			return err
72
+		}
73
+		req.Body = ioutil.NopCloser(jsonData)
74
+		req.Header.Set("Content-Type", "application/json")
75
+		return nil
76
+	})
77
+}
0 78
new file mode 100644
... ...
@@ -0,0 +1,208 @@
0
+package request // import "github.com/docker/docker/internal/test/request"
1
+
2
+import (
3
+	"context"
4
+	"crypto/tls"
5
+	"fmt"
6
+	"io"
7
+	"io/ioutil"
8
+	"net"
9
+	"net/http"
10
+	"net/url"
11
+	"os"
12
+	"path/filepath"
13
+	"time"
14
+
15
+	"github.com/docker/docker/client"
16
+	"github.com/docker/docker/internal/test/environment"
17
+	"github.com/docker/docker/opts"
18
+	"github.com/docker/docker/pkg/ioutils"
19
+	"github.com/docker/go-connections/sockets"
20
+	"github.com/docker/go-connections/tlsconfig"
21
+	"github.com/gotestyourself/gotestyourself/assert"
22
+	"github.com/pkg/errors"
23
+)
24
+
25
+// NewAPIClient returns a docker API client configured from environment variables
26
+func NewAPIClient(t assert.TestingT, ops ...func(*client.Client) error) client.APIClient {
27
+	ops = append([]func(*client.Client) error{client.FromEnv}, ops...)
28
+	clt, err := client.NewClientWithOpts(ops...)
29
+	assert.NilError(t, err)
30
+	return clt
31
+}
32
+
33
+// DaemonTime provides the current time on the daemon host
34
+func DaemonTime(ctx context.Context, t assert.TestingT, client client.APIClient, testEnv *environment.Execution) time.Time {
35
+	if testEnv.IsLocalDaemon() {
36
+		return time.Now()
37
+	}
38
+
39
+	info, err := client.Info(ctx)
40
+	assert.NilError(t, err)
41
+
42
+	dt, err := time.Parse(time.RFC3339Nano, info.SystemTime)
43
+	assert.NilError(t, err, "invalid time format in GET /info response")
44
+	return dt
45
+}
46
+
47
+// DaemonUnixTime returns the current time on the daemon host with nanoseconds precision.
48
+// It return the time formatted how the client sends timestamps to the server.
49
+func DaemonUnixTime(ctx context.Context, t assert.TestingT, client client.APIClient, testEnv *environment.Execution) string {
50
+	dt := DaemonTime(ctx, t, client, testEnv)
51
+	return fmt.Sprintf("%d.%09d", dt.Unix(), int64(dt.Nanosecond()))
52
+}
53
+
54
+// Post creates and execute a POST request on the specified host and endpoint, with the specified request modifiers
55
+func Post(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) {
56
+	return Do(endpoint, append(modifiers, Method(http.MethodPost))...)
57
+}
58
+
59
+// Delete creates and execute a DELETE request on the specified host and endpoint, with the specified request modifiers
60
+func Delete(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) {
61
+	return Do(endpoint, append(modifiers, Method(http.MethodDelete))...)
62
+}
63
+
64
+// Get creates and execute a GET request on the specified host and endpoint, with the specified request modifiers
65
+func Get(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) {
66
+	return Do(endpoint, modifiers...)
67
+}
68
+
69
+// Do creates and execute a request on the specified endpoint, with the specified request modifiers
70
+func Do(endpoint string, modifiers ...func(*Options)) (*http.Response, io.ReadCloser, error) {
71
+	opts := &Options{
72
+		host: DaemonHost(),
73
+	}
74
+	for _, mod := range modifiers {
75
+		mod(opts)
76
+	}
77
+	req, err := newRequest(endpoint, opts)
78
+	if err != nil {
79
+		return nil, nil, err
80
+	}
81
+	client, err := newHTTPClient(opts.host)
82
+	if err != nil {
83
+		return nil, nil, err
84
+	}
85
+	resp, err := client.Do(req)
86
+	var body io.ReadCloser
87
+	if resp != nil {
88
+		body = ioutils.NewReadCloserWrapper(resp.Body, func() error {
89
+			defer resp.Body.Close()
90
+			return nil
91
+		})
92
+	}
93
+	return resp, body, err
94
+}
95
+
96
+// ReadBody read the specified ReadCloser content and returns it
97
+func ReadBody(b io.ReadCloser) ([]byte, error) {
98
+	defer b.Close()
99
+	return ioutil.ReadAll(b)
100
+}
101
+
102
+// newRequest creates a new http Request to the specified host and endpoint, with the specified request modifiers
103
+func newRequest(endpoint string, opts *Options) (*http.Request, error) {
104
+	hostURL, err := client.ParseHostURL(opts.host)
105
+	if err != nil {
106
+		return nil, errors.Wrapf(err, "failed parsing url %q", opts.host)
107
+	}
108
+	req, err := http.NewRequest("GET", endpoint, nil)
109
+	if err != nil {
110
+		return nil, errors.Wrap(err, "failed to create request")
111
+	}
112
+
113
+	if os.Getenv("DOCKER_TLS_VERIFY") != "" {
114
+		req.URL.Scheme = "https"
115
+	} else {
116
+		req.URL.Scheme = "http"
117
+	}
118
+	req.URL.Host = hostURL.Host
119
+
120
+	for _, config := range opts.requestModifiers {
121
+		if err := config(req); err != nil {
122
+			return nil, err
123
+		}
124
+	}
125
+
126
+	return req, nil
127
+}
128
+
129
+// newHTTPClient creates an http client for the specific host
130
+// TODO: Share more code with client.defaultHTTPClient
131
+func newHTTPClient(host string) (*http.Client, error) {
132
+	// FIXME(vdemeester) 10*time.Second timeout of SockRequest… ?
133
+	hostURL, err := client.ParseHostURL(host)
134
+	if err != nil {
135
+		return nil, err
136
+	}
137
+	transport := new(http.Transport)
138
+	if hostURL.Scheme == "tcp" && os.Getenv("DOCKER_TLS_VERIFY") != "" {
139
+		// Setup the socket TLS configuration.
140
+		tlsConfig, err := getTLSConfig()
141
+		if err != nil {
142
+			return nil, err
143
+		}
144
+		transport = &http.Transport{TLSClientConfig: tlsConfig}
145
+	}
146
+	transport.DisableKeepAlives = true
147
+	err = sockets.ConfigureTransport(transport, hostURL.Scheme, hostURL.Host)
148
+	return &http.Client{Transport: transport}, err
149
+}
150
+
151
+func getTLSConfig() (*tls.Config, error) {
152
+	dockerCertPath := os.Getenv("DOCKER_CERT_PATH")
153
+
154
+	if dockerCertPath == "" {
155
+		return nil, errors.New("DOCKER_TLS_VERIFY specified, but no DOCKER_CERT_PATH environment variable")
156
+	}
157
+
158
+	option := &tlsconfig.Options{
159
+		CAFile:   filepath.Join(dockerCertPath, "ca.pem"),
160
+		CertFile: filepath.Join(dockerCertPath, "cert.pem"),
161
+		KeyFile:  filepath.Join(dockerCertPath, "key.pem"),
162
+	}
163
+	tlsConfig, err := tlsconfig.Client(*option)
164
+	if err != nil {
165
+		return nil, err
166
+	}
167
+
168
+	return tlsConfig, nil
169
+}
170
+
171
+// DaemonHost return the daemon host string for this test execution
172
+func DaemonHost() string {
173
+	daemonURLStr := "unix://" + opts.DefaultUnixSocket
174
+	if daemonHostVar := os.Getenv("DOCKER_HOST"); daemonHostVar != "" {
175
+		daemonURLStr = daemonHostVar
176
+	}
177
+	return daemonURLStr
178
+}
179
+
180
+// SockConn opens a connection on the specified socket
181
+func SockConn(timeout time.Duration, daemon string) (net.Conn, error) {
182
+	daemonURL, err := url.Parse(daemon)
183
+	if err != nil {
184
+		return nil, errors.Wrapf(err, "could not parse url %q", daemon)
185
+	}
186
+
187
+	var c net.Conn
188
+	switch daemonURL.Scheme {
189
+	case "npipe":
190
+		return npipeDial(daemonURL.Path, timeout)
191
+	case "unix":
192
+		return net.DialTimeout(daemonURL.Scheme, daemonURL.Path, timeout)
193
+	case "tcp":
194
+		if os.Getenv("DOCKER_TLS_VERIFY") != "" {
195
+			// Setup the socket TLS configuration.
196
+			tlsConfig, err := getTLSConfig()
197
+			if err != nil {
198
+				return nil, err
199
+			}
200
+			dialer := &net.Dialer{Timeout: timeout}
201
+			return tls.DialWithDialer(dialer, daemonURL.Scheme, daemonURL.Host, tlsConfig)
202
+		}
203
+		return net.DialTimeout(daemonURL.Scheme, daemonURL.Host, timeout)
204
+	default:
205
+		return c, errors.Errorf("unknown scheme %v (%s)", daemonURL.Scheme, daemon)
206
+	}
207
+}