Signed-off-by: Shijiang Wei <mountkin@gmail.com>
Shijiang Wei authored on 2016/05/07 19:05:26... | ... |
@@ -5,6 +5,14 @@ import ( |
5 | 5 |
"github.com/docker/docker/api/server/router" |
6 | 6 |
) |
7 | 7 |
|
8 |
+type validationError struct { |
|
9 |
+ error |
|
10 |
+} |
|
11 |
+ |
|
12 |
+func (validationError) IsValidationError() bool { |
|
13 |
+ return true |
|
14 |
+} |
|
15 |
+ |
|
8 | 16 |
// containerRouter is a router to talk with the container controller |
9 | 17 |
type containerRouter struct { |
10 | 18 |
backend Backend |
... | ... |
@@ -131,8 +131,15 @@ func (s *containerRouter) postContainersStart(ctx context.Context, w http.Respon |
131 | 131 |
// net/http otherwise seems to swallow any headers related to chunked encoding |
132 | 132 |
// including r.TransferEncoding |
133 | 133 |
// allow a nil body for backwards compatibility |
134 |
+ |
|
134 | 135 |
var hostConfig *container.HostConfig |
135 |
- if r.Body != nil && (r.ContentLength > 0 || r.ContentLength == -1) { |
|
136 |
+ // A non-nil json object is at least 7 characters. |
|
137 |
+ if r.ContentLength > 7 || r.ContentLength == -1 { |
|
138 |
+ version := httputils.VersionFromContext(ctx) |
|
139 |
+ if versions.GreaterThanOrEqualTo(version, "1.24") { |
|
140 |
+ return validationError{fmt.Errorf("starting container with HostConfig was deprecated since v1.10 and removed in v1.12")} |
|
141 |
+ } |
|
142 |
+ |
|
136 | 143 |
if err := httputils.CheckForJSON(r); err != nil { |
137 | 144 |
return err |
138 | 145 |
} |
... | ... |
@@ -141,7 +148,6 @@ func (s *containerRouter) postContainersStart(ctx context.Context, w http.Respon |
141 | 141 |
if err != nil { |
142 | 142 |
return err |
143 | 143 |
} |
144 |
- |
|
145 | 144 |
hostConfig = c |
146 | 145 |
} |
147 | 146 |
|
... | ... |
@@ -122,6 +122,7 @@ This section lists each version from latest to oldest. Each listing includes a |
122 | 122 |
* `GET /events` now supports a `reload` event that is emitted when the daemon configuration is reloaded. |
123 | 123 |
* `GET /events` now supports filtering by daemon name or ID. |
124 | 124 |
* `GET /images/json` now supports filters `since` and `before`. |
125 |
+* `POST /containers/(id or name)/start` no longer accepts a `HostConfig`. |
|
125 | 126 |
|
126 | 127 |
### v1.23 API changes |
127 | 128 |
|
... | ... |
@@ -1010,10 +1010,6 @@ Status Codes: |
1010 | 1010 |
|
1011 | 1011 |
Start the container `id` |
1012 | 1012 |
|
1013 |
-> **Note**: |
|
1014 |
-> For backwards compatibility, this endpoint accepts a `HostConfig` as JSON-encoded request body. |
|
1015 |
-> See [create a container](#create-a-container) for details. |
|
1016 |
- |
|
1017 | 1013 |
**Example request**: |
1018 | 1014 |
|
1019 | 1015 |
POST /containers/e90e34656806/start HTTP/1.1 |
... | ... |
@@ -168,94 +168,6 @@ func (s *DockerSuite) TestContainerApiGetChanges(c *check.C) { |
168 | 168 |
c.Assert(success, checker.True, check.Commentf("/etc/passwd has been removed but is not present in the diff")) |
169 | 169 |
} |
170 | 170 |
|
171 |
-func (s *DockerSuite) TestContainerApiStartVolumeBinds(c *check.C) { |
|
172 |
- // TODO Windows CI: Investigate further why this fails on Windows to Windows CI. |
|
173 |
- testRequires(c, DaemonIsLinux) |
|
174 |
- path := "/foo" |
|
175 |
- if daemonPlatform == "windows" { |
|
176 |
- path = `c:\foo` |
|
177 |
- } |
|
178 |
- name := "testing" |
|
179 |
- config := map[string]interface{}{ |
|
180 |
- "Image": "busybox", |
|
181 |
- "Volumes": map[string]struct{}{path: {}}, |
|
182 |
- } |
|
183 |
- |
|
184 |
- status, _, err := sockRequest("POST", "/containers/create?name="+name, config) |
|
185 |
- c.Assert(err, checker.IsNil) |
|
186 |
- c.Assert(status, checker.Equals, http.StatusCreated) |
|
187 |
- |
|
188 |
- bindPath := randomTmpDirPath("test", daemonPlatform) |
|
189 |
- config = map[string]interface{}{ |
|
190 |
- "Binds": []string{bindPath + ":" + path}, |
|
191 |
- } |
|
192 |
- status, _, err = sockRequest("POST", "/containers/"+name+"/start", config) |
|
193 |
- c.Assert(err, checker.IsNil) |
|
194 |
- c.Assert(status, checker.Equals, http.StatusNoContent) |
|
195 |
- |
|
196 |
- pth, err := inspectMountSourceField(name, path) |
|
197 |
- c.Assert(err, checker.IsNil) |
|
198 |
- c.Assert(pth, checker.Equals, bindPath, check.Commentf("expected volume host path to be %s, got %s", bindPath, pth)) |
|
199 |
-} |
|
200 |
- |
|
201 |
-// Test for GH#10618 |
|
202 |
-func (s *DockerSuite) TestContainerApiStartDupVolumeBinds(c *check.C) { |
|
203 |
- // TODO Windows to Windows CI - Port this |
|
204 |
- testRequires(c, DaemonIsLinux) |
|
205 |
- name := "testdups" |
|
206 |
- config := map[string]interface{}{ |
|
207 |
- "Image": "busybox", |
|
208 |
- "Volumes": map[string]struct{}{"/tmp": {}}, |
|
209 |
- } |
|
210 |
- |
|
211 |
- status, _, err := sockRequest("POST", "/containers/create?name="+name, config) |
|
212 |
- c.Assert(err, checker.IsNil) |
|
213 |
- c.Assert(status, checker.Equals, http.StatusCreated) |
|
214 |
- |
|
215 |
- bindPath1 := randomTmpDirPath("test1", daemonPlatform) |
|
216 |
- bindPath2 := randomTmpDirPath("test2", daemonPlatform) |
|
217 |
- |
|
218 |
- config = map[string]interface{}{ |
|
219 |
- "Binds": []string{bindPath1 + ":/tmp", bindPath2 + ":/tmp"}, |
|
220 |
- } |
|
221 |
- status, body, err := sockRequest("POST", "/containers/"+name+"/start", config) |
|
222 |
- c.Assert(err, checker.IsNil) |
|
223 |
- c.Assert(status, checker.Equals, http.StatusInternalServerError) |
|
224 |
- c.Assert(string(body), checker.Contains, "Duplicate mount point", check.Commentf("Expected failure due to duplicate bind mounts to same path, instead got: %q with error: %v", string(body), err)) |
|
225 |
-} |
|
226 |
- |
|
227 |
-func (s *DockerSuite) TestContainerApiStartVolumesFrom(c *check.C) { |
|
228 |
- // TODO Windows to Windows CI - Port this |
|
229 |
- testRequires(c, DaemonIsLinux) |
|
230 |
- volName := "voltst" |
|
231 |
- volPath := "/tmp" |
|
232 |
- |
|
233 |
- dockerCmd(c, "run", "--name", volName, "-v", volPath, "busybox") |
|
234 |
- |
|
235 |
- name := "TestContainerApiStartVolumesFrom" |
|
236 |
- config := map[string]interface{}{ |
|
237 |
- "Image": "busybox", |
|
238 |
- "Volumes": map[string]struct{}{volPath: {}}, |
|
239 |
- } |
|
240 |
- |
|
241 |
- status, _, err := sockRequest("POST", "/containers/create?name="+name, config) |
|
242 |
- c.Assert(err, checker.IsNil) |
|
243 |
- c.Assert(status, checker.Equals, http.StatusCreated) |
|
244 |
- |
|
245 |
- config = map[string]interface{}{ |
|
246 |
- "VolumesFrom": []string{volName}, |
|
247 |
- } |
|
248 |
- status, _, err = sockRequest("POST", "/containers/"+name+"/start", config) |
|
249 |
- c.Assert(err, checker.IsNil) |
|
250 |
- c.Assert(status, checker.Equals, http.StatusNoContent) |
|
251 |
- |
|
252 |
- pth, err := inspectMountSourceField(name, volPath) |
|
253 |
- c.Assert(err, checker.IsNil) |
|
254 |
- pth2, err := inspectMountSourceField(volName, volPath) |
|
255 |
- c.Assert(err, checker.IsNil) |
|
256 |
- c.Assert(pth, checker.Equals, pth2, check.Commentf("expected volume host path to be %s, got %s", pth, pth2)) |
|
257 |
-} |
|
258 |
- |
|
259 | 171 |
func (s *DockerSuite) TestGetContainerStats(c *check.C) { |
260 | 172 |
// Problematic on Windows as Windows does not support stats |
261 | 173 |
testRequires(c, DaemonIsLinux) |
... | ... |
@@ -442,27 +354,6 @@ func (s *DockerSuite) TestGetStoppedContainerStats(c *check.C) { |
442 | 442 |
} |
443 | 443 |
} |
444 | 444 |
|
445 |
-// #9981 - Allow a docker created volume (ie, one in /var/lib/docker/volumes) to be used to overwrite (via passing in Binds on api start) an existing volume |
|
446 |
-func (s *DockerSuite) TestPostContainerBindNormalVolume(c *check.C) { |
|
447 |
- // TODO Windows to Windows CI - Port this |
|
448 |
- testRequires(c, DaemonIsLinux) |
|
449 |
- dockerCmd(c, "create", "-v", "/foo", "--name=one", "busybox") |
|
450 |
- |
|
451 |
- fooDir, err := inspectMountSourceField("one", "/foo") |
|
452 |
- c.Assert(err, checker.IsNil) |
|
453 |
- |
|
454 |
- dockerCmd(c, "create", "-v", "/foo", "--name=two", "busybox") |
|
455 |
- |
|
456 |
- bindSpec := map[string][]string{"Binds": {fooDir + ":/foo"}} |
|
457 |
- status, _, err := sockRequest("POST", "/containers/two/start", bindSpec) |
|
458 |
- c.Assert(err, checker.IsNil) |
|
459 |
- c.Assert(status, checker.Equals, http.StatusNoContent) |
|
460 |
- |
|
461 |
- fooDir2, err := inspectMountSourceField("two", "/foo") |
|
462 |
- c.Assert(err, checker.IsNil) |
|
463 |
- c.Assert(fooDir2, checker.Equals, fooDir, check.Commentf("expected volume path to be %s, got: %s", fooDir, fooDir2)) |
|
464 |
-} |
|
465 |
- |
|
466 | 445 |
func (s *DockerSuite) TestContainerApiPause(c *check.C) { |
467 | 446 |
// Problematic on Windows as Windows does not support pause |
468 | 447 |
testRequires(c, DaemonIsLinux) |
... | ... |
@@ -887,26 +778,6 @@ func (s *DockerSuite) TestCreateWithTooLowMemoryLimit(c *check.C) { |
887 | 887 |
c.Assert(string(b), checker.Contains, "Minimum memory limit allowed is 4MB") |
888 | 888 |
} |
889 | 889 |
|
890 |
-func (s *DockerSuite) TestStartWithTooLowMemoryLimit(c *check.C) { |
|
891 |
- // TODO Windows: Port once memory is supported |
|
892 |
- testRequires(c, DaemonIsLinux) |
|
893 |
- out, _ := dockerCmd(c, "create", "busybox") |
|
894 |
- |
|
895 |
- containerID := strings.TrimSpace(out) |
|
896 |
- |
|
897 |
- config := `{ |
|
898 |
- "CpuShares": 100, |
|
899 |
- "Memory": 524287 |
|
900 |
- }` |
|
901 |
- |
|
902 |
- res, body, err := sockRequestRaw("POST", "/containers/"+containerID+"/start", strings.NewReader(config), "application/json") |
|
903 |
- c.Assert(err, checker.IsNil) |
|
904 |
- b, err2 := readBody(body) |
|
905 |
- c.Assert(err2, checker.IsNil) |
|
906 |
- c.Assert(res.StatusCode, checker.Equals, http.StatusInternalServerError) |
|
907 |
- c.Assert(string(b), checker.Contains, "Minimum memory limit allowed is 4MB") |
|
908 |
-} |
|
909 |
- |
|
910 | 890 |
func (s *DockerSuite) TestContainerApiRename(c *check.C) { |
911 | 891 |
// TODO Windows: Debug why this sometimes fails on TP5. For now, leave disabled |
912 | 892 |
testRequires(c, DaemonIsLinux) |
... | ... |
@@ -973,13 +844,12 @@ func (s *DockerSuite) TestContainerApiStart(c *check.C) { |
973 | 973 |
c.Assert(err, checker.IsNil) |
974 | 974 |
c.Assert(status, checker.Equals, http.StatusCreated) |
975 | 975 |
|
976 |
- conf := make(map[string]interface{}) |
|
977 |
- status, _, err = sockRequest("POST", "/containers/"+name+"/start", conf) |
|
976 |
+ status, _, err = sockRequest("POST", "/containers/"+name+"/start", nil) |
|
978 | 977 |
c.Assert(err, checker.IsNil) |
979 | 978 |
c.Assert(status, checker.Equals, http.StatusNoContent) |
980 | 979 |
|
981 | 980 |
// second call to start should give 304 |
982 |
- status, _, err = sockRequest("POST", "/containers/"+name+"/start", conf) |
|
981 |
+ status, _, err = sockRequest("POST", "/containers/"+name+"/start", nil) |
|
983 | 982 |
c.Assert(err, checker.IsNil) |
984 | 983 |
|
985 | 984 |
// TODO(tibor): figure out why this doesn't work on windows |
... | ... |
@@ -1189,16 +1059,21 @@ func (s *DockerSuite) TestContainerApiDeleteRemoveVolume(c *check.C) { |
1189 | 1189 |
func (s *DockerSuite) TestContainerApiChunkedEncoding(c *check.C) { |
1190 | 1190 |
// TODO Windows CI: This can be ported |
1191 | 1191 |
testRequires(c, DaemonIsLinux) |
1192 |
- out, _ := dockerCmd(c, "create", "-v", "/foo", "busybox", "true") |
|
1193 |
- id := strings.TrimSpace(out) |
|
1194 | 1192 |
|
1195 | 1193 |
conn, err := sockConn(time.Duration(10 * time.Second)) |
1196 | 1194 |
c.Assert(err, checker.IsNil) |
1197 | 1195 |
client := httputil.NewClientConn(conn, nil) |
1198 | 1196 |
defer client.Close() |
1199 | 1197 |
|
1200 |
- bindCfg := strings.NewReader(`{"Binds": ["/tmp:/foo"]}`) |
|
1201 |
- req, err := http.NewRequest("POST", "/containers/"+id+"/start", bindCfg) |
|
1198 |
+ config := map[string]interface{}{ |
|
1199 |
+ "Image": "busybox", |
|
1200 |
+ "Cmd": append([]string{"/bin/sh", "-c"}, defaultSleepCommand...), |
|
1201 |
+ "OpenStdin": true, |
|
1202 |
+ } |
|
1203 |
+ b, err := json.Marshal(config) |
|
1204 |
+ c.Assert(err, checker.IsNil) |
|
1205 |
+ |
|
1206 |
+ req, err := http.NewRequest("POST", "/containers/create", bytes.NewBuffer(b)) |
|
1202 | 1207 |
c.Assert(err, checker.IsNil) |
1203 | 1208 |
req.Header.Set("Content-Type", "application/json") |
1204 | 1209 |
// This is a cheat to make the http request do chunked encoding |
... | ... |
@@ -1207,18 +1082,9 @@ func (s *DockerSuite) TestContainerApiChunkedEncoding(c *check.C) { |
1207 | 1207 |
req.ContentLength = -1 |
1208 | 1208 |
|
1209 | 1209 |
resp, err := client.Do(req) |
1210 |
- c.Assert(err, checker.IsNil, check.Commentf("error starting container with chunked encoding")) |
|
1210 |
+ c.Assert(err, checker.IsNil, check.Commentf("error creating container with chunked encoding")) |
|
1211 | 1211 |
resp.Body.Close() |
1212 |
- c.Assert(resp.StatusCode, checker.Equals, 204) |
|
1213 |
- |
|
1214 |
- out = inspectFieldJSON(c, id, "HostConfig.Binds") |
|
1215 |
- |
|
1216 |
- var binds []string |
|
1217 |
- c.Assert(json.NewDecoder(strings.NewReader(out)).Decode(&binds), checker.IsNil) |
|
1218 |
- c.Assert(binds, checker.HasLen, 1, check.Commentf("Got unexpected binds: %v", binds)) |
|
1219 |
- |
|
1220 |
- expected := "/tmp:/foo" |
|
1221 |
- c.Assert(binds[0], checker.Equals, expected, check.Commentf("got incorrect bind spec")) |
|
1212 |
+ c.Assert(resp.StatusCode, checker.Equals, http.StatusCreated) |
|
1222 | 1213 |
} |
1223 | 1214 |
|
1224 | 1215 |
func (s *DockerSuite) TestContainerApiPostContainerStop(c *check.C) { |
... | ... |
@@ -1302,59 +1168,6 @@ func (s *DockerSuite) TestPostContainersCreateWithStringOrSliceCapAddDrop(c *che |
1302 | 1302 |
c.Assert(status, checker.Equals, http.StatusCreated) |
1303 | 1303 |
} |
1304 | 1304 |
|
1305 |
-// #14640 |
|
1306 |
-func (s *DockerSuite) TestPostContainersStartWithoutLinksInHostConfig(c *check.C) { |
|
1307 |
- // TODO Windows: Windows doesn't support supplying a hostconfig on start. |
|
1308 |
- // An alternate test could be written to validate the negative testing aspect of this |
|
1309 |
- testRequires(c, DaemonIsLinux) |
|
1310 |
- name := "test-host-config-links" |
|
1311 |
- dockerCmd(c, append([]string{"create", "--name", name, "busybox"}, defaultSleepCommand...)...) |
|
1312 |
- |
|
1313 |
- hc := inspectFieldJSON(c, name, "HostConfig") |
|
1314 |
- config := `{"HostConfig":` + hc + `}` |
|
1315 |
- |
|
1316 |
- res, b, err := sockRequestRaw("POST", "/containers/"+name+"/start", strings.NewReader(config), "application/json") |
|
1317 |
- c.Assert(err, checker.IsNil) |
|
1318 |
- c.Assert(res.StatusCode, checker.Equals, http.StatusNoContent) |
|
1319 |
- b.Close() |
|
1320 |
-} |
|
1321 |
- |
|
1322 |
-// #14640 |
|
1323 |
-func (s *DockerSuite) TestPostContainersStartWithLinksInHostConfig(c *check.C) { |
|
1324 |
- // TODO Windows: Windows doesn't support supplying a hostconfig on start. |
|
1325 |
- // An alternate test could be written to validate the negative testing aspect of this |
|
1326 |
- testRequires(c, DaemonIsLinux) |
|
1327 |
- name := "test-host-config-links" |
|
1328 |
- dockerCmd(c, "run", "--name", "foo", "-d", "busybox", "top") |
|
1329 |
- dockerCmd(c, "create", "--name", name, "--link", "foo:bar", "busybox", "top") |
|
1330 |
- |
|
1331 |
- hc := inspectFieldJSON(c, name, "HostConfig") |
|
1332 |
- config := `{"HostConfig":` + hc + `}` |
|
1333 |
- |
|
1334 |
- res, b, err := sockRequestRaw("POST", "/containers/"+name+"/start", strings.NewReader(config), "application/json") |
|
1335 |
- c.Assert(err, checker.IsNil) |
|
1336 |
- c.Assert(res.StatusCode, checker.Equals, http.StatusNoContent) |
|
1337 |
- b.Close() |
|
1338 |
-} |
|
1339 |
- |
|
1340 |
-// #14640 |
|
1341 |
-func (s *DockerSuite) TestPostContainersStartWithLinksInHostConfigIdLinked(c *check.C) { |
|
1342 |
- // Windows does not support links |
|
1343 |
- testRequires(c, DaemonIsLinux) |
|
1344 |
- name := "test-host-config-links" |
|
1345 |
- out, _ := dockerCmd(c, "run", "--name", "link0", "-d", "busybox", "top") |
|
1346 |
- id := strings.TrimSpace(out) |
|
1347 |
- dockerCmd(c, "create", "--name", name, "--link", id, "busybox", "top") |
|
1348 |
- |
|
1349 |
- hc := inspectFieldJSON(c, name, "HostConfig") |
|
1350 |
- config := `{"HostConfig":` + hc + `}` |
|
1351 |
- |
|
1352 |
- res, b, err := sockRequestRaw("POST", "/containers/"+name+"/start", strings.NewReader(config), "application/json") |
|
1353 |
- c.Assert(err, checker.IsNil) |
|
1354 |
- c.Assert(res.StatusCode, checker.Equals, http.StatusNoContent) |
|
1355 |
- b.Close() |
|
1356 |
-} |
|
1357 |
- |
|
1358 | 1305 |
// #14915 |
1359 | 1306 |
func (s *DockerSuite) TestContainerApiCreateNoHostConfig118(c *check.C) { |
1360 | 1307 |
config := struct { |
... | ... |
@@ -1434,23 +1247,6 @@ func (s *DockerSuite) TestPostContainersCreateWithWrongCpusetValues(c *check.C) |
1434 | 1434 |
c.Assert(string(body), checker.Equals, expected) |
1435 | 1435 |
} |
1436 | 1436 |
|
1437 |
-func (s *DockerSuite) TestStartWithNilDNS(c *check.C) { |
|
1438 |
- // TODO Windows: Add once DNS is supported |
|
1439 |
- testRequires(c, DaemonIsLinux) |
|
1440 |
- out, _ := dockerCmd(c, "create", "busybox") |
|
1441 |
- containerID := strings.TrimSpace(out) |
|
1442 |
- |
|
1443 |
- config := `{"HostConfig": {"Dns": null}}` |
|
1444 |
- |
|
1445 |
- res, b, err := sockRequestRaw("POST", "/containers/"+containerID+"/start", strings.NewReader(config), "application/json") |
|
1446 |
- c.Assert(err, checker.IsNil) |
|
1447 |
- c.Assert(res.StatusCode, checker.Equals, http.StatusNoContent) |
|
1448 |
- b.Close() |
|
1449 |
- |
|
1450 |
- dns := inspectFieldJSON(c, containerID, "HostConfig.Dns") |
|
1451 |
- c.Assert(dns, checker.Equals, "[]") |
|
1452 |
-} |
|
1453 |
- |
|
1454 | 1437 |
func (s *DockerSuite) TestPostContainersCreateShmSizeNegative(c *check.C) { |
1455 | 1438 |
// ShmSize is not supported on Windows |
1456 | 1439 |
testRequires(c, DaemonIsLinux) |
... | ... |
@@ -1366,26 +1366,6 @@ func (s *DockerSuite) TestUserDefinedNetworkConnectDisconnectLink(c *check.C) { |
1366 | 1366 |
c.Assert(err, check.IsNil) |
1367 | 1367 |
} |
1368 | 1368 |
|
1369 |
-// #19100 This is a deprecated feature test, it should be removed in Docker 1.12 |
|
1370 |
-func (s *DockerNetworkSuite) TestDockerNetworkStartAPIWithHostconfig(c *check.C) { |
|
1371 |
- netName := "test" |
|
1372 |
- conName := "foo" |
|
1373 |
- dockerCmd(c, "network", "create", netName) |
|
1374 |
- dockerCmd(c, "create", "--name", conName, "busybox", "top") |
|
1375 |
- |
|
1376 |
- config := map[string]interface{}{ |
|
1377 |
- "HostConfig": map[string]interface{}{ |
|
1378 |
- "NetworkMode": netName, |
|
1379 |
- }, |
|
1380 |
- } |
|
1381 |
- _, _, err := sockRequest("POST", "/containers/"+conName+"/start", config) |
|
1382 |
- c.Assert(err, checker.IsNil) |
|
1383 |
- c.Assert(waitRun(conName), checker.IsNil) |
|
1384 |
- networks := inspectField(c, conName, "NetworkSettings.Networks") |
|
1385 |
- c.Assert(networks, checker.Contains, netName, check.Commentf(fmt.Sprintf("Should contain '%s' network", netName))) |
|
1386 |
- c.Assert(networks, checker.Not(checker.Contains), "bridge", check.Commentf("Should not contain 'bridge' network")) |
|
1387 |
-} |
|
1388 |
- |
|
1389 | 1369 |
func (s *DockerNetworkSuite) TestDockerNetworkDisconnectDefault(c *check.C) { |
1390 | 1370 |
netWorkName1 := "test1" |
1391 | 1371 |
netWorkName2 := "test2" |
1392 | 1372 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,227 @@ |
0 |
+// This file will be removed when we completely drop support for |
|
1 |
+// passing HostConfig to container start API. |
|
2 |
+ |
|
3 |
+package main |
|
4 |
+ |
|
5 |
+import ( |
|
6 |
+ "net/http" |
|
7 |
+ "strings" |
|
8 |
+ |
|
9 |
+ "github.com/docker/docker/pkg/integration/checker" |
|
10 |
+ "github.com/go-check/check" |
|
11 |
+) |
|
12 |
+ |
|
13 |
+func formatV123StartAPIURL(url string) string { |
|
14 |
+ return "/v1.23" + url |
|
15 |
+} |
|
16 |
+ |
|
17 |
+func (s *DockerSuite) TestDeprecatedContainerApiStartHostConfig(c *check.C) { |
|
18 |
+ name := "test-deprecated-api-124" |
|
19 |
+ dockerCmd(c, "create", "--name", name, "busybox") |
|
20 |
+ config := map[string]interface{}{ |
|
21 |
+ "Binds": []string{"/aa:/bb"}, |
|
22 |
+ } |
|
23 |
+ status, body, err := sockRequest("POST", "/containers/"+name+"/start", config) |
|
24 |
+ c.Assert(err, checker.IsNil) |
|
25 |
+ c.Assert(status, checker.Equals, http.StatusBadRequest) |
|
26 |
+ c.Assert(string(body), checker.Contains, "was deprecated since v1.10") |
|
27 |
+} |
|
28 |
+ |
|
29 |
+func (s *DockerSuite) TestDeprecatedContainerApiStartVolumeBinds(c *check.C) { |
|
30 |
+ // TODO Windows CI: Investigate further why this fails on Windows to Windows CI. |
|
31 |
+ testRequires(c, DaemonIsLinux) |
|
32 |
+ path := "/foo" |
|
33 |
+ if daemonPlatform == "windows" { |
|
34 |
+ path = `c:\foo` |
|
35 |
+ } |
|
36 |
+ name := "testing" |
|
37 |
+ config := map[string]interface{}{ |
|
38 |
+ "Image": "busybox", |
|
39 |
+ "Volumes": map[string]struct{}{path: {}}, |
|
40 |
+ } |
|
41 |
+ |
|
42 |
+ status, _, err := sockRequest("POST", formatV123StartAPIURL("/containers/create?name="+name), config) |
|
43 |
+ c.Assert(err, checker.IsNil) |
|
44 |
+ c.Assert(status, checker.Equals, http.StatusCreated) |
|
45 |
+ |
|
46 |
+ bindPath := randomTmpDirPath("test", daemonPlatform) |
|
47 |
+ config = map[string]interface{}{ |
|
48 |
+ "Binds": []string{bindPath + ":" + path}, |
|
49 |
+ } |
|
50 |
+ status, _, err = sockRequest("POST", formatV123StartAPIURL("/containers/"+name+"/start"), config) |
|
51 |
+ c.Assert(err, checker.IsNil) |
|
52 |
+ c.Assert(status, checker.Equals, http.StatusNoContent) |
|
53 |
+ |
|
54 |
+ pth, err := inspectMountSourceField(name, path) |
|
55 |
+ c.Assert(err, checker.IsNil) |
|
56 |
+ c.Assert(pth, checker.Equals, bindPath, check.Commentf("expected volume host path to be %s, got %s", bindPath, pth)) |
|
57 |
+} |
|
58 |
+ |
|
59 |
+// Test for GH#10618 |
|
60 |
+func (s *DockerSuite) TestDeprecatedContainerApiStartDupVolumeBinds(c *check.C) { |
|
61 |
+ // TODO Windows to Windows CI - Port this |
|
62 |
+ testRequires(c, DaemonIsLinux) |
|
63 |
+ name := "testdups" |
|
64 |
+ config := map[string]interface{}{ |
|
65 |
+ "Image": "busybox", |
|
66 |
+ "Volumes": map[string]struct{}{"/tmp": {}}, |
|
67 |
+ } |
|
68 |
+ |
|
69 |
+ status, _, err := sockRequest("POST", formatV123StartAPIURL("/containers/create?name="+name), config) |
|
70 |
+ c.Assert(err, checker.IsNil) |
|
71 |
+ c.Assert(status, checker.Equals, http.StatusCreated) |
|
72 |
+ |
|
73 |
+ bindPath1 := randomTmpDirPath("test1", daemonPlatform) |
|
74 |
+ bindPath2 := randomTmpDirPath("test2", daemonPlatform) |
|
75 |
+ |
|
76 |
+ config = map[string]interface{}{ |
|
77 |
+ "Binds": []string{bindPath1 + ":/tmp", bindPath2 + ":/tmp"}, |
|
78 |
+ } |
|
79 |
+ status, body, err := sockRequest("POST", formatV123StartAPIURL("/containers/"+name+"/start"), config) |
|
80 |
+ c.Assert(err, checker.IsNil) |
|
81 |
+ c.Assert(status, checker.Equals, http.StatusInternalServerError) |
|
82 |
+ c.Assert(string(body), checker.Contains, "Duplicate mount point", check.Commentf("Expected failure due to duplicate bind mounts to same path, instead got: %q with error: %v", string(body), err)) |
|
83 |
+} |
|
84 |
+ |
|
85 |
+func (s *DockerSuite) TestDeprecatedContainerApiStartVolumesFrom(c *check.C) { |
|
86 |
+ // TODO Windows to Windows CI - Port this |
|
87 |
+ testRequires(c, DaemonIsLinux) |
|
88 |
+ volName := "voltst" |
|
89 |
+ volPath := "/tmp" |
|
90 |
+ |
|
91 |
+ dockerCmd(c, "run", "--name", volName, "-v", volPath, "busybox") |
|
92 |
+ |
|
93 |
+ name := "TestContainerApiStartVolumesFrom" |
|
94 |
+ config := map[string]interface{}{ |
|
95 |
+ "Image": "busybox", |
|
96 |
+ "Volumes": map[string]struct{}{volPath: {}}, |
|
97 |
+ } |
|
98 |
+ |
|
99 |
+ status, _, err := sockRequest("POST", formatV123StartAPIURL("/containers/create?name="+name), config) |
|
100 |
+ c.Assert(err, checker.IsNil) |
|
101 |
+ c.Assert(status, checker.Equals, http.StatusCreated) |
|
102 |
+ |
|
103 |
+ config = map[string]interface{}{ |
|
104 |
+ "VolumesFrom": []string{volName}, |
|
105 |
+ } |
|
106 |
+ status, _, err = sockRequest("POST", formatV123StartAPIURL("/containers/"+name+"/start"), config) |
|
107 |
+ c.Assert(err, checker.IsNil) |
|
108 |
+ c.Assert(status, checker.Equals, http.StatusNoContent) |
|
109 |
+ |
|
110 |
+ pth, err := inspectMountSourceField(name, volPath) |
|
111 |
+ c.Assert(err, checker.IsNil) |
|
112 |
+ pth2, err := inspectMountSourceField(volName, volPath) |
|
113 |
+ c.Assert(err, checker.IsNil) |
|
114 |
+ c.Assert(pth, checker.Equals, pth2, check.Commentf("expected volume host path to be %s, got %s", pth, pth2)) |
|
115 |
+} |
|
116 |
+ |
|
117 |
+// #9981 - Allow a docker created volume (ie, one in /var/lib/docker/volumes) to be used to overwrite (via passing in Binds on api start) an existing volume |
|
118 |
+func (s *DockerSuite) TestDeprecatedPostContainerBindNormalVolume(c *check.C) { |
|
119 |
+ // TODO Windows to Windows CI - Port this |
|
120 |
+ testRequires(c, DaemonIsLinux) |
|
121 |
+ dockerCmd(c, "create", "-v", "/foo", "--name=one", "busybox") |
|
122 |
+ |
|
123 |
+ fooDir, err := inspectMountSourceField("one", "/foo") |
|
124 |
+ c.Assert(err, checker.IsNil) |
|
125 |
+ |
|
126 |
+ dockerCmd(c, "create", "-v", "/foo", "--name=two", "busybox") |
|
127 |
+ |
|
128 |
+ bindSpec := map[string][]string{"Binds": {fooDir + ":/foo"}} |
|
129 |
+ status, _, err := sockRequest("POST", formatV123StartAPIURL("/containers/two/start"), bindSpec) |
|
130 |
+ c.Assert(err, checker.IsNil) |
|
131 |
+ c.Assert(status, checker.Equals, http.StatusNoContent) |
|
132 |
+ |
|
133 |
+ fooDir2, err := inspectMountSourceField("two", "/foo") |
|
134 |
+ c.Assert(err, checker.IsNil) |
|
135 |
+ c.Assert(fooDir2, checker.Equals, fooDir, check.Commentf("expected volume path to be %s, got: %s", fooDir, fooDir2)) |
|
136 |
+} |
|
137 |
+ |
|
138 |
+func (s *DockerSuite) TestDeprecatedStartWithTooLowMemoryLimit(c *check.C) { |
|
139 |
+ // TODO Windows: Port once memory is supported |
|
140 |
+ testRequires(c, DaemonIsLinux) |
|
141 |
+ out, _ := dockerCmd(c, "create", "busybox") |
|
142 |
+ |
|
143 |
+ containerID := strings.TrimSpace(out) |
|
144 |
+ |
|
145 |
+ config := `{ |
|
146 |
+ "CpuShares": 100, |
|
147 |
+ "Memory": 524287 |
|
148 |
+ }` |
|
149 |
+ |
|
150 |
+ res, body, err := sockRequestRaw("POST", formatV123StartAPIURL("/containers/"+containerID+"/start"), strings.NewReader(config), "application/json") |
|
151 |
+ c.Assert(err, checker.IsNil) |
|
152 |
+ b, err2 := readBody(body) |
|
153 |
+ c.Assert(err2, checker.IsNil) |
|
154 |
+ c.Assert(res.StatusCode, checker.Equals, http.StatusInternalServerError) |
|
155 |
+ c.Assert(string(b), checker.Contains, "Minimum memory limit allowed is 4MB") |
|
156 |
+} |
|
157 |
+ |
|
158 |
+// #14640 |
|
159 |
+func (s *DockerSuite) TestDeprecatedPostContainersStartWithoutLinksInHostConfig(c *check.C) { |
|
160 |
+ // TODO Windows: Windows doesn't support supplying a hostconfig on start. |
|
161 |
+ // An alternate test could be written to validate the negative testing aspect of this |
|
162 |
+ testRequires(c, DaemonIsLinux) |
|
163 |
+ name := "test-host-config-links" |
|
164 |
+ dockerCmd(c, append([]string{"create", "--name", name, "busybox"}, defaultSleepCommand...)...) |
|
165 |
+ |
|
166 |
+ hc := inspectFieldJSON(c, name, "HostConfig") |
|
167 |
+ config := `{"HostConfig":` + hc + `}` |
|
168 |
+ |
|
169 |
+ res, b, err := sockRequestRaw("POST", formatV123StartAPIURL("/containers/"+name+"/start"), strings.NewReader(config), "application/json") |
|
170 |
+ c.Assert(err, checker.IsNil) |
|
171 |
+ c.Assert(res.StatusCode, checker.Equals, http.StatusNoContent) |
|
172 |
+ b.Close() |
|
173 |
+} |
|
174 |
+ |
|
175 |
+// #14640 |
|
176 |
+func (s *DockerSuite) TestDeprecatedPostContainersStartWithLinksInHostConfig(c *check.C) { |
|
177 |
+ // TODO Windows: Windows doesn't support supplying a hostconfig on start. |
|
178 |
+ // An alternate test could be written to validate the negative testing aspect of this |
|
179 |
+ testRequires(c, DaemonIsLinux) |
|
180 |
+ name := "test-host-config-links" |
|
181 |
+ dockerCmd(c, "run", "--name", "foo", "-d", "busybox", "top") |
|
182 |
+ dockerCmd(c, "create", "--name", name, "--link", "foo:bar", "busybox", "top") |
|
183 |
+ |
|
184 |
+ hc := inspectFieldJSON(c, name, "HostConfig") |
|
185 |
+ config := `{"HostConfig":` + hc + `}` |
|
186 |
+ |
|
187 |
+ res, b, err := sockRequestRaw("POST", formatV123StartAPIURL("/containers/"+name+"/start"), strings.NewReader(config), "application/json") |
|
188 |
+ c.Assert(err, checker.IsNil) |
|
189 |
+ c.Assert(res.StatusCode, checker.Equals, http.StatusNoContent) |
|
190 |
+ b.Close() |
|
191 |
+} |
|
192 |
+ |
|
193 |
+// #14640 |
|
194 |
+func (s *DockerSuite) TestDeprecatedPostContainersStartWithLinksInHostConfigIdLinked(c *check.C) { |
|
195 |
+ // Windows does not support links |
|
196 |
+ testRequires(c, DaemonIsLinux) |
|
197 |
+ name := "test-host-config-links" |
|
198 |
+ out, _ := dockerCmd(c, "run", "--name", "link0", "-d", "busybox", "top") |
|
199 |
+ id := strings.TrimSpace(out) |
|
200 |
+ dockerCmd(c, "create", "--name", name, "--link", id, "busybox", "top") |
|
201 |
+ |
|
202 |
+ hc := inspectFieldJSON(c, name, "HostConfig") |
|
203 |
+ config := `{"HostConfig":` + hc + `}` |
|
204 |
+ |
|
205 |
+ res, b, err := sockRequestRaw("POST", formatV123StartAPIURL("/containers/"+name+"/start"), strings.NewReader(config), "application/json") |
|
206 |
+ c.Assert(err, checker.IsNil) |
|
207 |
+ c.Assert(res.StatusCode, checker.Equals, http.StatusNoContent) |
|
208 |
+ b.Close() |
|
209 |
+} |
|
210 |
+ |
|
211 |
+func (s *DockerSuite) TestDeprecatedStartWithNilDNS(c *check.C) { |
|
212 |
+ // TODO Windows: Add once DNS is supported |
|
213 |
+ testRequires(c, DaemonIsLinux) |
|
214 |
+ out, _ := dockerCmd(c, "create", "busybox") |
|
215 |
+ containerID := strings.TrimSpace(out) |
|
216 |
+ |
|
217 |
+ config := `{"HostConfig": {"Dns": null}}` |
|
218 |
+ |
|
219 |
+ res, b, err := sockRequestRaw("POST", formatV123StartAPIURL("/containers/"+containerID+"/start"), strings.NewReader(config), "application/json") |
|
220 |
+ c.Assert(err, checker.IsNil) |
|
221 |
+ c.Assert(res.StatusCode, checker.Equals, http.StatusNoContent) |
|
222 |
+ b.Close() |
|
223 |
+ |
|
224 |
+ dns := inspectFieldJSON(c, containerID, "HostConfig.Dns") |
|
225 |
+ c.Assert(dns, checker.Equals, "[]") |
|
226 |
+} |
0 | 227 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,30 @@ |
0 |
+// +build !windows |
|
1 |
+ |
|
2 |
+package main |
|
3 |
+ |
|
4 |
+import ( |
|
5 |
+ "fmt" |
|
6 |
+ |
|
7 |
+ "github.com/docker/docker/pkg/integration/checker" |
|
8 |
+ "github.com/go-check/check" |
|
9 |
+) |
|
10 |
+ |
|
11 |
+// #19100 This is a deprecated feature test, it should be removed in Docker 1.12 |
|
12 |
+func (s *DockerNetworkSuite) TestDeprecatedDockerNetworkStartAPIWithHostconfig(c *check.C) { |
|
13 |
+ netName := "test" |
|
14 |
+ conName := "foo" |
|
15 |
+ dockerCmd(c, "network", "create", netName) |
|
16 |
+ dockerCmd(c, "create", "--name", conName, "busybox", "top") |
|
17 |
+ |
|
18 |
+ config := map[string]interface{}{ |
|
19 |
+ "HostConfig": map[string]interface{}{ |
|
20 |
+ "NetworkMode": netName, |
|
21 |
+ }, |
|
22 |
+ } |
|
23 |
+ _, _, err := sockRequest("POST", formatV123StartAPIURL("/containers/"+conName+"/start"), config) |
|
24 |
+ c.Assert(err, checker.IsNil) |
|
25 |
+ c.Assert(waitRun(conName), checker.IsNil) |
|
26 |
+ networks := inspectField(c, conName, "NetworkSettings.Networks") |
|
27 |
+ c.Assert(networks, checker.Contains, netName, check.Commentf(fmt.Sprintf("Should contain '%s' network", netName))) |
|
28 |
+ c.Assert(networks, checker.Not(checker.Contains), "bridge", check.Commentf("Should not contain 'bridge' network")) |
|
29 |
+} |