浏览代码

apply IPAM configuration to network and services

Signed-off-by: Nicolas De Loof <[email protected]>
Nicolas De Loof 4 年之前
父节点
当前提交
2fdc2e1dfb
共有 4 个文件被更改,包括 80 次插入5 次删除
  1. 12 0
      local/e2e/compose/fixtures/ipam/compose.yaml
  2. 23 0
      local/e2e/compose/networks_test.go
  3. 9 3
      pkg/compose/convergence.go
  4. 36 2
      pkg/compose/create.go

+ 12 - 0
local/e2e/compose/fixtures/ipam/compose.yaml

@@ -0,0 +1,12 @@
+services:
+  foo:
+    image: alpine
+    entrypoint: ["sleep", "600"]
+    networks:
+      default:
+        ipv4_address: 10.1.0.100  # <-- Fixed IP address
+networks:
+  default:
+    ipam:
+      config:
+        - subnet: 10.1.0.0/16

+ 23 - 0
local/e2e/compose/networks_test.go

@@ -94,3 +94,26 @@ func TestNetworkAliassesAndLinks(t *testing.T) {
 		_ = c.RunDockerCmd("compose", "--project-name", projectName, "down")
 	})
 }
+
+func TestIPAMConfig(t *testing.T) {
+	c := NewParallelE2eCLI(t, binDir)
+
+	const projectName = "ipam_e2e"
+
+	t.Run("ensure we do not reuse previous networks", func(t *testing.T) {
+		c.RunDockerOrExitError("network", "rm", projectName+"_default")
+	})
+
+	t.Run("up", func(t *testing.T) {
+		c.RunDockerCmd("compose", "-f", "./fixtures/ipam/compose.yaml", "--project-name", projectName, "up", "-d")
+	})
+
+	t.Run("ensure service get fixed IP assigned", func(t *testing.T) {
+		res := c.RunDockerCmd("inspect", projectName+"_foo_1", "-f", "{{ .NetworkSettings.Networks."+projectName+"_default.IPAddress }}")
+		res.Assert(t, icmd.Expected{Out: "10.1.0.100"})
+	})
+
+	t.Run("down", func(t *testing.T) {
+		_ = c.RunDockerCmd("compose", "--project-name", projectName, "down")
+	})
+}

+ 9 - 3
pkg/compose/convergence.go

@@ -370,18 +370,24 @@ func shortIDAliasExists(containerID string, aliases ...string) bool {
 
 func (s *composeService) connectContainerToNetwork(ctx context.Context, id string, netwrk string, cfg *types.ServiceNetworkConfig, links []string, aliases ...string) error {
 	var (
-		ipv4ddress  string
+		ipv4Address string
 		ipv6Address string
+		ipam        *network.EndpointIPAMConfig
 	)
 	if cfg != nil {
-		ipv4ddress = cfg.Ipv4Address
+		ipv4Address = cfg.Ipv4Address
 		ipv6Address = cfg.Ipv6Address
+		ipam = &network.EndpointIPAMConfig{
+			IPv4Address: ipv4Address,
+			IPv6Address: ipv6Address,
+		}
 	}
 	err := s.apiClient.NetworkConnect(ctx, netwrk, id, &network.EndpointSettings{
 		Aliases:           aliases,
-		IPAddress:         ipv4ddress,
+		IPAddress:         ipv4Address,
 		GlobalIPv6Address: ipv6Address,
 		Links:             links,
+		IPAMConfig:        ipam,
 	})
 	if err != nil {
 		return err

+ 36 - 2
pkg/compose/create.go

@@ -284,17 +284,34 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
 	}
 
 	var networkConfig *network.NetworkingConfig
+
 	for _, id := range service.NetworksByPriority() {
 		net := p.Networks[id]
 		config := service.Networks[id]
+		var ipam *network.EndpointIPAMConfig
+		var (
+			ipv4Address string
+			ipv6Address string
+		)
+		if config != nil {
+			ipv4Address = config.Ipv4Address
+			ipv6Address = config.Ipv6Address
+			ipam = &network.EndpointIPAMConfig{
+				IPv4Address: ipv4Address,
+				IPv6Address: ipv6Address,
+			}
+		}
 		networkConfig = &network.NetworkingConfig{
 			EndpointsConfig: map[string]*network.EndpointSettings{
 				net.Name: {
-					Aliases: getAliases(service, config),
+					Aliases:     getAliases(service, config),
+					IPAddress:   ipv4Address,
+					IPv6Gateway: ipv6Address,
+					IPAMConfig:  ipam,
 				},
 			},
 		}
-		break
+		break //nolint:staticcheck
 	}
 
 	ipcmode, err := getMode(ctx, service.Name, service.Ipc)
@@ -915,6 +932,22 @@ func (s *composeService) ensureNetwork(ctx context.Context, n types.NetworkConfi
 			if n.External.External {
 				return fmt.Errorf("network %s declared as external, but could not be found", n.Name)
 			}
+			var ipam *network.IPAM
+			if n.Ipam.Config != nil {
+				var config []network.IPAMConfig
+				for _, pool := range n.Ipam.Config {
+					config = append(config, network.IPAMConfig{
+						Subnet:     pool.Subnet,
+						IPRange:    pool.IPRange,
+						Gateway:    pool.Gateway,
+						AuxAddress: pool.AuxiliaryAddresses,
+					})
+				}
+				ipam = &network.IPAM{
+					Driver: n.Ipam.Driver,
+					Config: config,
+				}
+			}
 			createOpts := moby.NetworkCreate{
 				// TODO NameSpace Labels
 				Labels:     n.Labels,
@@ -922,6 +955,7 @@ func (s *composeService) ensureNetwork(ctx context.Context, n types.NetworkConfi
 				Options:    n.DriverOpts,
 				Internal:   n.Internal,
 				Attachable: n.Attachable,
+				IPAM:       ipam,
 			}
 
 			if n.Ipam.Driver != "" || len(n.Ipam.Config) > 0 {