Browse code

Remove duplicate calls for getting an APIClient

Remove request.SockRequest
Remove request.SockRequestHijack
Remove request.SockRequestRaw()
Remove deprecated ParseHost
Deprecate and unexport more helpers

Signed-off-by: Daniel Nephin <dnephin@docker.com>

Daniel Nephin authored on 2017/09/20 05:12:29
Showing 17 changed files
... ...
@@ -356,17 +356,6 @@ func (cli *Client) DaemonHost() string {
356 356
 	return cli.host
357 357
 }
358 358
 
359
-// ParseHost parses a url string, validates the strings is a host url, and returns
360
-// the parsed host as: protocol, address, and base path
361
-// Deprecated: use ParseHostURL
362
-func ParseHost(host string) (string, string, string, error) {
363
-	hostURL, err := ParseHostURL(host)
364
-	if err != nil {
365
-		return "", "", "", err
366
-	}
367
-	return hostURL.Scheme, hostURL.Host, hostURL.Path, nil
368
-}
369
-
370 359
 // ParseHostURL parses a url string, validates the string is a host url, and
371 360
 // returns the parsed URL
372 361
 func ParseHostURL(host string) (*url.URL, error) {
... ...
@@ -132,32 +132,6 @@ func TestGetAPIPath(t *testing.T) {
132 132
 	}
133 133
 }
134 134
 
