api: remove handling of HostConfig on POST /containers/{id}/start (api < v1.24)
API v1.20 (Docker Engine v1.11.0) and older allowed a HostConfig to be passed when starting a container. This feature was deprecated in API v1.21 (Docker Engine v1.10.0) in3e7405aea8
, and removed in API v1.23 (Docker Engine v1.12.0) in commit0a8386c8be
. API v1.23 and older are deprecated, and this patch removes the feature. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
ffd877f948
commit
8758d08bb4
17 changed files with 12 additions and 462 deletions
|
@ -12,5 +12,4 @@ import (
|
|||
// container configuration.
|
||||
type ContainerDecoder interface {
|
||||
DecodeConfig(src io.Reader) (*container.Config, *container.HostConfig, *network.NetworkingConfig, error)
|
||||
DecodeHostConfig(src io.Reader) (*container.HostConfig, error)
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ type stateBackend interface {
|
|||
ContainerResize(name string, height, width int) error
|
||||
ContainerRestart(ctx context.Context, name string, options container.StopOptions) error
|
||||
ContainerRm(name string, config *backend.ContainerRmConfig) error
|
||||
ContainerStart(ctx context.Context, name string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
|
||||
ContainerStart(ctx context.Context, name string, checkpoint string, checkpointDir string) error
|
||||
ContainerStop(ctx context.Context, name string, options container.StopOptions) error
|
||||
ContainerUnpause(name string) error
|
||||
ContainerUpdate(name string, hostConfig *container.HostConfig) (container.ContainerUpdateOKBody, error)
|
||||
|
|
|
@ -168,14 +168,6 @@ func (s *containerRouter) getContainersExport(ctx context.Context, w http.Respon
|
|||
return s.backend.ContainerExport(ctx, vars["name"], w)
|
||||
}
|
||||
|
||||
type bodyOnStartError struct{}
|
||||
|
||||
func (bodyOnStartError) Error() string {
|
||||
return "starting container with non-empty request body was deprecated since API v1.22 and removed in v1.24"
|
||||
}
|
||||
|
||||
func (bodyOnStartError) InvalidParameter() {}
|
||||
|
||||
func (s *containerRouter) postContainersStart(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
||||
// If contentLength is -1, we can assumed chunked encoding
|
||||
// or more technically that the length is unknown
|
||||
|
@ -183,33 +175,17 @@ func (s *containerRouter) postContainersStart(ctx context.Context, w http.Respon
|
|||
// net/http otherwise seems to swallow any headers related to chunked encoding
|
||||
// including r.TransferEncoding
|
||||
// allow a nil body for backwards compatibility
|
||||
|
||||
version := httputils.VersionFromContext(ctx)
|
||||
var hostConfig *container.HostConfig
|
||||
//
|
||||
// A non-nil json object is at least 7 characters.
|
||||
if r.ContentLength > 7 || r.ContentLength == -1 {
|
||||
if versions.GreaterThanOrEqualTo(version, "1.24") {
|
||||
return bodyOnStartError{}
|
||||
}
|
||||
|
||||
if err := httputils.CheckForJSON(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c, err := s.decoder.DecodeHostConfig(r.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hostConfig = c
|
||||
return errdefs.InvalidParameter(errors.New("starting container with non-empty request body was deprecated since API v1.22 and removed in v1.24"))
|
||||
}
|
||||
|
||||
if err := httputils.ParseForm(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
checkpoint := r.Form.Get("checkpoint")
|
||||
checkpointDir := r.Form.Get("checkpoint-dir")
|
||||
if err := s.backend.ContainerStart(ctx, vars["name"], hostConfig, checkpoint, checkpointDir); err != nil {
|
||||
if err := s.backend.ContainerStart(ctx, vars["name"], r.Form.Get("checkpoint"), r.Form.Get("checkpoint-dir")); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ type ExecBackend interface {
|
|||
// ContainerRm removes a container specified by `id`.
|
||||
ContainerRm(name string, config *backend.ContainerRmConfig) error
|
||||
// ContainerStart starts a new container
|
||||
ContainerStart(ctx context.Context, containerID string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
|
||||
ContainerStart(ctx context.Context, containerID string, checkpoint string, checkpointDir string) error
|
||||
// ContainerWait stops processing until the given container is stopped.
|
||||
ContainerWait(ctx context.Context, name string, condition containerpkg.WaitCondition) (<-chan containerpkg.StateStatus, error)
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ func (c *containerManager) Run(ctx context.Context, cID string, stdout, stderr i
|
|||
}
|
||||
}()
|
||||
|
||||
if err := c.backend.ContainerStart(ctx, cID, nil, "", ""); err != nil {
|
||||
if err := c.backend.ContainerStart(ctx, cID, "", ""); err != nil {
|
||||
close(finished)
|
||||
logCancellationError(cancelErrCh, "error from ContainerStart: "+err.Error())
|
||||
return err
|
||||
|
|
|
@ -46,7 +46,7 @@ func (m *MockBackend) CommitBuildStep(ctx context.Context, c backend.CommitConfi
|
|||
return "", nil
|
||||
}
|
||||
|
||||
func (m *MockBackend) ContainerStart(ctx context.Context, containerID string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error {
|
||||
func (m *MockBackend) ContainerStart(ctx context.Context, containerID string, checkpoint string, checkpointDir string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ type Backend interface {
|
|||
SetupIngress(clustertypes.NetworkCreateRequest, string) (<-chan struct{}, error)
|
||||
ReleaseIngress() (<-chan struct{}, error)
|
||||
CreateManagedContainer(ctx context.Context, config backend.ContainerCreateConfig) (container.CreateResponse, error)
|
||||
ContainerStart(ctx context.Context, name string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
|
||||
ContainerStart(ctx context.Context, name string, checkpoint string, checkpointDir string) error
|
||||
ContainerStop(ctx context.Context, name string, config container.StopOptions) error
|
||||
ContainerLogs(ctx context.Context, name string, config *container.LogsOptions) (msgs <-chan *backend.LogMessage, tty bool, err error)
|
||||
ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error
|
||||
|
|
|
@ -347,7 +347,7 @@ func (c *containerAdapter) start(ctx context.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return c.backend.ContainerStart(ctx, c.container.name(), nil, "", "")
|
||||
return c.backend.ContainerStart(ctx, c.container.name(), "", "")
|
||||
}
|
||||
|
||||
func (c *containerAdapter) inspect(ctx context.Context) (types.ContainerJSON, error) {
|
||||
|
|
|
@ -2,12 +2,10 @@ package daemon // import "github.com/docker/docker/daemon"
|
|||
|
||||
import (
|
||||
"context"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/log"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
containertypes "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/errdefs"
|
||||
|
@ -41,7 +39,7 @@ func validateState(ctr *container.Container) error {
|
|||
}
|
||||
|
||||
// ContainerStart starts a container.
|
||||
func (daemon *Daemon) ContainerStart(ctx context.Context, name string, hostConfig *containertypes.HostConfig, checkpoint string, checkpointDir string) error {
|
||||
func (daemon *Daemon) ContainerStart(ctx context.Context, name string, checkpoint string, checkpointDir string) error {
|
||||
daemonCfg := daemon.config()
|
||||
if checkpoint != "" && !daemonCfg.Experimental {
|
||||
return errdefs.InvalidParameter(errors.New("checkpoint is only supported in experimental mode"))
|
||||
|
@ -55,51 +53,12 @@ func (daemon *Daemon) ContainerStart(ctx context.Context, name string, hostConfi
|
|||
return err
|
||||
}
|
||||
|
||||
// Windows does not have the backwards compatibility issue here.
|
||||
if runtime.GOOS != "windows" {
|
||||
// This is kept for backward compatibility - hostconfig should be passed when
|
||||
// creating a container, not during start.
|
||||
if hostConfig != nil {
|
||||
log.G(ctx).Warn("DEPRECATED: Setting host configuration options when the container starts is deprecated and has been removed in Docker 1.12")
|
||||
oldNetworkMode := ctr.HostConfig.NetworkMode
|
||||
if err := daemon.setSecurityOptions(&daemonCfg.Config, ctr, hostConfig); err != nil {
|
||||
return errdefs.InvalidParameter(err)
|
||||
}
|
||||
if err := daemon.mergeAndVerifyLogConfig(&hostConfig.LogConfig); err != nil {
|
||||
return errdefs.InvalidParameter(err)
|
||||
}
|
||||
if err := daemon.setHostConfig(ctr, hostConfig); err != nil {
|
||||
return errdefs.InvalidParameter(err)
|
||||
}
|
||||
newNetworkMode := ctr.HostConfig.NetworkMode
|
||||
if string(oldNetworkMode) != string(newNetworkMode) {
|
||||
// if user has change the network mode on starting, clean up the
|
||||
// old networks. It is a deprecated feature and has been removed in Docker 1.12
|
||||
ctr.NetworkSettings.Networks = nil
|
||||
}
|
||||
if err := ctr.CheckpointTo(daemon.containersReplica); err != nil {
|
||||
return errdefs.System(err)
|
||||
}
|
||||
ctr.InitDNSHostConfig()
|
||||
}
|
||||
} else {
|
||||
if hostConfig != nil {
|
||||
return errdefs.InvalidParameter(errors.New("Supplying a hostconfig on start is not supported. It should be supplied on create"))
|
||||
}
|
||||
}
|
||||
|
||||
// check if hostConfig is in line with the current system settings.
|
||||
// It may happen cgroups are umounted or the like.
|
||||
// It may happen cgroups are unmounted or the like.
|
||||
if _, err = daemon.verifyContainerSettings(daemonCfg, ctr.HostConfig, nil, false); err != nil {
|
||||
return errdefs.InvalidParameter(err)
|
||||
}
|
||||
// Adapt for old containers in case we have updates in this function and
|
||||
// old containers never have chance to call the new function in create stage.
|
||||
if hostConfig != nil {
|
||||
if err := daemon.adaptContainerSettings(&daemonCfg.Config, ctr.HostConfig); err != nil {
|
||||
return errdefs.InvalidParameter(err)
|
||||
}
|
||||
}
|
||||
|
||||
return daemon.containerStart(ctx, daemonCfg, ctr, checkpoint, checkpointDir, true)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,239 +0,0 @@
|
|||
// This file will be removed when we completely drop support for
|
||||
// passing HostConfig to container start API.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/integration-cli/cli"
|
||||
"github.com/docker/docker/testutil"
|
||||
"github.com/docker/docker/testutil/request"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
|
||||
func formatV123StartAPIURL(url string) string {
|
||||
return "/v1.23" + url
|
||||
}
|
||||
|
||||
func (s *DockerAPISuite) TestDeprecatedContainerAPIStartHostConfig(c *testing.T) {
|
||||
name := "test-deprecated-api-124"
|
||||
cli.DockerCmd(c, "create", "--name", name, "busybox")
|
||||
config := map[string]interface{}{
|
||||
"Binds": []string{"/aa:/bb"},
|
||||
}
|
||||
res, body, err := request.Post(testutil.GetContext(c), "/containers/"+name+"/start", request.JSONBody(config))
|
||||
assert.NilError(c, err)
|
||||
assert.Equal(c, res.StatusCode, http.StatusBadRequest)
|
||||
buf, err := request.ReadBody(body)
|
||||
assert.NilError(c, err)
|
||||
|
||||
assert.Equal(c, res.StatusCode, http.StatusBadRequest)
|
||||
assert.Assert(c, strings.Contains(string(buf), "was deprecated since API v1.22"))
|
||||
}
|
||||
|
||||
func (s *DockerAPISuite) TestDeprecatedContainerAPIStartVolumeBinds(c *testing.T) {
|
||||
// TODO Windows CI: Investigate further why this fails on Windows to Windows CI.
|
||||
testRequires(c, DaemonIsLinux)
|
||||
path := "/foo"
|
||||
if testEnv.DaemonInfo.OSType == "windows" {
|
||||
path = `c:\foo`
|
||||
}
|
||||
name := "testing"
|
||||
config := map[string]interface{}{
|
||||
"Image": "busybox",
|
||||
"Volumes": map[string]struct{}{path: {}},
|
||||
}
|
||||
|
||||
res, _, err := request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/create?name="+name), request.JSONBody(config))
|
||||
assert.NilError(c, err)
|
||||
assert.Equal(c, res.StatusCode, http.StatusCreated)
|
||||
|
||||
bindPath := RandomTmpDirPath("test", testEnv.DaemonInfo.OSType)
|
||||
config = map[string]interface{}{
|
||||
"Binds": []string{bindPath + ":" + path},
|
||||
}
|
||||
res, _, err = request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/"+name+"/start"), request.JSONBody(config))
|
||||
assert.NilError(c, err)
|
||||
assert.Equal(c, res.StatusCode, http.StatusNoContent)
|
||||
|
||||
pth, err := inspectMountSourceField(name, path)
|
||||
assert.NilError(c, err)
|
||||
assert.Equal(c, pth, bindPath, "expected volume host path to be %s, got %s", bindPath, pth)
|
||||
}
|
||||
|
||||
// Test for GH#10618
|
||||
func (s *DockerAPISuite) TestDeprecatedContainerAPIStartDupVolumeBinds(c *testing.T) {
|
||||
// TODO Windows to Windows CI - Port this
|
||||
testRequires(c, DaemonIsLinux)
|
||||
name := "testdups"
|
||||
config := map[string]interface{}{
|
||||
"Image": "busybox",
|
||||
"Volumes": map[string]struct{}{"/tmp": {}},
|
||||
}
|
||||
|
||||
res, _, err := request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/create?name="+name), request.JSONBody(config))
|
||||
assert.NilError(c, err)
|
||||
assert.Equal(c, res.StatusCode, http.StatusCreated)
|
||||
|
||||
bindPath1 := RandomTmpDirPath("test1", testEnv.DaemonInfo.OSType)
|
||||
bindPath2 := RandomTmpDirPath("test2", testEnv.DaemonInfo.OSType)
|
||||
|
||||
config = map[string]interface{}{
|
||||
"Binds": []string{bindPath1 + ":/tmp", bindPath2 + ":/tmp"},
|
||||
}
|
||||
res, body, err := request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/"+name+"/start"), request.JSONBody(config))
|
||||
assert.NilError(c, err)
|
||||
|
||||
buf, err := request.ReadBody(body)
|
||||
assert.NilError(c, err)
|
||||
assert.Equal(c, res.StatusCode, http.StatusBadRequest)
|
||||
assert.Assert(c, strings.Contains(string(buf), "Duplicate mount point"), "Expected failure due to duplicate bind mounts to same path, instead got: %q with error: %v", string(buf), err)
|
||||
}
|
||||
|
||||
func (s *DockerAPISuite) TestDeprecatedContainerAPIStartVolumesFrom(c *testing.T) {
|
||||
// TODO Windows to Windows CI - Port this
|
||||
testRequires(c, DaemonIsLinux)
|
||||
volName := "voltst"
|
||||
volPath := "/tmp"
|
||||
|
||||
cli.DockerCmd(c, "run", "--name", volName, "-v", volPath, "busybox")
|
||||
|
||||
name := "TestContainerAPIStartVolumesFrom"
|
||||
config := map[string]interface{}{
|
||||
"Image": "busybox",
|
||||
"Volumes": map[string]struct{}{volPath: {}},
|
||||
}
|
||||
|
||||
res, _, err := request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/create?name="+name), request.JSONBody(config))
|
||||
assert.NilError(c, err)
|
||||
assert.Equal(c, res.StatusCode, http.StatusCreated)
|
||||
|
||||
config = map[string]interface{}{
|
||||
"VolumesFrom": []string{volName},
|
||||
}
|
||||
res, _, err = request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/"+name+"/start"), request.JSONBody(config))
|
||||
assert.NilError(c, err)
|
||||
assert.Equal(c, res.StatusCode, http.StatusNoContent)
|
||||
|
||||
pth, err := inspectMountSourceField(name, volPath)
|
||||
assert.NilError(c, err)
|
||||
pth2, err := inspectMountSourceField(volName, volPath)
|
||||
assert.NilError(c, err)
|
||||
assert.Equal(c, pth, pth2, "expected volume host path to be %s, got %s", pth, pth2)
|
||||
}
|
||||
|
||||
// #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
|
||||
func (s *DockerAPISuite) TestDeprecatedPostContainerBindNormalVolume(c *testing.T) {
|
||||
// TODO Windows to Windows CI - Port this
|
||||
testRequires(c, DaemonIsLinux)
|
||||
cli.DockerCmd(c, "create", "-v", "/foo", "--name=one", "busybox")
|
||||
|
||||
fooDir, err := inspectMountSourceField("one", "/foo")
|
||||
assert.NilError(c, err)
|
||||
|
||||
cli.DockerCmd(c, "create", "-v", "/foo", "--name=two", "busybox")
|
||||
|
||||
bindSpec := map[string][]string{"Binds": {fooDir + ":/foo"}}
|
||||
res, _, err := request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/two/start"), request.JSONBody(bindSpec))
|
||||
assert.NilError(c, err)
|
||||
assert.Equal(c, res.StatusCode, http.StatusNoContent)
|
||||
|
||||
fooDir2, err := inspectMountSourceField("two", "/foo")
|
||||
assert.NilError(c, err)
|
||||
assert.Equal(c, fooDir2, fooDir, "expected volume path to be %s, got: %s", fooDir, fooDir2)
|
||||
}
|
||||
|
||||
func (s *DockerAPISuite) TestDeprecatedStartWithTooLowMemoryLimit(c *testing.T) {
|
||||
// TODO Windows: Port once memory is supported
|
||||
testRequires(c, DaemonIsLinux)
|
||||
containerID := cli.DockerCmd(c, "create", "busybox").Stdout()
|
||||
containerID = strings.TrimSpace(containerID)
|
||||
|
||||
const config = `{
|
||||
"CpuShares": 100,
|
||||
"Memory": 524287
|
||||
}`
|
||||
|
||||
res, body, err := request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/"+containerID+"/start"), request.RawString(config), request.JSON)
|
||||
assert.NilError(c, err)
|
||||
b, err := request.ReadBody(body)
|
||||
assert.NilError(c, err)
|
||||
assert.Equal(c, res.StatusCode, http.StatusBadRequest)
|
||||
assert.Assert(c, is.Contains(string(b), "Minimum memory limit allowed is 6MB"))
|
||||
}
|
||||
|
||||
// #14640
|
||||
func (s *DockerAPISuite) TestDeprecatedPostContainersStartWithoutLinksInHostConfig(c *testing.T) {
|
||||
// TODO Windows: Windows doesn't support supplying a hostconfig on start.
|
||||
// An alternate test could be written to validate the negative testing aspect of this
|
||||
testRequires(c, DaemonIsLinux)
|
||||
name := "test-host-config-links"
|
||||
cli.DockerCmd(c, append([]string{"create", "--name", name, "busybox"}, sleepCommandForDaemonPlatform()...)...)
|
||||
|
||||
hc := inspectFieldJSON(c, name, "HostConfig")
|
||||
config := `{"HostConfig":` + hc + `}`
|
||||
|
||||
res, b, err := request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/"+name+"/start"), request.RawString(config), request.JSON)
|
||||
assert.NilError(c, err)
|
||||
assert.Equal(c, res.StatusCode, http.StatusNoContent)
|
||||
b.Close()
|
||||
}
|
||||
|
||||
// #14640
|
||||
func (s *DockerAPISuite) TestDeprecatedPostContainersStartWithLinksInHostConfig(c *testing.T) {
|
||||
// TODO Windows: Windows doesn't support supplying a hostconfig on start.
|
||||
// An alternate test could be written to validate the negative testing aspect of this
|
||||
testRequires(c, DaemonIsLinux)
|
||||
name := "test-host-config-links"
|
||||
cli.DockerCmd(c, "run", "--name", "foo", "-d", "busybox", "top")
|
||||
cli.DockerCmd(c, "create", "--name", name, "--link", "foo:bar", "busybox", "top")
|
||||
|
||||
hc := inspectFieldJSON(c, name, "HostConfig")
|
||||
config := `{"HostConfig":` + hc + `}`
|
||||
|
||||
res, b, err := request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/"+name+"/start"), request.RawString(config), request.JSON)
|
||||
assert.NilError(c, err)
|
||||
assert.Equal(c, res.StatusCode, http.StatusNoContent)
|
||||
b.Close()
|
||||
}
|
||||
|
||||
// #14640
|
||||
func (s *DockerAPISuite) TestDeprecatedPostContainersStartWithLinksInHostConfigIdLinked(c *testing.T) {
|
||||
// Windows does not support links
|
||||
testRequires(c, DaemonIsLinux)
|
||||
const name = "test-host-config-links"
|
||||
containerID := cli.DockerCmd(c, "run", "--name", "link0", "-d", "busybox", "top").Combined()
|
||||
containerID = strings.TrimSpace(containerID)
|
||||
defer cli.DockerCmd(c, "stop", "link0")
|
||||
cli.DockerCmd(c, "create", "--name", name, "--link", containerID, "busybox", "top")
|
||||
defer cli.DockerCmd(c, "stop", name)
|
||||
|
||||
hc := inspectFieldJSON(c, name, "HostConfig")
|
||||
config := `{"HostConfig":` + hc + `}`
|
||||
|
||||
res, b, err := request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/"+name+"/start"), request.RawString(config), request.JSON)
|
||||
assert.NilError(c, err)
|
||||
assert.Equal(c, res.StatusCode, http.StatusNoContent)
|
||||
b.Close()
|
||||
}
|
||||
|
||||
func (s *DockerAPISuite) TestDeprecatedStartWithNilDNS(c *testing.T) {
|
||||
// TODO Windows: Add once DNS is supported
|
||||
testRequires(c, DaemonIsLinux)
|
||||
containerID := cli.DockerCmd(c, "create", "busybox").Stdout()
|
||||
containerID = strings.TrimSpace(containerID)
|
||||
|
||||
const config = `{"HostConfig": {"Dns": null}}`
|
||||
|
||||
res, b, err := request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/"+containerID+"/start"), request.RawString(config), request.JSON)
|
||||
assert.NilError(c, err)
|
||||
assert.Equal(c, res.StatusCode, http.StatusNoContent)
|
||||
b.Close()
|
||||
|
||||
dns := inspectFieldJSON(c, containerID, "HostConfig.Dns")
|
||||
assert.Equal(c, dns, "[]")
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
//go:build !windows
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/integration-cli/cli"
|
||||
"github.com/docker/docker/testutil"
|
||||
"github.com/docker/docker/testutil/request"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
// #19100 This is a deprecated feature test, it should be removed in Docker 1.12
|
||||
func (s *DockerNetworkSuite) TestDeprecatedDockerNetworkStartAPIWithHostconfig(c *testing.T) {
|
||||
const netName = "test"
|
||||
const conName = "foo"
|
||||
cli.DockerCmd(c, "network", "create", netName)
|
||||
cli.DockerCmd(c, "create", "--name", conName, "busybox", "top")
|
||||
|
||||
config := map[string]interface{}{
|
||||
"HostConfig": map[string]interface{}{
|
||||
"NetworkMode": netName,
|
||||
},
|
||||
}
|
||||
_, _, err := request.Post(testutil.GetContext(c), formatV123StartAPIURL("/containers/"+conName+"/start"), request.JSONBody(config))
|
||||
assert.NilError(c, err)
|
||||
cli.WaitRun(c, conName)
|
||||
networks := inspectField(c, conName, "NetworkSettings.Networks")
|
||||
assert.Assert(c, strings.Contains(networks, netName), "Should contain '%s' network", netName)
|
||||
assert.Assert(c, !strings.Contains(networks, "bridge"), "Should not contain 'bridge' network")
|
||||
}
|
|
@ -2,7 +2,6 @@ package container // import "github.com/docker/docker/integration/container"
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/testutil"
|
||||
|
@ -25,14 +24,6 @@ func TestContainerInvalidJSON(t *testing.T) {
|
|||
"/exec/foobar/start",
|
||||
}
|
||||
|
||||
// windows doesnt support API < v1.24
|
||||
if runtime.GOOS != "windows" {
|
||||
endpoints = append(
|
||||
endpoints,
|
||||
"/v1.23/containers/foobar/start", // accepts a body on API < v1.24
|
||||
)
|
||||
}
|
||||
|
||||
for _, ep := range endpoints {
|
||||
ep := ep
|
||||
t.Run(ep[1:], func(t *testing.T) {
|
||||
|
|
|
@ -27,11 +27,6 @@ func (r ContainerDecoder) DecodeConfig(src io.Reader) (*container.Config, *conta
|
|||
return decodeContainerConfig(src, si)
|
||||
}
|
||||
|
||||
// DecodeHostConfig makes ContainerDecoder to implement httputils.ContainerDecoder
|
||||
func (r ContainerDecoder) DecodeHostConfig(src io.Reader) (*container.HostConfig, error) {
|
||||
return decodeHostConfig(src)
|
||||
}
|
||||
|
||||
// decodeContainerConfig decodes a json encoded config into a ContainerConfigWrapper
|
||||
// struct and returns both a Config and a HostConfig struct, and performs some
|
||||
// validation. Certain parameters need daemon-side validation that cannot be done
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
{
|
||||
"Binds": ["/tmp:/tmp"],
|
||||
"ContainerIDFile": "",
|
||||
"LxcConf": [],
|
||||
"Privileged": false,
|
||||
"PortBindings": {
|
||||
"80/tcp": [
|
||||
{
|
||||
"HostIp": "0.0.0.0",
|
||||
"HostPort": "49153"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Links": ["/name:alias"],
|
||||
"PublishAllPorts": false,
|
||||
"CapAdd": ["NET_ADMIN"],
|
||||
"CapDrop": ["MKNOD"]
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
{
|
||||
"Binds": ["/tmp:/tmp"],
|
||||
"Links": ["redis3:redis"],
|
||||
"LxcConf": {"lxc.utsname":"docker"},
|
||||
"Memory": 0,
|
||||
"MemorySwap": 0,
|
||||
"CpuShares": 512,
|
||||
"CpuPeriod": 100000,
|
||||
"CpusetCpus": "0,1",
|
||||
"CpusetMems": "0,1",
|
||||
"BlkioWeight": 300,
|
||||
"OomKillDisable": false,
|
||||
"PortBindings": { "22/tcp": [{ "HostPort": "11022" }] },
|
||||
"PublishAllPorts": false,
|
||||
"Privileged": false,
|
||||
"ReadonlyRootfs": false,
|
||||
"Dns": ["8.8.8.8"],
|
||||
"DnsSearch": [""],
|
||||
"ExtraHosts": null,
|
||||
"VolumesFrom": ["parent", "other:ro"],
|
||||
"CapAdd": ["NET_ADMIN"],
|
||||
"CapDrop": ["MKNOD"],
|
||||
"RestartPolicy": { "Name": "", "MaximumRetryCount": 0 },
|
||||
"NetworkMode": "bridge",
|
||||
"Devices": [],
|
||||
"Ulimits": [{}],
|
||||
"LogConfig": { "Type": "json-file", "Config": {} },
|
||||
"SecurityOpt": [""],
|
||||
"CgroupParent": ""
|
||||
}
|
|
@ -1,23 +1,12 @@
|
|||
package runconfig // import "github.com/docker/docker/runconfig"
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/network"
|
||||
)
|
||||
|
||||
// DecodeHostConfig creates a HostConfig based on the specified Reader.
|
||||
// It assumes the content of the reader will be JSON, and decodes it.
|
||||
func decodeHostConfig(src io.Reader) (*container.HostConfig, error) {
|
||||
var w ContainerConfigWrapper
|
||||
if err := loadJSON(src, &w); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return w.getHostConfig(), nil
|
||||
}
|
||||
|
||||
// SetDefaultNetModeIfBlank changes the NetworkMode in a HostConfig structure
|
||||
// to default if it is not populated. This ensures backwards compatibility after
|
||||
// the validation of the network mode was moved from the docker CLI to the
|
||||
|
|
|
@ -3,51 +3,12 @@
|
|||
package runconfig // import "github.com/docker/docker/runconfig"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/pkg/sysinfo"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
func TestDecodeHostConfig(t *testing.T) {
|
||||
fixtures := []struct {
|
||||
file string
|
||||
}{
|
||||
{"fixtures/unix/container_hostconfig_1_14.json"},
|
||||
{"fixtures/unix/container_hostconfig_1_19.json"},
|
||||
}
|
||||
|
||||
for _, f := range fixtures {
|
||||
b, err := os.ReadFile(f.file)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
c, err := decodeHostConfig(bytes.NewReader(b))
|
||||
if err != nil {
|
||||
t.Fatal(fmt.Errorf("Error parsing %s: %v", f, err))
|
||||
}
|
||||
|
||||
assert.Check(t, !c.Privileged)
|
||||
|
||||
if l := len(c.Binds); l != 1 {
|
||||
t.Fatalf("Expected 1 bind, found %d\n", l)
|
||||
}
|
||||
|
||||
if len(c.CapAdd) != 1 && c.CapAdd[0] != "NET_ADMIN" {
|
||||
t.Fatalf("Expected CapAdd NET_ADMIN, got %v", c.CapAdd)
|
||||
}
|
||||
|
||||
if len(c.CapDrop) != 1 && c.CapDrop[0] != "NET_ADMIN" {
|
||||
t.Fatalf("Expected CapDrop NET_ADMIN, got %v", c.CapDrop)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateResources(t *testing.T) {
|
||||
type resourceTest struct {
|
||||
ConfigCPURealtimePeriod int64
|
||||
|
|
Loading…
Reference in a new issue