Signed-off-by: Shijiang Wei <mountkin@gmail.com>
| ... | ... |
@@ -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 |
+} |