Sfoglia il codice sorgente

Merge pull request #46720 from akerouanton/container-create-init-structs

api: ContainerCreate: clean up BC conditions
Sebastiaan van Stijn 1 anno fa
parent
commit
460e1b3600

+ 55 - 38
api/server/router/container/container_routes.go

@@ -19,10 +19,12 @@ import (
 	"github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/api/types/mount"
 	"github.com/docker/docker/api/types/mount"
+	"github.com/docker/docker/api/types/network"
 	"github.com/docker/docker/api/types/versions"
 	"github.com/docker/docker/api/types/versions"
 	containerpkg "github.com/docker/docker/container"
 	containerpkg "github.com/docker/docker/container"
 	"github.com/docker/docker/errdefs"
 	"github.com/docker/docker/errdefs"
 	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/docker/pkg/ioutils"
+	"github.com/docker/docker/runconfig"
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/pkg/errors"
 	"github.com/pkg/errors"
 	"golang.org/x/net/websocket"
 	"golang.org/x/net/websocket"
@@ -492,21 +494,39 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
 		}
 		}
 		return err
 		return err
 	}
 	}
+
+	if config == nil {
+		return errdefs.InvalidParameter(runconfig.ErrEmptyConfig)
+	}
+	if hostConfig == nil {
+		hostConfig = &container.HostConfig{}
+	}
+	if hostConfig.NetworkMode == "" {
+		hostConfig.NetworkMode = "default"
+	}
+	if networkingConfig == nil {
+		networkingConfig = &network.NetworkingConfig{}
+	}
+	if networkingConfig.EndpointsConfig == nil {
+		networkingConfig.EndpointsConfig = make(map[string]*network.EndpointSettings)
+	}
+
 	version := httputils.VersionFromContext(ctx)
 	version := httputils.VersionFromContext(ctx)
 	adjustCPUShares := versions.LessThan(version, "1.19")
 	adjustCPUShares := versions.LessThan(version, "1.19")
 
 
 	// When using API 1.24 and under, the client is responsible for removing the container
 	// When using API 1.24 and under, the client is responsible for removing the container
-	if hostConfig != nil && versions.LessThan(version, "1.25") {
+	if versions.LessThan(version, "1.25") {
 		hostConfig.AutoRemove = false
 		hostConfig.AutoRemove = false
 	}
 	}
 
 
-	if hostConfig != nil && versions.LessThan(version, "1.40") {
+	if versions.LessThan(version, "1.40") {
 		// Ignore BindOptions.NonRecursive because it was added in API 1.40.
 		// Ignore BindOptions.NonRecursive because it was added in API 1.40.
 		for _, m := range hostConfig.Mounts {
 		for _, m := range hostConfig.Mounts {
 			if bo := m.BindOptions; bo != nil {
 			if bo := m.BindOptions; bo != nil {
 				bo.NonRecursive = false
 				bo.NonRecursive = false
 			}
 			}
 		}
 		}
+
 		// Ignore KernelMemoryTCP because it was added in API 1.40.
 		// Ignore KernelMemoryTCP because it was added in API 1.40.
 		hostConfig.KernelMemoryTCP = 0
 		hostConfig.KernelMemoryTCP = 0
 
 
@@ -515,14 +535,26 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
 			hostConfig.IpcMode = container.IPCModeShareable
 			hostConfig.IpcMode = container.IPCModeShareable
 		}
 		}
 	}
 	}
-	if hostConfig != nil && versions.LessThan(version, "1.41") && !s.cgroup2 {
+
+	if versions.LessThan(version, "1.41") {
 		// Older clients expect the default to be "host" on cgroup v1 hosts
 		// Older clients expect the default to be "host" on cgroup v1 hosts
-		if hostConfig.CgroupnsMode.IsEmpty() {
+		if !s.cgroup2 && hostConfig.CgroupnsMode.IsEmpty() {
 			hostConfig.CgroupnsMode = container.CgroupnsModeHost
 			hostConfig.CgroupnsMode = container.CgroupnsModeHost
 		}
 		}
 	}
 	}
 
 
