Browse code

api/client: have cli.call() return headers

Docker-DCO-1.1-Signed-off-by: Josh Hawn <josh.hawn@docker.com> (github: jlhawn)

Josh Hawn authored on 2015/05/14 10:36:36
Showing 19 changed files
... ...
@@ -26,7 +26,7 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
26 26
 	cmd.ParseFlags(args, true)
27 27
 	name := cmd.Arg(0)
28 28
 
29
-	stream, _, err := cli.call("GET", "/containers/"+name+"/json", nil, nil)
29
+	stream, _, _, err := cli.call("GET", "/containers/"+name+"/json", nil, nil)
30 30
 	if err != nil {
31 31
 		return err
32 32
 	}
... ...
@@ -66,7 +66,7 @@ func (cli *DockerCli) CmdCommit(args ...string) error {
66 66
 			return err
67 67
 		}
68 68
 	}
69
-	stream, _, err := cli.call("POST", "/commit?"+v.Encode(), config, nil)
69
+	stream, _, _, err := cli.call("POST", "/commit?"+v.Encode(), config, nil)
70 70
 	if err != nil {
71 71
 		return err
72 72
 	}
... ...
@@ -31,7 +31,7 @@ func (cli *DockerCli) CmdCp(args ...string) error {
31 31
 	cfg := &types.CopyConfig{
32 32
 		Resource: info[1],
33 33
 	}
34
-	stream, statusCode, err := cli.call("POST", "/containers/"+info[0]+"/copy", cfg, nil)
34
+	stream, _, statusCode, err := cli.call("POST", "/containers/"+info[0]+"/copy", cfg, nil)
35 35
 	if stream != nil {
36 36
 		defer stream.Close()
37 37
 	}
... ...
@@ -95,7 +95,7 @@ func (cli *DockerCli) createContainer(config *runconfig.Config, hostConfig *runc
95 95
 	}
96 96
 
97 97
 	//create the container
98
-	stream, statusCode, err := cli.call("POST", "/containers/create?"+containerValues.Encode(), mergedConfig, nil)
98
+	stream, _, statusCode, err := cli.call("POST", "/containers/create?"+containerValues.Encode(), mergedConfig, nil)
99 99
 	//if image not found try to pull it
100 100
 	if statusCode == 404 && strings.Contains(err.Error(), config.Image) {
101 101
 		repo, tag := parsers.ParseRepositoryTag(config.Image)
... ...
@@ -109,7 +109,7 @@ func (cli *DockerCli) createContainer(config *runconfig.Config, hostConfig *runc
109 109
 			return nil, err
110 110
 		}
111 111
 		// Retry
112
-		if stream, _, err = cli.call("POST", "/containers/create?"+containerValues.Encode(), mergedConfig, nil); err != nil {
112
+		if stream, _, _, err = cli.call("POST", "/containers/create?"+containerValues.Encode(), mergedConfig, nil); err != nil {
113 113
 			return nil, err
114 114
 		}
115 115
 	} else if err != nil {
... ...
@@ -25,7 +25,7 @@ func (cli *DockerCli) CmdDiff(args ...string) error {
25 25
 		return fmt.Errorf("Container name cannot be empty")
26 26
 	}
27 27
 
28
-	rdr, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/changes", nil, nil)
28
+	rdr, _, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/changes", nil, nil)
29 29
 	if err != nil {
30 30
 		return err
31 31
 	}
... ...
@@ -23,7 +23,7 @@ func (cli *DockerCli) CmdExec(args ...string) error {
23 23
 		return StatusError{StatusCode: 1}
24 24
 	}
25 25
 
26
-	stream, _, err := cli.call("POST", "/containers/"+execConfig.Container+"/exec", execConfig, nil)
26
+	stream, _, _, err := cli.call("POST", "/containers/"+execConfig.Container+"/exec", execConfig, nil)
27 27
 	if err != nil {
28 28
 		return err
29 29
 	}
... ...
@@ -24,7 +24,7 @@ func (cli *DockerCli) CmdHistory(args ...string) error {
24 24
 	cmd.Require(flag.Exact, 1)
25 25
 	cmd.ParseFlags(args, true)
26 26
 
27
-	rdr, _, err := cli.call("GET", "/images/"+cmd.Arg(0)+"/history", nil, nil)
27
+	rdr, _, _, err := cli.call("GET", "/images/"+cmd.Arg(0)+"/history", nil, nil)
28 28
 	if err != nil {
29 29
 		return err
30 30
 	}
... ...
@@ -61,7 +61,7 @@ func (cli *DockerCli) CmdImages(args ...string) error {
61 61
 		v.Set("all", "1")
62 62
 	}
63 63
 
64
-	rdr, _, err := cli.call("GET", "/images/json?"+v.Encode(), nil, nil)
64
+	rdr, _, _, err := cli.call("GET", "/images/json?"+v.Encode(), nil, nil)
65 65
 	if err != nil {
66 66
 		return err
67 67
 	}
... ...
@@ -18,7 +18,7 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
18 18
 	cmd.Require(flag.Exact, 0)
19 19
 	cmd.ParseFlags(args, true)
20 20
 
21
-	rdr, _, err := cli.call("GET", "/info", nil, nil)
21
+	rdr, _, _, err := cli.call("GET", "/info", nil, nil)
22 22
 	if err != nil {
23 23
 		return err
24 24
 	}
... ...
@@ -113,7 +113,7 @@ func (cli *DockerCli) CmdLogin(args ...string) error {
113 113
 	authconfig.ServerAddress = serverAddress
114 114
 	cli.configFile.AuthConfigs[serverAddress] = authconfig
115 115
 
116
-	stream, statusCode, err := cli.call("POST", "/auth", cli.configFile.AuthConfigs[serverAddress], nil)
116
+	stream, _, statusCode, err := cli.call("POST", "/auth", cli.configFile.AuthConfigs[serverAddress], nil)
117 117
 	if statusCode == 401 {
118 118
 		delete(cli.configFile.AuthConfigs, serverAddress)
119 119
 		if err2 := cli.configFile.Save(); err2 != nil {
... ...
@@ -28,7 +28,7 @@ func (cli *DockerCli) CmdLogs(args ...string) error {
28 28
 
29 29
 	name := cmd.Arg(0)
30 30
 
31
-	stream, _, err := cli.call("GET", "/containers/"+name+"/json", nil, nil)
31
+	stream, _, _, err := cli.call("GET", "/containers/"+name+"/json", nil, nil)
32 32
 	if err != nil {
33 33
 		return err
34 34
 	}
... ...
@@ -18,7 +18,7 @@ func (cli *DockerCli) CmdPort(args ...string) error {
18 18
 	cmd.Require(flag.Min, 1)
19 19
 	cmd.ParseFlags(args, true)
20 20
 
21
-	stream, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/json", nil, nil)
21
+	stream, _, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/json", nil, nil)
22 22
 	if err != nil {
23 23
 		return err
24 24
 	}
... ...
@@ -86,7 +86,7 @@ func (cli *DockerCli) CmdPs(args ...string) error {
86 86
 		v.Set("filters", filterJSON)
87 87
 	}
88 88
 
89
-	rdr, _, err := cli.call("GET", "/containers/json?"+v.Encode(), nil, nil)
89
+	rdr, _, _, err := cli.call("GET", "/containers/json?"+v.Encode(), nil, nil)
90 90
 	if err != nil {
91 91
 		return err
92 92
 	}
... ...
@@ -31,7 +31,7 @@ func (cli *DockerCli) CmdRmi(args ...string) error {
31 31
 
32 32
 	var errNames []string
33 33
 	for _, name := range cmd.Args() {
34
-		rdr, _, err := cli.call("DELETE", "/images/"+name+"?"+v.Encode(), nil, nil)
34
+		rdr, _, _, err := cli.call("DELETE", "/images/"+name+"?"+v.Encode(), nil, nil)
35 35
 		if err != nil {
36 36
 			fmt.Fprintf(cli.err, "%s\n", err)
37 37
 			errNames = append(errNames, name)
... ...
@@ -61,7 +61,7 @@ func (cli *DockerCli) CmdStart(args ...string) error {
61 61
 			return fmt.Errorf("You cannot start and attach multiple containers at once.")
62 62
 		}
63 63
 
64
-		stream, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/json", nil, nil)
64
+		stream, _, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/json", nil, nil)
65 65
 		if err != nil {
66 66
 			return err
67 67
 		}
... ...
@@ -35,7 +35,7 @@ func (s *containerStats) Collect(cli *DockerCli, streamStats bool) {
35 35
 	} else {
36 36
 		v.Set("stream", "0")
37 37
 	}
38
-	stream, _, err := cli.call("GET", "/containers/"+s.Name+"/stats?"+v.Encode(), nil, nil)
38
+	stream, _, _, err := cli.call("GET", "/containers/"+s.Name+"/stats?"+v.Encode(), nil, nil)
39 39
 	if err != nil {
40 40
 		s.mu.Lock()
41 41
 		s.err = err
... ...
@@ -25,7 +25,7 @@ func (cli *DockerCli) CmdTop(args ...string) error {
25 25
 		val.Set("ps_args", strings.Join(cmd.Args()[1:], " "))
26 26
 	}
27 27
 
28
-	stream, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/top?"+val.Encode(), nil, nil)
28
+	stream, _, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/top?"+val.Encode(), nil, nil)
29 29
 	if err != nil {
30 30
 		return err
31 31
 	}
... ...
@@ -48,14 +48,14 @@ func (cli *DockerCli) encodeData(data interface{}) (*bytes.Buffer, error) {
48 48
 	return params, nil
49 49
 }
50 50
 
51
-func (cli *DockerCli) clientRequest(method, path string, in io.Reader, headers map[string][]string) (io.ReadCloser, string, int, error) {
51
+func (cli *DockerCli) clientRequest(method, path string, in io.Reader, headers map[string][]string) (io.ReadCloser, http.Header, int, error) {
52 52
 	expectedPayload := (method == "POST" || method == "PUT")
53 53
 	if expectedPayload && in == nil {
54 54
 		in = bytes.NewReader([]byte{})
55 55
 	}
56 56
 	req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", api.APIVERSION, path), in)
57 57
 	if err != nil {
58
-		return nil, "", -1, err
58
+		return nil, nil, -1, err
59 59
 	}
60 60
 
61 61
 	// Add CLI Config's HTTP Headers BEFORE we set the Docker headers
... ...
@@ -85,27 +85,27 @@ func (cli *DockerCli) clientRequest(method, path string, in io.Reader, headers m
85 85
 	}
86 86
 	if err != nil {
87 87
 		if strings.Contains(err.Error(), "connection refused") {
88
-			return nil, "", statusCode, errConnectionRefused
88
+			return nil, nil, statusCode, errConnectionRefused
89 89
 		}
90 90
 
91 91
 		if cli.tlsConfig == nil {
92
-			return nil, "", statusCode, fmt.Errorf("%v. Are you trying to connect to a TLS-enabled daemon without TLS?", err)
92
+			return nil, nil, statusCode, fmt.Errorf("%v. Are you trying to connect to a TLS-enabled daemon without TLS?", err)
93 93
 		}
94
-		return nil, "", statusCode, fmt.Errorf("An error occurred trying to connect: %v", err)
94
+		return nil, nil, statusCode, fmt.Errorf("An error occurred trying to connect: %v", err)
95 95
 	}
96 96
 
97 97
 	if statusCode < 200 || statusCode >= 400 {
98 98
 		body, err := ioutil.ReadAll(resp.Body)
99 99
 		if err != nil {
100
-			return nil, "", statusCode, err
100
+			return nil, nil, statusCode, err
101 101
 		}
102 102
 		if len(body) == 0 {
103
-			return nil, "", statusCode, fmt.Errorf("Error: request returned %s for API route and version %s, check if the server supports the requested API version", http.StatusText(statusCode), req.URL)
103
+			return nil, nil, statusCode, fmt.Errorf("Error: request returned %s for API route and version %s, check if the server supports the requested API version", http.StatusText(statusCode), req.URL)
104 104
 		}
105
-		return nil, "", statusCode, fmt.Errorf("Error response from daemon: %s", bytes.TrimSpace(body))
105
+		return nil, nil, statusCode, fmt.Errorf("Error response from daemon: %s", bytes.TrimSpace(body))
106 106
 	}
107 107
 
108
-	return resp.Body, resp.Header.Get("Content-Type"), statusCode, nil
108
+	return resp.Body, resp.Header, statusCode, nil
109 109
 }
110 110
 
111 111
 func (cli *DockerCli) clientRequestAttemptLogin(method, path string, in io.Reader, out io.Writer, index *registry.IndexInfo, cmdName string) (io.ReadCloser, int, error) {
... ...
@@ -119,13 +119,13 @@ func (cli *DockerCli) clientRequestAttemptLogin(method, path string, in io.Reade
119 119
 		}
120 120
 
121 121
 		// begin the request
122
-		body, contentType, statusCode, err := cli.clientRequest(method, path, in, map[string][]string{
122
+		body, hdr, statusCode, err := cli.clientRequest(method, path, in, map[string][]string{
123 123
 			"X-Registry-Auth": registryAuthHeader,
124 124
 		})
125 125
 		if err == nil && out != nil {
126 126
 			// If we are streaming output, complete the stream since
127 127
 			// errors may not appear until later.
128
-			err = cli.streamBody(body, contentType, true, out, nil)
128
+			err = cli.streamBody(body, hdr.Get("Content-Type"), true, out, nil)
129 129
 		}
130 130
 		if err != nil {
131 131
 			// Since errors in a stream appear after status 200 has been written,
... ...
@@ -153,10 +153,10 @@ func (cli *DockerCli) clientRequestAttemptLogin(method, path string, in io.Reade
153 153
 	return body, statusCode, err
154 154
 }
155 155
 
156
-func (cli *DockerCli) call(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, int, error) {
156
+func (cli *DockerCli) call(method, path string, data interface{}, headers map[string][]string) (io.ReadCloser, http.Header, int, error) {
157 157
 	params, err := cli.encodeData(data)
158 158
 	if err != nil {
159
-		return nil, -1, err
159
+		return nil, nil, -1, err
160 160
 	}
161 161
 
162 162
 	if data != nil {
... ...
@@ -166,8 +166,8 @@ func (cli *DockerCli) call(method, path string, data interface{}, headers map[st
166 166
 		headers["Content-Type"] = []string{"application/json"}
167 167
 	}
168 168
 
169
-	body, _, statusCode, err := cli.clientRequest(method, path, params, headers)
170
-	return body, statusCode, err
169
+	body, hdr, statusCode, err := cli.clientRequest(method, path, params, headers)
170
+	return body, hdr, statusCode, err
171 171
 }
172 172
 
173 173
 type streamOpts struct {
... ...
@@ -179,11 +179,11 @@ type streamOpts struct {
179 179
 }
180 180
 
181 181
 func (cli *DockerCli) stream(method, path string, opts *streamOpts) error {
182
-	body, contentType, _, err := cli.clientRequest(method, path, opts.in, opts.headers)
182
+	body, hdr, _, err := cli.clientRequest(method, path, opts.in, opts.headers)
183 183
 	if err != nil {
184 184
 		return err
185 185
 	}
186
-	return cli.streamBody(body, contentType, opts.rawTerminal, opts.out, opts.err)
186
+	return cli.streamBody(body, hdr.Get("Content-Type"), opts.rawTerminal, opts.out, opts.err)
187 187
 }
188 188
 
189 189
 func (cli *DockerCli) streamBody(body io.ReadCloser, contentType string, rawTerminal bool, stdout, stderr io.Writer) error {
... ...
@@ -228,7 +228,7 @@ func (cli *DockerCli) resizeTty(id string, isExec bool) {
228 228
 }
229 229
 
230 230
 func waitForExit(cli *DockerCli, containerID string) (int, error) {
231
-	stream, _, err := cli.call("POST", "/containers/"+containerID+"/wait", nil, nil)
231
+	stream, _, _, err := cli.call("POST", "/containers/"+containerID+"/wait", nil, nil)
232 232
 	if err != nil {
233 233
 		return -1, err
234 234
 	}
... ...
@@ -244,7 +244,7 @@ func waitForExit(cli *DockerCli, containerID string) (int, error) {
244 244
 // getExitCode perform an inspect on the container. It returns
245 245
 // the running state and the exit code.
246 246
 func getExitCode(cli *DockerCli, containerID string) (bool, int, error) {
247
-	stream, _, err := cli.call("GET", "/containers/"+containerID+"/json", nil, nil)
247
+	stream, _, _, err := cli.call("GET", "/containers/"+containerID+"/json", nil, nil)
248 248
 	if err != nil {
249 249
 		// If we can't connect, then the daemon probably died.
250 250
 		if err != errConnectionRefused {
... ...
@@ -264,7 +264,7 @@ func getExitCode(cli *DockerCli, containerID string) (bool, int, error) {
264 264
 // getExecExitCode perform an inspect on the exec command. It returns
265 265
 // the running state and the exit code.
266 266
 func getExecExitCode(cli *DockerCli, execID string) (bool, int, error) {
267
-	stream, _, err := cli.call("GET", "/exec/"+execID+"/json", nil, nil)
267
+	stream, _, _, err := cli.call("GET", "/exec/"+execID+"/json", nil, nil)
268 268
 	if err != nil {
269 269
 		// If we can't connect, then the daemon probably died.
270 270
 		if err != errConnectionRefused {
... ...
@@ -330,7 +330,7 @@ func (cli *DockerCli) getTtySize() (int, int) {
330 330
 	return int(ws.Height), int(ws.Width)
331 331
 }
332 332
 
333
-func readBody(stream io.ReadCloser, statusCode int, err error) ([]byte, int, error) {
333
+func readBody(stream io.ReadCloser, hdr http.Header, statusCode int, err error) ([]byte, int, error) {
334 334
 	if stream != nil {
335 335
 		defer stream.Close()
336 336
 	}
... ...
@@ -36,7 +36,7 @@ func (cli *DockerCli) CmdVersion(args ...string) error {
36 36
 		fmt.Fprintf(cli.out, "Experimental (client): true\n")
37 37
 	}
38 38
 
39
-	stream, _, err := cli.call("GET", "/version", nil, nil)
39
+	stream, _, _, err := cli.call("GET", "/version", nil, nil)
40 40
 	if err != nil {
41 41
 		return err
42 42
 	}