Browse Source

Reject multiple networks on container creation

Signed-off-by: Alessandro Boch <aboch@docker.com>
Alessandro Boch 9 years ago
parent
commit
cfa515fd9d
4 changed files with 51 additions and 0 deletions
  1. 5 0
      daemon/create.go
  2. 13 0
      daemon/daemon.go
  3. 9 0
      errors/daemon.go
  4. 24 0
      integration-cli/docker_api_containers_test.go

+ 5 - 0
daemon/create.go

@@ -26,6 +26,11 @@ func (daemon *Daemon) ContainerCreate(params types.ContainerCreateConfig) (types
 		return types.ContainerCreateResponse{Warnings: warnings}, err
 	}
 
+	err = daemon.verifyNetworkingConfig(params.NetworkingConfig)
+	if err != nil {
+		return types.ContainerCreateResponse{}, err
+	}
+
 	if params.HostConfig == nil {
 		params.HostConfig = &containertypes.HostConfig{}
 	}

+ 13 - 0
daemon/daemon.go

@@ -31,6 +31,7 @@ import (
 	containertypes "github.com/docker/engine-api/types/container"
 	eventtypes "github.com/docker/engine-api/types/events"
 	"github.com/docker/engine-api/types/filters"
+	networktypes "github.com/docker/engine-api/types/network"
 	registrytypes "github.com/docker/engine-api/types/registry"
 	"github.com/docker/engine-api/types/strslice"
 	// register graph drivers
@@ -1416,6 +1417,18 @@ func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostCon
 	return verifyPlatformContainerSettings(daemon, hostConfig, config)
 }
 
+// Checks if the client set configurations for more than one network while creating a container
+func (daemon *Daemon) verifyNetworkingConfig(nwConfig *networktypes.NetworkingConfig) error {
+	if nwConfig == nil || len(nwConfig.EndpointsConfig) <= 1 {
+		return nil
+	}
+	l := make([]string, 0, len(nwConfig.EndpointsConfig))
+	for k := range nwConfig.EndpointsConfig {
+		l = append(l, k)
+	}
+	return derr.ErrorCodeMultipleNetworkConnect.WithArgs(fmt.Sprintf("%v", l))
+}
+
 func configureVolumes(config *Config, rootUID, rootGID int) (*store.VolumeStore, error) {
 	volumesDriver, err := local.New(config.Root, rootUID, rootGID)
 	if err != nil {

+ 9 - 0
errors/daemon.go

@@ -966,4 +966,13 @@ var (
 		Description:    "Engine's predefined networks cannot be deleted",
 		HTTPStatusCode: http.StatusForbidden,
 	})
+
+	// ErrorCodeMultipleNetworkConnect is generated when more than one network is passed
+	// when creating a container
+	ErrorCodeMultipleNetworkConnect = errcode.Register(errGroup, errcode.ErrorDescriptor{
+		Value:          "CANNOT_CONNECT_TO_MULTIPLE_NETWORKS",
+		Message:        "Container cannot be connected to %s",
+		Description:    "A container can only be connected to one network at the time",
+		HTTPStatusCode: http.StatusBadRequest,
+	})
 )

+ 24 - 0
integration-cli/docker_api_containers_test.go

@@ -20,6 +20,7 @@ import (
 	"github.com/docker/docker/pkg/stringid"
 	"github.com/docker/engine-api/types"
 	containertypes "github.com/docker/engine-api/types/container"
+	networktypes "github.com/docker/engine-api/types/network"
 	"github.com/go-check/check"
 )
 
@@ -604,6 +605,29 @@ func (s *DockerSuite) TestContainerApiCreateEmptyConfig(c *check.C) {
 	c.Assert(string(b), checker.Equals, expected)
 }
 
+func (s *DockerSuite) TestContainerApiCreateMultipleNetworksConfig(c *check.C) {
+	// Container creation must fail if client specified configurations for more than one network
+	config := map[string]interface{}{
+		"Image": "busybox",
+		"NetworkingConfig": networktypes.NetworkingConfig{
+			EndpointsConfig: map[string]*networktypes.EndpointSettings{
+				"net1": {},
+				"net2": {},
+				"net3": {},
+			},
+		},
+	}
+
+	status, b, err := sockRequest("POST", "/containers/create", config)
+	c.Assert(err, checker.IsNil)
+	c.Assert(status, checker.Equals, http.StatusBadRequest)
+	// network name order in error message is not deterministic
+	c.Assert(string(b), checker.Contains, "Container cannot be connected to [")
+	c.Assert(string(b), checker.Contains, "net1")
+	c.Assert(string(b), checker.Contains, "net2")
+	c.Assert(string(b), checker.Contains, "net3")
+}
+
 func (s *DockerSuite) TestContainerApiCreateWithHostName(c *check.C) {
 	testRequires(c, DaemonIsLinux)
 	hostName := "test-host"