-	if hostConfig != nil && versions.LessThan(version, "1.42") {
+	var platform *ocispec.Platform
+	if versions.GreaterThanOrEqualTo(version, "1.41") {
+		if v := r.Form.Get("platform"); v != "" {
+			p, err := platforms.Parse(v)
+			if err != nil {
+				return errdefs.InvalidParameter(err)
+			}
+			platform = &p
+		}
+	}
+
+	if versions.LessThan(version, "1.42") {
 		for _, m := range hostConfig.Mounts {
 		for _, m := range hostConfig.Mounts {
 			// Ignore BindOptions.CreateMountpoint because it was added in API 1.42.
 			// Ignore BindOptions.CreateMountpoint because it was added in API 1.42.
 			if bo := m.BindOptions; bo != nil {
 			if bo := m.BindOptions; bo != nil {
@@ -542,16 +574,14 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
 				bo.CreateMountpoint = false
 				bo.CreateMountpoint = false
 			}
 			}
 		}
 		}
-	}
 
 
-	if config != nil && versions.LessThan(version, "1.44") {
-		if config.Healthcheck != nil {
-			// StartInterval was added in API 1.44
-			config.Healthcheck.StartInterval = 0
+		if runtime.GOOS == "linux" {
+			// ConsoleSize is not respected by Linux daemon before API 1.42
+			hostConfig.ConsoleSize = [2]uint{0, 0}
 		}
 		}
 	}
 	}
 
 
-	if hostConfig != nil && versions.GreaterThanOrEqualTo(version, "1.42") {
+	if versions.GreaterThanOrEqualTo(version, "1.42") {
 		// Ignore KernelMemory removed in API 1.42.
 		// Ignore KernelMemory removed in API 1.42.
 		hostConfig.KernelMemory = 0
 		hostConfig.KernelMemory = 0
 		for _, m := range hostConfig.Mounts {
 		for _, m := range hostConfig.Mounts {
@@ -567,36 +597,17 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
 		}
 		}
 	}
 	}
 
 
-	if hostConfig != nil && runtime.GOOS == "linux" && versions.LessThan(version, "1.42") {
-		// ConsoleSize is not respected by Linux daemon before API 1.42
-		hostConfig.ConsoleSize = [2]uint{0, 0}
-	}
-
-	if hostConfig != nil && versions.LessThan(version, "1.43") {
+	if versions.LessThan(version, "1.43") {
 		// Ignore Annotations because it was added in API v1.43.
 		// Ignore Annotations because it was added in API v1.43.
 		hostConfig.Annotations = nil
 		hostConfig.Annotations = nil
 	}
 	}
 
 
-	var platform *ocispec.Platform
-	if versions.GreaterThanOrEqualTo(version, "1.41") {
-		if v := r.Form.Get("platform"); v != "" {
-			p, err := platforms.Parse(v)
-			if err != nil {
-				return errdefs.InvalidParameter(err)
-			}
-			platform = &p
+	if versions.LessThan(version, "1.44") {
+		if config.Healthcheck != nil {
+			// StartInterval was added in API 1.44
+			config.Healthcheck.StartInterval = 0
 		}
 		}
-	}
-
-	if hostConfig != nil && hostConfig.PidsLimit != nil && *hostConfig.PidsLimit <= 0 {
-		// Don't set a limit if either no limit was specified, or "unlimited" was
-		// explicitly set.
-		// Both `0` and `-1` are accepted as "unlimited", and historically any
-		// negative value was accepted, so treat those as "unlimited" as well.
-		hostConfig.PidsLimit = nil
-	}
 
 
-	if hostConfig != nil && versions.LessThan(version, "1.44") {
 		for _, m := range hostConfig.Mounts {
 		for _, m := range hostConfig.Mounts {
 			if m.BindOptions != nil {
 			if m.BindOptions != nil {
 				// Ignore ReadOnlyNonRecursive because it was added in API 1.44.
 				// Ignore ReadOnlyNonRecursive because it was added in API 1.44.
@@ -606,11 +617,9 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
 				}
 				}
 			}
 			}
 		}
 		}
