Skip to content
This repository was archived by the owner on Jul 18, 2025. It is now read-only.

Commit 2fdc2e1

Browse files
committed
apply IPAM configuration to network and services
Signed-off-by: Nicolas De Loof <[email protected]>
1 parent 7f18b47 commit 2fdc2e1

File tree

4 files changed

+80
-5
lines changed

4 files changed

+80
-5
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
services:
2+
foo:
3+
image: alpine
4+
entrypoint: ["sleep", "600"]
5+
networks:
6+
default:
7+
ipv4_address: 10.1.0.100 # <-- Fixed IP address
8+
networks:
9+
default:
10+
ipam:
11+
config:
12+
- subnet: 10.1.0.0/16

local/e2e/compose/networks_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,26 @@ func TestNetworkAliassesAndLinks(t *testing.T) {
9494
_ = c.RunDockerCmd("compose", "--project-name", projectName, "down")
9595
})
9696
}
97+
98+
func TestIPAMConfig(t *testing.T) {
99+
c := NewParallelE2eCLI(t, binDir)
100+
101+
const projectName = "ipam_e2e"
102+
103+
t.Run("ensure we do not reuse previous networks", func(t *testing.T) {
104+
c.RunDockerOrExitError("network", "rm", projectName+"_default")
105+
})
106+
107+
t.Run("up", func(t *testing.T) {
108+
c.RunDockerCmd("compose", "-f", "./fixtures/ipam/compose.yaml", "--project-name", projectName, "up", "-d")
109+
})
110+
111+
t.Run("ensure service get fixed IP assigned", func(t *testing.T) {
112+
res := c.RunDockerCmd("inspect", projectName+"_foo_1", "-f", "{{ .NetworkSettings.Networks."+projectName+"_default.IPAddress }}")
113+
res.Assert(t, icmd.Expected{Out: "10.1.0.100"})
114+
})
115+
116+
t.Run("down", func(t *testing.T) {
117+
_ = c.RunDockerCmd("compose", "--project-name", projectName, "down")
118+
})
119+
}

pkg/compose/convergence.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -370,18 +370,24 @@ func shortIDAliasExists(containerID string, aliases ...string) bool {
370370

371371
func (s *composeService) connectContainerToNetwork(ctx context.Context, id string, netwrk string, cfg *types.ServiceNetworkConfig, links []string, aliases ...string) error {
372372
var (
373-
ipv4ddress string
373+
ipv4Address string
374374
ipv6Address string
375+
ipam *network.EndpointIPAMConfig
375376
)
376377
if cfg != nil {
377-
ipv4ddress = cfg.Ipv4Address
378+
ipv4Address = cfg.Ipv4Address
378379
ipv6Address = cfg.Ipv6Address
380+
ipam = &network.EndpointIPAMConfig{
381+
IPv4Address: ipv4Address,
382+
IPv6Address: ipv6Address,
383+
}
379384
}
380385
err := s.apiClient.NetworkConnect(ctx, netwrk, id, &network.EndpointSettings{
381386
Aliases: aliases,
382-
IPAddress: ipv4ddress,
387+
IPAddress: ipv4Address,
383388
GlobalIPv6Address: ipv6Address,
384389
Links: links,
390+
IPAMConfig: ipam,
385391
})
386392
if err != nil {
387393
return err

pkg/compose/create.go

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,17 +284,34 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
284284
}
285285

286286
var networkConfig *network.NetworkingConfig
287+
287288
for _, id := range service.NetworksByPriority() {
288289
net := p.Networks[id]
289290
config := service.Networks[id]
291+
var ipam *network.EndpointIPAMConfig
292+
var (
293+
ipv4Address string
294+
ipv6Address string
295+
)
296+
if config != nil {
297+
ipv4Address = config.Ipv4Address
298+
ipv6Address = config.Ipv6Address
299+
ipam = &network.EndpointIPAMConfig{
300+
IPv4Address: ipv4Address,
301+
IPv6Address: ipv6Address,
302+
}
303+
}
290304
networkConfig = &network.NetworkingConfig{
291305
EndpointsConfig: map[string]*network.EndpointSettings{
292306
net.Name: {
293-
Aliases: getAliases(service, config),
307+
Aliases: getAliases(service, config),
308+
IPAddress: ipv4Address,
309+
IPv6Gateway: ipv6Address,
310+
IPAMConfig: ipam,
294311
},
295312
},
296313
}
297-
break
314+
break //nolint:staticcheck
298315
}
299316

300317
ipcmode, err := getMode(ctx, service.Name, service.Ipc)
@@ -915,13 +932,30 @@ func (s *composeService) ensureNetwork(ctx context.Context, n types.NetworkConfi
915932
if n.External.External {
916933
return fmt.Errorf("network %s declared as external, but could not be found", n.Name)
917934
}
935+
var ipam *network.IPAM
936+
if n.Ipam.Config != nil {
937+
var config []network.IPAMConfig
938+
for _, pool := range n.Ipam.Config {
939+
config = append(config, network.IPAMConfig{
940+
Subnet: pool.Subnet,
941+
IPRange: pool.IPRange,
942+
Gateway: pool.Gateway,
943+
AuxAddress: pool.AuxiliaryAddresses,
944+
})
945+
}
946+
ipam = &network.IPAM{
947+
Driver: n.Ipam.Driver,
948+
Config: config,
949+
}
950+
}
918951
createOpts := moby.NetworkCreate{
919952
// TODO NameSpace Labels
920953
Labels: n.Labels,
921954
Driver: n.Driver,
922955
Options: n.DriverOpts,
923956
Internal: n.Internal,
924957
Attachable: n.Attachable,
958+
IPAM: ipam,
925959
}
926960

927961
if n.Ipam.Driver != "" || len(n.Ipam.Config) > 0 {

0 commit comments

Comments
 (0)