135
-func TestParseHost(t *testing.T) {
136
-	cases := []struct {
137
-		host  string
138
-		proto string
139
-		addr  string
140
-		base  string
141
-		err   bool
142
-	}{
143
-		{"", "", "", "", true},
144
-		{"foobar", "", "", "", true},
145
-		{"foo://bar", "foo", "bar", "", false},
146
-		{"tcp://localhost:2476", "tcp", "localhost:2476", "", false},
147
-		{"tcp://localhost:2476/path", "tcp", "localhost:2476", "/path", false},
148
-	}
149
-
150
-	for _, cs := range cases {
151
-		p, a, b, e := ParseHost(cs.host)
152
-		if cs.err {
153
-			assert.Error(t, e)
154
-		}
155
-		assert.Equal(t, cs.proto, p)
156
-		assert.Equal(t, cs.addr, a)
157
-		assert.Equal(t, cs.base, b)
158
-	}
159
-}
160
-
161 135
 func TestParseHostURL(t *testing.T) {
162 136
 	testcases := []struct {
163 137
 		host        string
... ...
@@ -37,6 +37,7 @@ type CommonAPIClient interface {
37 37
 	NegotiateAPIVersion(ctx context.Context)
38 38
 	NegotiateAPIVersionPing(types.Ping)
39 39
 	DialSession(ctx context.Context, proto string, meta map[string][]string) (net.Conn, error)
40
+	Close() error
40 41
 }
41 42
 
42 43
 // ContainerAPIClient defines API client methods for the containers
... ...
@@ -123,10 +123,7 @@ func (cli *Client) sendRequest(ctx context.Context, method, path string, query u
123 123
 	if err != nil {
124 124
 		return resp, err
125 125
 	}
126
-	if err := cli.checkResponseErr(resp); err != nil {
127
-		return resp, err
128
-	}
129
-	return resp, nil
126
+	return resp, cli.checkResponseErr(resp)
130 127
 }
131 128
 
132 129
 func (cli *Client) doRequest(ctx context.Context, req *http.Request) (serverResponse, error) {
... ...
@@ -9,6 +9,7 @@ import (
9 9
 	"testing"
10 10
 
11 11
 	"github.com/docker/docker/api/types"
12
+	"github.com/stretchr/testify/require"
12 13
 	"golang.org/x/net/context"
13 14
 )
14 15
 
... ...
@@ -44,10 +45,8 @@ func TestSetHostHeader(t *testing.T) {
44 44
 	}
45 45
 
46 46
 	for c, test := range testCases {
47
-		proto, addr, basePath, err := ParseHost(test.host)
48
-		if err != nil {
49
-			t.Fatal(err)
50
-		}
47
+		hostURL, err := ParseHostURL(test.host)
48
+		require.NoError(t, err)
51 49
 
52 50
 		client := &Client{
53 51
 			client: newMockClient(func(req *http.Request) (*http.Response, error) {
... ...
@@ -66,15 +65,13 @@ func TestSetHostHeader(t *testing.T) {
66 66
 				}, nil
67 67
 			}),
68 68
 
69
-			proto:    proto,
70
-			addr:     addr,
71
-			basePath: basePath,
69
+			proto:    hostURL.Scheme,
70
+			addr:     hostURL.Host,
71
+			basePath: hostURL.Path,
72 72
 		}
73 73
 
74 74
 		_, err = client.sendRequest(context.Background(), "GET", testURL, nil, nil, nil)
75
-		if err != nil {
76
-			t.Fatal(err)
77
-		}
75
+		require.NoError(t, err)
78 76
 	}
79 77
 }
80 78
 
... ...
@@ -1,7 +1,6 @@
1 1
 package daemon // import "github.com/docker/docker/integration-cli/daemon"
2 2
 
3 3
 import (
4
-	"bytes"
5 4
 	"encoding/json"
6 5
 	"fmt"
7 6
 	"io"
... ...
@@ -14,7 +13,6 @@ import (
14 14
 	"strings"
15 15
 	"time"
16 16
 
17
-	"github.com/docker/docker/api"
18 17
 	"github.com/docker/docker/api/types"
19 18
 	"github.com/docker/docker/api/types/events"
20 19
 	"github.com/docker/docker/client"
... ...
@@ -596,28 +594,6 @@ func (d *Daemon) PrependHostArg(args []string) []string {
596 596
 	return append([]string{"--host", d.Sock()}, args...)
597 597
 }
598 598
 
599
-// SockRequest executes a socket request on a daemon and returns statuscode and output.
600
-func (d *Daemon) SockRequest(method, endpoint string, data interface{}) (int, []byte, error) {
601
-	jsonData := bytes.NewBuffer(nil)
602
-	if err := json.NewEncoder(jsonData).Encode(data); err != nil {
603
-		return -1, nil, err
604
-	}
605
-
606
-	res, body, err := d.SockRequestRaw(method, endpoint, jsonData, "application/json")
607
-	if err != nil {
608
-		return -1, nil, err
609
-	}
610
-	b, err := request.ReadBody(body)
611
-	return res.StatusCode, b, err
612
-}
613
-
614
-// SockRequestRaw executes a socket request on a daemon and returns an http
615
-// response and a reader for the output data.
616
-// Deprecated: use request package instead
617
-func (d *Daemon) SockRequestRaw(method, endpoint string, data io.Reader, ct string) (*http.Response, io.ReadCloser, error) {
618
-	return request.SockRequestRaw(method, endpoint, data, ct, d.Sock())
619
-}
620
-
621 599
 // LogFileName returns the path the daemon's log file
622 600
 func (d *Daemon) LogFileName() string {
623 601
 	return d.logFile.Name()
... ...
@@ -746,12 +722,9 @@ func (d *Daemon) ReloadConfig() error {
746 746
 
747 747
 // NewClient creates new client based on daemon's socket path
748 748
 func (d *Daemon) NewClient() (*client.Client, error) {
749
-	httpClient, err := request.NewHTTPClient(d.Sock())
750
-	if err != nil {
751
-		return nil, err
752
-	}
753
-
754
-	return client.NewClient(d.Sock(), api.DefaultVersion, httpClient, nil)
749
+	return client.NewClientWithOpts(
750
+		client.FromEnv,
751
+		client.WithHost(d.Sock()))
755 752
 }
756 753
 
757 754
 // WaitInspectWithArgs waits for the specified expression to be equals to the specified expected string in the given time.
... ...
@@ -1,18 +1,18 @@
1 1
 package daemon // import "github.com/docker/docker/integration-cli/daemon"
2 2
 
3 3
 import (
4
-	"encoding/json"
5 4
 	"fmt"
6
-	"net/http"
7 5
 	"strings"
8 6
 	"time"
9 7
 
10 8
 	"github.com/docker/docker/api/types"
11 9
 	"github.com/docker/docker/api/types/filters"
12 10
 	"github.com/docker/docker/api/types/swarm"
11
+	"github.com/docker/docker/client"
13 12
 	"github.com/docker/docker/integration-cli/checker"
14 13
 	"github.com/go-check/check"
15 14
 	"github.com/pkg/errors"
15
+	"github.com/stretchr/testify/require"
16 16
 	"golang.org/x/net/context"
17 17
 )
18 18
 
... ...
@@ -234,31 +234,28 @@ func (d *Swarm) CheckServiceUpdateState(service string) func(*check.C) (interfac
234 234
 // CheckPluginRunning returns the runtime state of the plugin
235 235
 func (d *Swarm) CheckPluginRunning(plugin string) func(c *check.C) (interface{}, check.CommentInterface) {
236 236
 	return func(c *check.C) (interface{}, check.CommentInterface) {
237
-		status, out, err := d.SockRequest("GET", "/plugins/"+plugin+"/json", nil)
238
-		c.Assert(err, checker.IsNil, check.Commentf(string(out)))
239
-		if status != http.StatusOK {
240
-			return false, nil
237
+		apiclient, err := d.NewClient()
238
+		require.NoError(c, err)
239
+		resp, _, err := apiclient.PluginInspectWithRaw(context.Background(), plugin)
240
+		if client.IsErrNotFound(err) {
241
+			return false, check.Commentf("%v", err)
241 242
 		}
242
-
243
-		var p types.Plugin
244
-		c.Assert(json.Unmarshal(out, &p), checker.IsNil, check.Commentf(string(out)))
245
-
246
-		return p.Enabled, check.Commentf("%+v", p)
243
+		require.NoError(c, err)
244
+		return resp.Enabled, check.Commentf("%+v", resp)
247 245
 	}
248 246
 }
249 247
 
250 248
 // CheckPluginImage returns the runtime state of the plugin
251 249
 func (d *Swarm) CheckPluginImage(plugin string) func(c *check.C) (interface{}, check.CommentInterface) {
252 250
 	return func(c *check.C) (interface{}, check.CommentInterface) {
253
-		status, out, err := d.SockRequest("GET", "/plugins/"+plugin+"/json", nil)
254
-		c.Assert(err, checker.IsNil, check.Commentf(string(out)))
255
-		if status != http.StatusOK {
256
-			return false, nil
251
+		apiclient, err := d.NewClient()
252
+		require.NoError(c, err)
253
+		resp, _, err := apiclient.PluginInspectWithRaw(context.Background(), plugin)
254
+		if client.IsErrNotFound(err) {
255
+			return false, check.Commentf("%v", err)
257 256
 		}
258
-
259
-		var p types.Plugin
260
-		c.Assert(json.Unmarshal(out, &p), checker.IsNil, check.Commentf(string(out)))
261
-		return p.PluginReference, check.Commentf("%+v", p)
257
+		require.NoError(c, err)
258
+		return resp.PluginReference, check.Commentf("%+v", resp)
262 259
 	}
263 260
 }
264 261
 
... ...
@@ -4,9 +4,11 @@ import (
4 4
 	"bufio"
5 5
 	"bytes"
6 6
 	"context"
7
+	"fmt"
7 8
 	"io"
8 9
 	"net"
9 10
 	"net/http"
11
+	"net/http/httputil"
10 12
 	"strings"
11 13
 	"time"
12 14
 
... ...
@@ -73,10 +75,8 @@ func (s *DockerSuite) TestGetContainersAttachWebsocket(c *check.C) {
73 73
 
74 74
 // regression gh14320
75 75
 func (s *DockerSuite) TestPostContainersAttachContainerNotFound(c *check.C) {
76
-	client, err := request.NewHTTPClient(daemonHost())
76
+	resp, _, err := request.Post("/containers/doesnotexist/attach")
77 77
 	c.Assert(err, checker.IsNil)
78
-	req, err := request.New(daemonHost(), "/containers/doesnotexist/attach", request.Method(http.MethodPost))
79
-	resp, err := client.Do(req)
80 78
 	// connection will shutdown, err should be "persistent connection closed"
81 79
 	c.Assert(resp.StatusCode, checker.Equals, http.StatusNotFound)
82 80
 	content, err := request.ReadBody(resp.Body)
... ...
@@ -140,12 +140,12 @@ func (s *DockerSuite) TestPostContainersAttach(c *check.C) {
140 140
 	cid, _ := dockerCmd(c, "run", "-di", "busybox", "cat")
141 141
 	cid = strings.TrimSpace(cid)
142 142
 	// Attach to the container's stdout stream.
143
-	conn, br, err := request.SockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stdout=1", nil, "text/plain", daemonHost())
143
+	conn, br, err := sockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stdout=1", nil, "text/plain", daemonHost())
144 144
 	c.Assert(err, checker.IsNil)
145 145
 	// Check if the data from stdout can be received.
146 146
 	expectSuccess(conn, br, "stdout", false)
147 147
 	// Attach to the container's stderr stream.
148
-	conn, br, err = request.SockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stderr=1", nil, "text/plain", daemonHost())
148
+	conn, br, err = sockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stderr=1", nil, "text/plain", daemonHost())
149 149
 	c.Assert(err, checker.IsNil)
150 150
 	// Since the container only emits stdout, attaching to stderr should return nothing.
151 151
 	expectTimeout(conn, br, "stdout")
... ...
@@ -153,10 +153,10 @@ func (s *DockerSuite) TestPostContainersAttach(c *check.C) {
153 153
 	// Test the similar functions of the stderr stream.
154 154
 	cid, _ = dockerCmd(c, "run", "-di", "busybox", "/bin/sh", "-c", "cat >&2")
155 155
 	cid = strings.TrimSpace(cid)
156
-	conn, br, err = request.SockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stderr=1", nil, "text/plain", daemonHost())
156
+	conn, br, err = sockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stderr=1", nil, "text/plain", daemonHost())
157 157
 	c.Assert(err, checker.IsNil)
158 158
 	expectSuccess(conn, br, "stderr", false)
159
-	conn, br, err = request.SockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stdout=1", nil, "text/plain", daemonHost())
159
+	conn, br, err = sockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stdout=1", nil, "text/plain", daemonHost())
160 160
 	c.Assert(err, checker.IsNil)
161 161
 	expectTimeout(conn, br, "stderr")
162 162
 
... ...
@@ -164,12 +164,12 @@ func (s *DockerSuite) TestPostContainersAttach(c *check.C) {
164 164
 	cid, _ = dockerCmd(c, "run", "-dit", "busybox", "/bin/sh", "-c", "cat >&2")
165 165
 	cid = strings.TrimSpace(cid)
166 166
 	// Attach to stdout only.
167
-	conn, br, err = request.SockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stdout=1", nil, "text/plain", daemonHost())
167
+	conn, br, err = sockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stdout=1", nil, "text/plain", daemonHost())
168 168
 	c.Assert(err, checker.IsNil)
169 169
 	expectSuccess(conn, br, "stdout", true)
170 170
 
171 171
 	// Attach without stdout stream.
172
-	conn, br, err = request.SockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stderr=1", nil, "text/plain", daemonHost())
172
+	conn, br, err = sockRequestHijack("POST", "/containers/"+cid+"/attach?stream=1&stdin=1&stderr=1", nil, "text/plain", daemonHost())
173 173
 	c.Assert(err, checker.IsNil)
174 174
 	// Nothing should be received because both the stdout and stderr of the container will be
175 175
 	// sent to the client as stdout when tty is enabled.
... ...
@@ -210,3 +210,43 @@ func (s *DockerSuite) TestPostContainersAttach(c *check.C) {
210 210
 	stdcopy.StdCopy(actualStdout, actualStderr, resp.Reader)
211 211
 	c.Assert(actualStdout.Bytes(), checker.DeepEquals, []byte("hello\nsuccess"), check.Commentf("Attach didn't return the expected data from stdout"))
212 212
 }
213
+
214
+// SockRequestHijack creates a connection to specified host (with method, contenttype, …) and returns a hijacked connection
215
+// and the output as a `bufio.Reader`
216
+func sockRequestHijack(method, endpoint string, data io.Reader, ct string, daemon string, modifiers ...func(*http.Request)) (net.Conn, *bufio.Reader, error) {
217
+	req, client, err := newRequestClient(method, endpoint, data, ct, daemon, modifiers...)
218
+	if err != nil {
219
+		return nil, nil, err
220
+	}
221
+
222
+	client.Do(req)
223
+	conn, br := client.Hijack()
224
+	return conn, br, nil
225
+}
226
+
227
+// FIXME(vdemeester) httputil.ClientConn is deprecated, use http.Client instead (closer to actual client)
228
+// Deprecated: Use New instead of NewRequestClient
229
+// Deprecated: use request.Do (or Get, Delete, Post) instead
230
+func newRequestClient(method, endpoint string, data io.Reader, ct, daemon string, modifiers ...func(*http.Request)) (*http.Request, *httputil.ClientConn, error) {
231
+	c, err := request.SockConn(time.Duration(10*time.Second), daemon)
232
+	if err != nil {
233
+		return nil, nil, fmt.Errorf("could not dial docker daemon: %v", err)
234
+	}
235
+
236
+	client := httputil.NewClientConn(c, nil)
237
+
238
+	req, err := http.NewRequest(method, endpoint, data)
239
+	if err != nil {
240
+		client.Close()
241
+		return nil, nil, fmt.Errorf("could not create new request: %v", err)
242
+	}
243
+
244
+	for _, opt := range modifiers {
245
+		opt(req)
246
+	}
247
+
248
+	if ct != "" {
249
+		req.Header.Set("Content-Type", ct)
250
+	}
251
+	return req, client, nil
252
+}
... ...
@@ -319,8 +319,7 @@ func (s *DockerSuite) TestBuildOnBuildCache(c *check.C) {
319 319
 	assert.Len(c, imageIDs, 2)
320 320
 	parentID, childID := imageIDs[0], imageIDs[1]
321 321
 
322
-	client, err := request.NewClient()
323
-	require.NoError(c, err)
322
+	client := testEnv.APIClient()
324 323
 
325 324
 	// check parentID is correct
326 325
 	image, _, err := client.ImageInspectWithRaw(context.Background(), childID)
... ...
@@ -329,12 +328,11 @@ func (s *DockerSuite) TestBuildOnBuildCache(c *check.C) {
329 329
 }
330 330
 
331 331
 func (s *DockerRegistrySuite) TestBuildCopyFromForcePull(c *check.C) {
332
-	client, err := request.NewClient()
333
-	require.NoError(c, err)
332
+	client := testEnv.APIClient()
334 333
 
335 334
 	repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
336 335
 	// tag the image to upload it to the private registry
337
-	err = client.ImageTag(context.TODO(), "busybox", repoName)
336
+	err := client.ImageTag(context.TODO(), "busybox", repoName)
338 337
 	assert.Nil(c, err)
339 338
 	// push the image to the registry
340 339
 	rc, err := client.ImagePush(context.TODO(), repoName, types.ImagePushOptions{RegistryAuth: "{}"})
... ...
@@ -545,9 +543,7 @@ func (s *DockerSuite) TestBuildWithSession(c *check.C) {
545 545
 	assert.Equal(c, strings.Count(out, "Using cache"), 2)
546 546
 	assert.Contains(c, out, "contentcontent")
547 547
 
548
-	client, err := request.NewClient()
549
-	require.NoError(c, err)
550
-
548
+	client := testEnv.APIClient()
551 549
 	du, err := client.DiskUsage(context.TODO())
552 550
 	assert.Nil(c, err)
553 551
 	assert.True(c, du.BuilderSize > 10)
... ...
@@ -582,9 +578,7 @@ func (s *DockerSuite) TestBuildWithSession(c *check.C) {
582 582
 }
583 583
 
584 584
 func testBuildWithSession(c *check.C, dir, dockerfile string) (outStr string) {
585
-	client, err := request.NewClient()
586
-	require.NoError(c, err)
587
-
585
+	client := testEnv.APIClient()
588 586
 	sess, err := session.NewSession("foo1", "foo")
589 587
 	assert.Nil(c, err)
590 588
 
... ...
@@ -6,13 +6,16 @@ import (
6 6
 	"fmt"
7 7
 	"io/ioutil"
8 8
 	"math/rand"
9
-	"net/http"
10 9
 	"strings"
11 10
 
12 11
 	winio "github.com/Microsoft/go-winio"
13
-	"github.com/docker/docker/integration-cli/checker"
14
-	"github.com/docker/docker/integration-cli/request"
12
+	"github.com/docker/docker/api/types"
13
+	"github.com/docker/docker/api/types/container"
14
+	"github.com/docker/docker/api/types/mount"
15 15
 	"github.com/go-check/check"
16
+	"github.com/stretchr/testify/assert"
17
+	"github.com/stretchr/testify/require"
18
+	"golang.org/x/net/context"
16 19
 )
17 20
 
18 21
 func (s *DockerSuite) TestContainersAPICreateMountsBindNamedPipe(c *check.C) {
... ...
@@ -44,28 +47,30 @@ func (s *DockerSuite) TestContainersAPICreateMountsBindNamedPipe(c *check.C) {
44 44
 	containerPipeName := `\\.\pipe\docker-cli-test-pipe`
45 45
 	text := "hello from a pipe"
46 46
 	cmd := fmt.Sprintf("echo %s > %s", text, containerPipeName)
47
-
48 47
 	name := "test-bind-npipe"
49
-	data := map[string]interface{}{
50
-		"Image":      testEnv.PlatformDefaults.BaseImage,
51
-		"Cmd":        []string{"cmd", "/c", cmd},
52
-		"HostConfig": map[string]interface{}{"Mounts": []map[string]interface{}{{"Type": "npipe", "Source": hostPipeName, "Target": containerPipeName}}},
53
-	}
54 48
 
55
-	status, resp, err := request.SockRequest("POST", "/containers/create?name="+name, data, daemonHost())
56
-	c.Assert(err, checker.IsNil, check.Commentf(string(resp)))
57
-	c.Assert(status, checker.Equals, http.StatusCreated, check.Commentf(string(resp)))
49
+	ctx := context.Background()
50
+	client := testEnv.APIClient()
51
+	_, err = client.ContainerCreate(ctx,
52
+		&container.Config{
53
+			Image: testEnv.PlatformDefaults.BaseImage,
54
+			Cmd:   []string{"cmd", "/c", cmd},
55
+		}, &container.HostConfig{
56
+			Mounts: []mount.Mount{
57
+				{
58
+					Type:   "npipe",
59
+					Source: hostPipeName,
60
+					Target: containerPipeName,
61
+				},
62
+			},
63
+		},
64
+		nil, name)
65
+	require.NoError(c, err)
58 66
 
59
-	status, _, err = request.SockRequest("POST", "/containers/"+name+"/start", nil, daemonHost())
60
-	c.Assert(err, checker.IsNil)
61
-	c.Assert(status, checker.Equals, http.StatusNoContent)
67
+	err = client.ContainerStart(ctx, name, types.ContainerStartOptions{})
68
+	require.NoError(c, err)
62 69
 
63 70
 	err = <-ch
64
-	if err != nil {
65
-		c.Fatal(err)
66
-	}
67
-	result := strings.TrimSpace(string(b))
68
-	if result != text {
69
-		c.Errorf("expected pipe to contain %s, got %s", text, result)
70
-	}
71
+	require.NoError(c, err)
72
+	assert.Equal(c, text, strings.TrimSpace(string(b)))
71 73
 }
... ...
@@ -59,7 +59,7 @@ func (s *DockerSuite) TestExecResizeImmediatelyAfterExecStart(c *check.C) {
59 59
 		}
60 60
 
61 61
 		payload := bytes.NewBufferString(`{"Tty":true}`)
62
-		conn, _, err := request.SockRequestHijack("POST", fmt.Sprintf("/exec/%s/start", execID), payload, "application/json", daemonHost())
62
+		conn, _, err := sockRequestHijack("POST", fmt.Sprintf("/exec/%s/start", execID), payload, "application/json", daemonHost())
63 63
 		if err != nil {
64 64
 			return fmt.Errorf("Failed to start the exec: %q", err.Error())
65 65
 		}
... ...
@@ -157,33 +157,21 @@ func (s *DockerSuite) TestAPIImagesSearchJSONContentType(c *check.C) {
157 157
 // Test case for 30027: image size reported as -1 in v1.12 client against v1.13 daemon.
158 158
 // This test checks to make sure both v1.12 and v1.13 client against v1.13 daemon get correct `Size` after the fix.
159 159
 func (s *DockerSuite) TestAPIImagesSizeCompatibility(c *check.C) {
160
-	cli, err := client.NewEnvClient()
161
-	c.Assert(err, checker.IsNil)
162
-	defer cli.Close()
160
+	apiclient := testEnv.APIClient()
161
+	defer apiclient.Close()
163 162
 
164
-	images, err := cli.ImageList(context.Background(), types.ImageListOptions{})
163
+	images, err := apiclient.ImageList(context.Background(), types.ImageListOptions{})
165 164
 	c.Assert(err, checker.IsNil)
166 165
 	c.Assert(len(images), checker.Not(checker.Equals), 0)
167 166
 	for _, image := range images {
168 167
 		c.Assert(image.Size, checker.Not(checker.Equals), int64(-1))
169 168
 	}
170 169
 
171
-	type v124Image struct {
172
-		ID          string `json:"Id"`
173
-		ParentID    string `json:"ParentId"`
174
-		RepoTags    []string
175
-		RepoDigests []string
176
-		Created     int64
177
-		Size        int64
178
-		VirtualSize int64
179
-		Labels      map[string]string
180
-	}
181
-
182
-	cli, err = client.NewClientWithOpts(client.FromEnv, client.WithVersion("v1.24"))
170
+	apiclient, err = client.NewClientWithOpts(client.FromEnv, client.WithVersion("v1.24"))
183 171
 	c.Assert(err, checker.IsNil)
184
-	defer cli.Close()
172
+	defer apiclient.Close()
185 173
 
186
-	v124Images, err := cli.ImageList(context.Background(), types.ImageListOptions{})
174
+	v124Images, err := apiclient.ImageList(context.Background(), types.ImageListOptions{})
187 175
 	c.Assert(err, checker.IsNil)
188 176
 	c.Assert(len(v124Images), checker.Not(checker.Equals), 0)
189 177
 	for _, image := range v124Images {
... ...
@@ -12,7 +12,6 @@ import (
12 12
 	"github.com/docker/docker/api/types/container"
13 13
 	"github.com/docker/docker/integration-cli/checker"
14 14
 	"github.com/docker/docker/integration-cli/cli"
15
-	"github.com/docker/docker/integration-cli/request"
16 15
 	"github.com/go-check/check"
17 16
 	"golang.org/x/net/context"
18 17
 )
... ...
@@ -59,8 +58,7 @@ func testIpcNonePrivateShareable(c *check.C, mode string, mustBeMounted bool, mu
59 59
 	}
60 60
 	ctx := context.Background()
61 61
 
62
-	client, err := request.NewClient()
63
-	c.Assert(err, checker.IsNil)
62
+	client := testEnv.APIClient()
64 63
 
65 64
 	resp, err := client.ContainerCreate(ctx, &cfg, &hostCfg, nil, "")
66 65
 	c.Assert(err, checker.IsNil)
... ...
@@ -125,8 +123,7 @@ func testIpcContainer(s *DockerSuite, c *check.C, donorMode string, mustWork boo
125 125
 	}
126 126
 	ctx := context.Background()
127 127
 
128
-	client, err := request.NewClient()
129
-	c.Assert(err, checker.IsNil)
128
+	client := testEnv.APIClient()
130 129
 
131 130
 	// create and start the "donor" container
132 131
 	resp, err := client.ContainerCreate(ctx, &cfg, &hostCfg, nil, "")
... ...
@@ -195,9 +192,7 @@ func (s *DockerSuite) TestAPIIpcModeHost(c *check.C) {
195 195
 	}
196 196
 	ctx := context.Background()
197 197
 
198
-	client, err := request.NewClient()
199
-	c.Assert(err, checker.IsNil)
200
-
198
+	client := testEnv.APIClient()
201 199
 	resp, err := client.ContainerCreate(ctx, &cfg, &hostCfg, nil, "")
202 200
 	c.Assert(err, checker.IsNil)
203 201
 	c.Assert(len(resp.Warnings), checker.Equals, 0)
... ...
@@ -3,12 +3,10 @@
3 3
 package main
4 4
 
5 5
 import (
6
-	"encoding/json"
7 6
 	"fmt"
8 7
 	"io/ioutil"
9 8
 	"net"
10 9
 	"net/http"
11
-	"net/url"
12 10
 	"os"
13 11
 	"path/filepath"
14 12
 	"strings"
... ...
@@ -21,11 +19,14 @@ import (
21 21
 	"github.com/docker/docker/api/types"
22 22
 	"github.com/docker/docker/api/types/container"
23 23
 	"github.com/docker/docker/api/types/swarm"
24
+	"github.com/docker/docker/client"
24 25
 	"github.com/docker/docker/integration-cli/checker"
25 26
 	"github.com/docker/docker/integration-cli/daemon"
26 27
 	"github.com/docker/docker/integration-cli/request"
27 28
 	"github.com/docker/swarmkit/ca"
28 29
 	"github.com/go-check/check"
30
+	"github.com/stretchr/testify/assert"
31
+	"github.com/stretchr/testify/require"
29 32
 	"golang.org/x/net/context"
30 33
 )
31 34
 
... ...
@@ -1006,32 +1007,19 @@ func (s *DockerSwarmSuite) TestSwarmRepeatedRootRotation(c *check.C) {
1006 1006
 func (s *DockerSwarmSuite) TestAPINetworkInspectWithScope(c *check.C) {
1007 1007
 	d := s.AddDaemon(c, true, true)
1008 1008
 
1009
-	name := "foo"
1010
-	networkCreateRequest := types.NetworkCreateRequest{
1011
-		Name: name,
1012
-	}
1013
-
1014
-	var n types.NetworkCreateResponse
1015
-	networkCreateRequest.NetworkCreate.Driver = "overlay"
1016
-
1017
-	status, out, err := d.SockRequest("POST", "/networks/create", networkCreateRequest)
1018
-	c.Assert(err, checker.IsNil, check.Commentf(string(out)))
1019
-	c.Assert(status, checker.Equals, http.StatusCreated, check.Commentf(string(out)))
1020
-	c.Assert(json.Unmarshal(out, &n), checker.IsNil)
1021
-
1022
-	var r types.NetworkResource
1009
+	name := "test-scoped-network"
1010
+	ctx := context.Background()
1011
+	apiclient, err := d.NewClient()
1012
+	require.NoError(c, err)
1023 1013
 
1024
-	status, body, err := d.SockRequest("GET", "/networks/"+name, nil)
1025
-	c.Assert(err, checker.IsNil, check.Commentf(string(out)))
1026
-	c.Assert(status, checker.Equals, http.StatusOK, check.Commentf(string(out)))
1027
-	c.Assert(json.Unmarshal(body, &r), checker.IsNil)
1028
-	c.Assert(r.Scope, checker.Equals, "swarm")
1029
-	c.Assert(r.ID, checker.Equals, n.ID)
1014
+	resp, err := apiclient.NetworkCreate(ctx, name, types.NetworkCreate{Driver: "overlay"})
1015
+	require.NoError(c, err)
1030 1016
 
1031
-	v := url.Values{}
1032
-	v.Set("scope", "local")
1017
+	network, err := apiclient.NetworkInspect(ctx, name, types.NetworkInspectOptions{})
1018
+	require.NoError(c, err)
1019
+	assert.Equal(c, "swarm", network.Scope)
1020
+	assert.Equal(c, resp.ID, network.ID)
1033 1021
 
1034
-	status, _, err = d.SockRequest("GET", "/networks/"+name+"?"+v.Encode(), nil)
1035
-	c.Assert(err, checker.IsNil, check.Commentf(string(out)))
1036
-	c.Assert(status, checker.Equals, http.StatusNotFound, check.Commentf(string(out)))
1022
+	_, err = apiclient.NetworkInspect(ctx, name, types.NetworkInspectOptions{Scope: "local"})
1023
+	assert.True(c, client.IsErrNotFound(err))
1037 1024
 }
... ...
@@ -15,7 +15,6 @@ import (
15 15
 	"github.com/docker/docker/integration-cli/cli"
16 16
 	"github.com/docker/docker/integration-cli/daemon"
17 17
 	"github.com/docker/docker/integration-cli/fixtures/plugin"
18
-	"github.com/docker/docker/integration-cli/request"
19 18
 	"github.com/go-check/check"
20 19
 	"github.com/gotestyourself/gotestyourself/icmd"
21 20
 	"golang.org/x/net/context"
... ...
@@ -159,9 +158,7 @@ func (s *DockerSuite) TestPluginInstallDisableVolumeLs(c *check.C) {
159 159
 }
160 160
 
161 161
 func (ps *DockerPluginSuite) TestPluginSet(c *check.C) {
162
-	// Create a new plugin with extra settings
163
-	client, err := request.NewClient()
164
-	c.Assert(err, checker.IsNil, check.Commentf("failed to create test client"))
162
+	client := testEnv.APIClient()
165 163
 
166 164
 	name := "test"
167 165
 	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
... ...
@@ -171,7 +168,8 @@ func (ps *DockerPluginSuite) TestPluginSet(c *check.C) {
171 171
 	mntSrc := "foo"
172 172
 	devPath := "/dev/bar"
173 173
 
174
-	err = plugin.Create(ctx, client, name, func(cfg *plugin.Config) {
174
+	// Create a new plugin with extra settings
175
+	err := plugin.Create(ctx, client, name, func(cfg *plugin.Config) {
175 176
 		cfg.Env = []types.PluginEnv{{Name: "DEBUG", Value: &initialValue, Settable: []string{"value"}}}
176 177
 		cfg.Mounts = []types.PluginMount{
177 178
 			{Name: "pmount1", Settable: []string{"source"}, Type: "none", Source: &mntSrc},
... ...
@@ -401,12 +399,11 @@ func (s *DockerTrustSuite) TestPluginUntrustedInstall(c *check.C) {
401 401
 
402 402
 func (ps *DockerPluginSuite) TestPluginIDPrefix(c *check.C) {
403 403
 	name := "test"
404
-	client, err := request.NewClient()
405
-	c.Assert(err, checker.IsNil, check.Commentf("error creating test client"))
404
+	client := testEnv.APIClient()
406 405
 
407 406
 	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
408 407
 	initialValue := "0"
409
-	err = plugin.Create(ctx, client, name, func(cfg *plugin.Config) {
408
+	err := plugin.Create(ctx, client, name, func(cfg *plugin.Config) {
410 409
 		cfg.Env = []types.PluginEnv{{Name: "DEBUG", Value: &initialValue, Settable: []string{"value"}}}
411 410
 	})
412 411
 	cancel()
... ...
@@ -466,8 +463,7 @@ func (ps *DockerPluginSuite) TestPluginListDefaultFormat(c *check.C) {
466 466
 	c.Assert(err, check.IsNil)
467 467
 
468 468
 	name := "test:latest"
469
-	client, err := request.NewClient()
470
-	c.Assert(err, checker.IsNil, check.Commentf("error creating test client"))
469
+	client := testEnv.APIClient()
471 470
 
472 471
 	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
473 472
 	defer cancel()
... ...
@@ -1,16 +1,13 @@
1 1
 package request // import "github.com/docker/docker/integration-cli/request"
2 2
 
3 3
 import (
4
-	"bufio"
5 4
 	"bytes"
6 5
 	"crypto/tls"
7 6
 	"encoding/json"
8
-	"fmt"
9 7
 	"io"
10 8
 	"io/ioutil"
11 9
 	"net"
12 10
 	"net/http"
13
-	"net/http/httputil"
14 11
 	"net/url"
15 12
 	"os"
16 13
 	"path/filepath"
... ...
@@ -95,11 +92,11 @@ func Do(endpoint string, modifiers ...func(*http.Request) error) (*http.Response
95 95
 
96 96
 // DoOnHost creates and execute a request on the specified host and endpoint, with the specified request modifiers
97 97
 func DoOnHost(host, endpoint string, modifiers ...func(*http.Request) error) (*http.Response, io.ReadCloser, error) {
98
-	req, err := New(host, endpoint, modifiers...)
98
+	req, err := newRequest(host, endpoint, modifiers...)
99 99
 	if err != nil {
100 100
 		return nil, nil, err
101 101
 	}
102
-	client, err := NewHTTPClient(host)
102
+	client, err := newHTTPClient(host)
103 103
 	if err != nil {
104 104
 		return nil, nil, err
105 105
 	}
... ...
@@ -114,18 +111,15 @@ func DoOnHost(host, endpoint string, modifiers ...func(*http.Request) error) (*h
114 114
 	return resp, body, err
115 115
 }
116 116
 
117
-// New creates a new http Request to the specified host and endpoint, with the specified request modifiers
118
-func New(host, endpoint string, modifiers ...func(*http.Request) error) (*http.Request, error) {
119
-	_, addr, _, err := dclient.ParseHost(host)
117
+// newRequest creates a new http Request to the specified host and endpoint, with the specified request modifiers
118
+func newRequest(host, endpoint string, modifiers ...func(*http.Request) error) (*http.Request, error) {
119
+	hostUrl, err := dclient.ParseHostURL(host)
120 120
 	if err != nil {
121
-		return nil, err
122
-	}
123
-	if err != nil {
124
-		return nil, errors.Wrapf(err, "could not parse url %q", host)
121
+		return nil, errors.Wrapf(err, "failed parsing url %q", host)
125 122
 	}
126 123
 	req, err := http.NewRequest("GET", endpoint, nil)
127 124
 	if err != nil {
128
-		return nil, fmt.Errorf("could not create new request: %v", err)
125
+		return nil, errors.Wrap(err, "failed to create request")
129 126
 	}
130 127
 
131 128
 	if os.Getenv("DOCKER_TLS_VERIFY") != "" {
... ...
@@ -133,7 +127,7 @@ func New(host, endpoint string, modifiers ...func(*http.Request) error) (*http.R
133 133
 	} else {
134 134
 		req.URL.Scheme = "http"
135 135
 	}
136
-	req.URL.Host = addr
136
+	req.URL.Host = hostUrl.Host
137 137
 
138 138
 	for _, config := range modifiers {
139 139
 		if err := config(req); err != nil {
... ...
@@ -143,15 +137,16 @@ func New(host, endpoint string, modifiers ...func(*http.Request) error) (*http.R
143 143
 	return req, nil
144 144
 }
145 145
 
146
-// NewHTTPClient creates an http client for the specific host
147
-func NewHTTPClient(host string) (*http.Client, error) {
146
+// newHTTPClient creates an http client for the specific host
147
+// TODO: Share more code with client.defaultHTTPClient
148
+func newHTTPClient(host string) (*http.Client, error) {
148 149
 	// FIXME(vdemeester) 10*time.Second timeout of SockRequest… ?
149
-	proto, addr, _, err := dclient.ParseHost(host)
150
+	hostUrl, err := dclient.ParseHostURL(host)
150 151
 	if err != nil {
151 152
 		return nil, err
152 153
 	}
153 154
 	transport := new(http.Transport)
154
-	if proto == "tcp" && os.Getenv("DOCKER_TLS_VERIFY") != "" {
155
+	if hostUrl.Scheme == "tcp" && os.Getenv("DOCKER_TLS_VERIFY") != "" {
155 156
 		// Setup the socket TLS configuration.
156 157
 		tlsConfig, err := getTLSConfig()
157 158
 		if err != nil {
... ...
@@ -160,102 +155,22 @@ func NewHTTPClient(host string) (*http.Client, error) {
160 160
 		transport = &http.Transport{TLSClientConfig: tlsConfig}
161 161
 	}
162 162
 	transport.DisableKeepAlives = true
163
-	err = sockets.ConfigureTransport(transport, proto, addr)
164
-	return &http.Client{
165
-		Transport: transport,
166
-	}, err
163
+	err = sockets.ConfigureTransport(transport, hostUrl.Scheme, hostUrl.Host)
164
+	return &http.Client{Transport: transport}, err
167 165
 }
168 166
 
169 167
 // NewClient returns a new Docker API client
168
+// Deprecated: Use Execution.APIClient()
170 169
 func NewClient() (dclient.APIClient, error) {
171 170
 	return dclient.NewClientWithOpts(dclient.WithHost(DaemonHost()))
172 171
 }
173 172
 
174
-// FIXME(vdemeester) httputil.ClientConn is deprecated, use http.Client instead (closer to actual client)
175
-// Deprecated: Use New instead of NewRequestClient
176
-// Deprecated: use request.Do (or Get, Delete, Post) instead
177
-func newRequestClient(method, endpoint string, data io.Reader, ct, daemon string, modifiers ...func(*http.Request)) (*http.Request, *httputil.ClientConn, error) {
178
-	c, err := SockConn(time.Duration(10*time.Second), daemon)
179
-	if err != nil {
180
-		return nil, nil, fmt.Errorf("could not dial docker daemon: %v", err)
181
-	}
182
-
183
-	client := httputil.NewClientConn(c, nil)
184
-
185
-	req, err := http.NewRequest(method, endpoint, data)
186
-	if err != nil {
187
-		client.Close()
188
-		return nil, nil, fmt.Errorf("could not create new request: %v", err)
189
-	}
190
-
191
-	for _, opt := range modifiers {
192
-		opt(req)
193
-	}
194
-
195
-	if ct != "" {
196
-		req.Header.Set("Content-Type", ct)
197
-	}
198
-	return req, client, nil
199
-}
200
-
201
-// SockRequest create a request against the specified host (with method, endpoint and other request modifier) and
202
-// returns the status code, and the content as an byte slice
203
-// Deprecated: use request.Do instead
204
-func SockRequest(method, endpoint string, data interface{}, daemon string, modifiers ...func(*http.Request)) (int, []byte, error) {
205
-	jsonData := bytes.NewBuffer(nil)
206
-	if err := json.NewEncoder(jsonData).Encode(data); err != nil {
207
-		return -1, nil, err
208
-	}
209
-
210
-	res, body, err := SockRequestRaw(method, endpoint, jsonData, "application/json", daemon, modifiers...)
211
-	if err != nil {
212
-		return -1, nil, err
213
-	}
214
-	b, err := ReadBody(body)
215
-	return res.StatusCode, b, err
216
-}
217
-
218 173
 // ReadBody read the specified ReadCloser content and returns it
219 174
 func ReadBody(b io.ReadCloser) ([]byte, error) {
220 175
 	defer b.Close()
221 176
 	return ioutil.ReadAll(b)
222 177
 }
223 178
 
224
-// SockRequestRaw create a request against the specified host (with method, endpoint and other request modifier) and
225
-// returns the http response, the output as a io.ReadCloser
226
-// Deprecated: use request.Do (or Get, Delete, Post) instead
227
-func SockRequestRaw(method, endpoint string, data io.Reader, ct, daemon string, modifiers ...func(*http.Request)) (*http.Response, io.ReadCloser, error) {
228
-	req, client, err := newRequestClient(method, endpoint, data, ct, daemon, modifiers...)
229
-	if err != nil {
230
-		return nil, nil, err
231
-	}
232
-
233
-	resp, err := client.Do(req)
234
-	if err != nil {
235
-		client.Close()
236
-		return resp, nil, err
237
-	}
238
-	body := ioutils.NewReadCloserWrapper(resp.Body, func() error {
239
-		defer resp.Body.Close()
240
-		return client.Close()
241
-	})
242
-
243
-	return resp, body, err
244
-}
245
-
246
-// SockRequestHijack creates a connection to specified host (with method, contenttype, …) and returns a hijacked connection
247
-// and the output as a `bufio.Reader`
248
-func SockRequestHijack(method, endpoint string, data io.Reader, ct string, daemon string, modifiers ...func(*http.Request)) (net.Conn, *bufio.Reader, error) {
249
-	req, client, err := newRequestClient(method, endpoint, data, ct, daemon, modifiers...)
250
-	if err != nil {
251
-		return nil, nil, err
252
-	}
253
-
254
-	client.Do(req)
255
-	conn, br := client.Hijack()
256
-	return conn, br, nil
257
-}
258
-
259 179
 // SockConn opens a connection on the specified socket
260 180
 func SockConn(timeout time.Duration, daemon string) (net.Conn, error) {
261 181
 	daemonURL, err := url.Parse(daemon)
... ...
@@ -17,7 +17,6 @@ import (
17 17
 	"github.com/docker/docker/integration-cli/checker"
18 18
 	"github.com/docker/docker/integration-cli/cli"
19 19
 	"github.com/docker/docker/integration-cli/fixtures/plugin"
20
-	"github.com/docker/docker/integration-cli/request"
21 20
 	"github.com/docker/go-connections/tlsconfig"
22 21
 	"github.com/go-check/check"
23 22
 	"github.com/gotestyourself/gotestyourself/icmd"
... ...
@@ -230,11 +229,10 @@ func (s *DockerTrustSuite) setupTrustedImage(c *check.C, name string) string {
230 230
 func (s *DockerTrustSuite) setupTrustedplugin(c *check.C, source, name string) string {
231 231
 	repoName := fmt.Sprintf("%v/dockercli/%s:latest", privateRegistryURL, name)
232 232
 
233
-	client, err := request.NewClient()
234
-	c.Assert(err, checker.IsNil, check.Commentf("could not create test client"))
233
+	client := testEnv.APIClient()
235 234
 
236 235
 	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
237
-	err = plugin.Create(ctx, client, repoName)
236
+	err := plugin.Create(ctx, client, repoName)
238 237
 	cancel()
239 238
 	c.Assert(err, checker.IsNil, check.Commentf("could not create test plugin"))
240 239