-	}
 
 
-	if versions.LessThan(version, "1.44") {
 		// Creating a container connected to several networks is not supported until v1.44.
 		// Creating a container connected to several networks is not supported until v1.44.
-		if networkingConfig != nil && len(networkingConfig.EndpointsConfig) > 1 {
+		if len(networkingConfig.EndpointsConfig) > 1 {
 			l := make([]string, 0, len(networkingConfig.EndpointsConfig))
 			l := make([]string, 0, len(networkingConfig.EndpointsConfig))
 			for k := range networkingConfig.EndpointsConfig {
 			for k := range networkingConfig.EndpointsConfig {
 				l = append(l, k)
 				l = append(l, k)
@@ -619,6 +628,14 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
 		}
 		}
 	}
 	}
 
 
+	if hostConfig.PidsLimit != nil && *hostConfig.PidsLimit <= 0 {
+		// Don't set a limit if either no limit was specified, or "unlimited" was
+		// explicitly set.
+		// Both `0` and `-1` are accepted as "unlimited", and historically any
+		// negative value was accepted, so treat those as "unlimited" as well.
+		hostConfig.PidsLimit = nil
+	}
+
 	ccr, err := s.backend.ContainerCreate(ctx, types.ContainerCreateConfig{
 	ccr, err := s.backend.ContainerCreate(ctx, types.ContainerCreateConfig{
 		Name:             name,
 		Name:             name,
 		Config:           config,
 		Config:           config,

+ 1 - 2
daemon/create.go

@@ -2,7 +2,6 @@ package daemon // import "github.com/docker/docker/daemon"
 
 
 import (
 import (
 	"context"
 	"context"
-	"errors"
 	"fmt"
 	"fmt"
 	"runtime"
 	"runtime"
 	"strings"
 	"strings"
@@ -61,7 +60,7 @@ func (daemon *Daemon) ContainerCreateIgnoreImagesArgsEscaped(ctx context.Context
 func (daemon *Daemon) containerCreate(ctx context.Context, daemonCfg *configStore, opts createOpts) (containertypes.CreateResponse, error) {
 func (daemon *Daemon) containerCreate(ctx context.Context, daemonCfg *configStore, opts createOpts) (containertypes.CreateResponse, error) {
 	start := time.Now()
 	start := time.Now()
 	if opts.params.Config == nil {
 	if opts.params.Config == nil {
-		return containertypes.CreateResponse{}, errdefs.InvalidParameter(errors.New("Config cannot be empty in order to create a container"))
+		return containertypes.CreateResponse{}, errdefs.InvalidParameter(runconfig.ErrEmptyConfig)
 	}
 	}
 
 
 	// Normalize some defaults. Doing this "ad-hoc" here for now, as there's
 	// Normalize some defaults. Doing this "ad-hoc" here for now, as there's

+ 3 - 2
integration-cli/docker_api_test.go

@@ -12,6 +12,7 @@ import (
 
 
 	"github.com/docker/docker/api"
 	"github.com/docker/docker/api"
 	"github.com/docker/docker/api/types/versions"
 	"github.com/docker/docker/api/types/versions"
+	"github.com/docker/docker/runconfig"
 	"github.com/docker/docker/testutil"
 	"github.com/docker/docker/testutil"
 	"github.com/docker/docker/testutil/request"
 	"github.com/docker/docker/testutil/request"
 	"gotest.tools/v3/assert"
 	"gotest.tools/v3/assert"
@@ -82,7 +83,7 @@ func (s *DockerAPISuite) TestAPIErrorJSON(c *testing.T) {
 	assert.Assert(c, strings.Contains(httpResp.Header.Get("Content-Type"), "application/json"))
 	assert.Assert(c, strings.Contains(httpResp.Header.Get("Content-Type"), "application/json"))
 	b, err := request.ReadBody(body)
 	b, err := request.ReadBody(body)
 	assert.NilError(c, err)
 	assert.NilError(c, err)
-	assert.Equal(c, getErrorMessage(c, b), "Config cannot be empty in order to create a container")
+	assert.Equal(c, getErrorMessage(c, b), runconfig.ErrEmptyConfig.Error())
 }
 }
 
 
 func (s *DockerAPISuite) TestAPIErrorPlainText(c *testing.T) {
 func (s *DockerAPISuite) TestAPIErrorPlainText(c *testing.T) {
@@ -99,7 +100,7 @@ func (s *DockerAPISuite) TestAPIErrorPlainText(c *testing.T) {
 	assert.Assert(c, strings.Contains(httpResp.Header.Get("Content-Type"), "text/plain"))
 	assert.Assert(c, strings.Contains(httpResp.Header.Get("Content-Type"), "text/plain"))
 	b, err := request.ReadBody(body)
 	b, err := request.ReadBody(body)
 	assert.NilError(c, err)
 	assert.NilError(c, err)
-	assert.Equal(c, strings.TrimSpace(string(b)), "Config cannot be empty in order to create a container")
+	assert.Equal(c, strings.TrimSpace(string(b)), runconfig.ErrEmptyConfig.Error())
 }
 }
 
 
 func (s *DockerAPISuite) TestAPIErrorNotFoundJSON(c *testing.T) {
 func (s *DockerAPISuite) TestAPIErrorNotFoundJSON(c *testing.T) {

+ 2 - 0
runconfig/errors.go

@@ -31,6 +31,8 @@ const (
 	ErrUnsupportedNetworkAndAlias validationError = "network-scoped alias is supported only for containers in user defined networks"
 	ErrUnsupportedNetworkAndAlias validationError = "network-scoped alias is supported only for containers in user defined networks"
 	// ErrConflictUTSHostname conflict between the hostname and the UTS mode
 	// ErrConflictUTSHostname conflict between the hostname and the UTS mode
 	ErrConflictUTSHostname validationError = "conflicting options: hostname and the UTS mode"
 	ErrConflictUTSHostname validationError = "conflicting options: hostname and the UTS mode"
+	// ErrEmptyConfig when container config is nil
+	ErrEmptyConfig validationError = "config cannot be empty in order to create a container"
 )
 )
 
 
 type validationError string
 type validationError string