Browse code

Reject multiple networks on container creation

Signed-off-by: Alessandro Boch <aboch@docker.com>

Alessandro Boch authored on 2016/01/22 07:24:35
Showing 4 changed files
... ...
@@ -26,6 +26,11 @@ func (daemon *Daemon) ContainerCreate(params types.ContainerCreateConfig) (types
26 26
 		return types.ContainerCreateResponse{Warnings: warnings}, err
27 27
 	}
28 28
 
29
+	err = daemon.verifyNetworkingConfig(params.NetworkingConfig)
30
+	if err != nil {
31
+		return types.ContainerCreateResponse{}, err
32
+	}
33
+
29 34
 	if params.HostConfig == nil {
30 35
 		params.HostConfig = &containertypes.HostConfig{}
31 36
 	}
... ...
@@ -31,6 +31,7 @@ import (
31 31
 	containertypes "github.com/docker/engine-api/types/container"
32 32
 	eventtypes "github.com/docker/engine-api/types/events"
33 33
 	"github.com/docker/engine-api/types/filters"
34
+	networktypes "github.com/docker/engine-api/types/network"
34 35
 	registrytypes "github.com/docker/engine-api/types/registry"
35 36
 	"github.com/docker/engine-api/types/strslice"
36 37
 	// register graph drivers
... ...
@@ -1416,6 +1417,18 @@ func (daemon *Daemon) verifyContainerSettings(hostConfig *containertypes.HostCon
1416 1416
 	return verifyPlatformContainerSettings(daemon, hostConfig, config)
1417 1417
 }
1418 1418
 
1419
+// Checks if the client set configurations for more than one network while creating a container
1420
+func (daemon *Daemon) verifyNetworkingConfig(nwConfig *networktypes.NetworkingConfig) error {
1421
+	if nwConfig == nil || len(nwConfig.EndpointsConfig) <= 1 {
1422
+		return nil
1423
+	}
1424
+	l := make([]string, 0, len(nwConfig.EndpointsConfig))
1425
+	for k := range nwConfig.EndpointsConfig {
1426
+		l = append(l, k)
1427
+	}
1428
+	return derr.ErrorCodeMultipleNetworkConnect.WithArgs(fmt.Sprintf("%v", l))
1429
+}
1430
+
1419 1431
 func configureVolumes(config *Config, rootUID, rootGID int) (*store.VolumeStore, error) {
1420 1432
 	volumesDriver, err := local.New(config.Root, rootUID, rootGID)
1421 1433
 	if err != nil {
... ...
@@ -966,4 +966,13 @@ var (
966 966
 		Description:    "Engine's predefined networks cannot be deleted",
967 967
 		HTTPStatusCode: http.StatusForbidden,
968 968
 	})
969
+
970
+	// ErrorCodeMultipleNetworkConnect is generated when more than one network is passed
971
+	// when creating a container
972
+	ErrorCodeMultipleNetworkConnect = errcode.Register(errGroup, errcode.ErrorDescriptor{
973
+		Value:          "CANNOT_CONNECT_TO_MULTIPLE_NETWORKS",
974
+		Message:        "Container cannot be connected to %s",
975
+		Description:    "A container can only be connected to one network at the time",
976
+		HTTPStatusCode: http.StatusBadRequest,
977
+	})
969 978
 )
... ...
@@ -20,6 +20,7 @@ import (
20 20
 	"github.com/docker/docker/pkg/stringid"
21 21
 	"github.com/docker/engine-api/types"
22 22
 	containertypes "github.com/docker/engine-api/types/container"
23
+	networktypes "github.com/docker/engine-api/types/network"
23 24
 	"github.com/go-check/check"
24 25
 )
25 26
 
... ...
@@ -604,6 +605,29 @@ func (s *DockerSuite) TestContainerApiCreateEmptyConfig(c *check.C) {
604 604
 	c.Assert(string(b), checker.Equals, expected)
605 605
 }
606 606
 
607
+func (s *DockerSuite) TestContainerApiCreateMultipleNetworksConfig(c *check.C) {
608
+	// Container creation must fail if client specified configurations for more than one network
609
+	config := map[string]interface{}{
610
+		"Image": "busybox",
611
+		"NetworkingConfig": networktypes.NetworkingConfig{
612
+			EndpointsConfig: map[string]*networktypes.EndpointSettings{
613
+				"net1": {},
614
+				"net2": {},
615
+				"net3": {},
616
+			},
617
+		},
618
+	}
619
+
620
+	status, b, err := sockRequest("POST", "/containers/create", config)
621
+	c.Assert(err, checker.IsNil)
622
+	c.Assert(status, checker.Equals, http.StatusBadRequest)
623
+	// network name order in error message is not deterministic
624
+	c.Assert(string(b), checker.Contains, "Container cannot be connected to [")
625
+	c.Assert(string(b), checker.Contains, "net1")
626
+	c.Assert(string(b), checker.Contains, "net2")
627
+	c.Assert(string(b), checker.Contains, "net3")
628
+}
629
+
607 630
 func (s *DockerSuite) TestContainerApiCreateWithHostName(c *check.C) {
608 631
 	testRequires(c, DaemonIsLinux)
609 632
 	hostName := "test-host"