| package daemon | |
| import ( | |
| "net/netip" | |
| "testing" | |
| "github.com/moby/moby/api/types/network" | |
| "gotest.tools/v3/assert" | |
| is "gotest.tools/v3/assert/cmp" | |
| ) | |
| func TestValidateIPAM(t *testing.T) { | |
| tests := []struct { | |
| name string | |
| ipam []network.IPAMConfig | |
| ipv6 bool | |
| expectedErrors []string | |
| }{ | |
| { | |
| name: "IP version mismatch", | |
| ipam: []network.IPAMConfig{{ | |
| Subnet: netip.MustParsePrefix("10.10.10.0/24"), | |
| IPRange: netip.MustParsePrefix("2001:db8::/32"), | |
| Gateway: netip.MustParseAddr("2001:db8::1"), | |
| AuxAddress: map[string]netip.Addr{"DefaultGatewayIPv4": netip.MustParseAddr("2001:db8::1")}, | |
| }}, | |
| expectedErrors: []string{ | |
| "invalid ip-range 2001:db8::/32: parent subnet is an IPv4 block", | |
| "invalid gateway 2001:db8::1: parent subnet is an IPv4 block", | |
| "invalid auxiliary address DefaultGatewayIPv4: parent subnet is an IPv4 block", | |
| }, | |
| }, | |
| { | |
| // Regression test for https://github.com/moby/moby/issues/47202 | |
| name: "IPv6 subnet is discarded with no error when IPv6 is disabled", | |
| ipam: []network.IPAMConfig{{Subnet: netip.MustParsePrefix("2001:db8::/32")}}, | |
| ipv6: false, | |
| }, | |
| { | |
| name: "IPRange bigger than its subnet", | |
| ipam: []network.IPAMConfig{ | |
| {Subnet: netip.MustParsePrefix("10.10.10.0/24"), IPRange: netip.MustParsePrefix("10.0.0.0/8")}, | |
| }, | |
| expectedErrors: []string{ | |
| "invalid ip-range 10.0.0.0/8: CIDR block is bigger than its parent subnet 10.10.10.0/24", | |
| }, | |
| }, | |
| { | |
| name: "Out of range prefix & addresses", | |
| ipam: []network.IPAMConfig{{ | |
| Subnet: netip.MustParsePrefix("10.0.0.0/8"), | |
| IPRange: netip.MustParsePrefix("192.168.0.1/24"), | |
| Gateway: netip.MustParseAddr("192.168.0.1"), | |
| AuxAddress: map[string]netip.Addr{"DefaultGatewayIPv4": netip.MustParseAddr("192.168.0.1")}, | |
| }}, | |
| expectedErrors: []string{ | |
| "invalid ip-range 192.168.0.1/24: it should be 192.168.0.0/24", | |
| "invalid ip-range 192.168.0.1/24: parent subnet 10.0.0.0/8 doesn't contain ip-range", | |
| "invalid gateway 192.168.0.1: parent subnet 10.0.0.0/8 doesn't contain this address", | |
| "invalid auxiliary address DefaultGatewayIPv4: parent subnet 10.0.0.0/8 doesn't contain this address", | |
| }, | |
| }, | |
| { | |
| name: "Subnet with host fragment set", | |
| ipam: []network.IPAMConfig{{ | |
| Subnet: netip.MustParsePrefix("10.10.10.0/8"), | |
| }}, | |
| expectedErrors: []string{"invalid subnet 10.10.10.0/8: it should be 10.0.0.0/8"}, | |
| }, | |
| { | |
| name: "IPRange with host fragment set", | |
| ipam: []network.IPAMConfig{{ | |
| Subnet: netip.MustParsePrefix("10.0.0.0/8"), | |
| IPRange: netip.MustParsePrefix("10.10.10.0/16"), | |
| }}, | |
| expectedErrors: []string{"invalid ip-range 10.10.10.0/16: it should be 10.10.0.0/16"}, | |
| }, | |
| { | |
| name: "Empty IPAM is valid", | |
| }, | |
| { | |
| name: "Valid IPAM", | |
| ipam: []network.IPAMConfig{{ | |
| Subnet: netip.MustParsePrefix("10.0.0.0/8"), | |
| IPRange: netip.MustParsePrefix("10.10.0.0/16"), | |
| Gateway: netip.MustParseAddr("10.10.0.1"), | |
| AuxAddress: map[string]netip.Addr{"DefaultGatewayIPv4": netip.MustParseAddr("10.10.0.1")}, | |
| }}, | |
| }, | |
| } | |
| for _, tc := range tests { | |
| t.Run(tc.name, func(t *testing.T) { | |
| t.Parallel() | |
| errs := validateIpamConfig(tc.ipam, tc.ipv6) | |
| if tc.expectedErrors == nil { | |
| assert.NilError(t, errs) | |
| return | |
| } | |
| assert.Check(t, is.ErrorContains(errs, "invalid network config")) | |
| for _, expected := range tc.expectedErrors { | |
| assert.Check(t, is.ErrorContains(errs, expected)) | |
| } | |
| }) | |
| } | |
| } |