فهرست منبع

api/t/net: test EndpointIPAMConfig.Validate()

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
Albin Kerouanton 1 سال پیش
والد
کامیت
acf825def2
1فایلهای تغییر یافته به همراه188 افزوده شده و 0 حذف شده
  1. 188 0
      api/types/network/endpoint_test.go

+ 188 - 0
api/types/network/endpoint_test.go

@@ -0,0 +1,188 @@
+package network
+
+import (
+	"net"
+	"testing"
+
+	"gotest.tools/v3/assert"
+	is "gotest.tools/v3/assert/cmp"
+)
+
+type subnetStub struct {
+	static   bool
+	contains map[string]bool
+}
+
+func (stub subnetStub) IsStatic() bool {
+	return stub.static
+}
+
+func (stub subnetStub) Contains(addr net.IP) bool {
+	v, ok := stub.contains[addr.String()]
+	return ok && v
+}
+
+func TestEndpointIPAMConfigWithOutOfRangeAddrs(t *testing.T) {
+	testcases := []struct {
+		name           string
+		ipamConfig     *EndpointIPAMConfig
+		v4Subnets      []NetworkSubnet
+		v6Subnets      []NetworkSubnet
+		expectedErrors []string
+	}{
+		{
+			name: "valid config",
+			ipamConfig: &EndpointIPAMConfig{
+				IPv4Address:  "192.168.100.10",
+				IPv6Address:  "2a01:d2:af:420b:25c1:1816:bb33:855c",
+				LinkLocalIPs: []string{"169.254.169.254", "fe80::42:a8ff:fe33:6230"},
+			},
+			v4Subnets: []NetworkSubnet{
+				subnetStub{static: true, contains: map[string]bool{"192.168.100.10": true}},
+			},
+			v6Subnets: []NetworkSubnet{
+				subnetStub{static: true, contains: map[string]bool{"2a01:d2:af:420b:25c1:1816:bb33:855c": true}},
+			},
+		},
+		{
+			name: "static addresses out of range",
+			ipamConfig: &EndpointIPAMConfig{
+				IPv4Address: "192.168.100.10",
+				IPv6Address: "2a01:d2:af:420b:25c1:1816:bb33:855c",
+			},
+			v4Subnets: []NetworkSubnet{
+				subnetStub{static: true, contains: map[string]bool{"192.168.100.10": false}},
+			},
+			v6Subnets: []NetworkSubnet{
+				subnetStub{static: true, contains: map[string]bool{"2a01:d2:af:420b:25c1:1816:bb33:855c": false}},
+			},
+			expectedErrors: []string{
+				"no configured subnet or ip-range contain the IP address 192.168.100.10",
+				"no configured subnet or ip-range contain the IP address 2a01:d2:af:420b:25c1:1816:bb33:855c",
+			},
+		},
+		{
+			name: "static addresses with dynamic network subnets",
+			ipamConfig: &EndpointIPAMConfig{
+				IPv4Address: "192.168.100.10",
+				IPv6Address: "2a01:d2:af:420b:25c1:1816:bb33:855c",
+			},
+			v4Subnets: []NetworkSubnet{
+				subnetStub{static: false},
+			},
+			v6Subnets: []NetworkSubnet{
+				subnetStub{static: false},
+			},
+			expectedErrors: []string{
+				"user specified IP address is supported only when connecting to networks with user configured subnets",
+				"user specified IP address is supported only when connecting to networks with user configured subnets",
+			},
+		},
+	}
+
+	for _, tc := range testcases {
+		tc := tc
+		t.Run(tc.name, func(t *testing.T) {
+			t.Parallel()
+
+			err := tc.ipamConfig.IsInRange(tc.v4Subnets, tc.v6Subnets)
+			if tc.expectedErrors == nil {
+				assert.NilError(t, err)
+				return
+			}
+
+			if _, ok := err.(interface{ Unwrap() []error }); !ok {
+				t.Fatal("returned error isn't a multierror")
+			}
+			errs := err.(interface{ Unwrap() []error }).Unwrap()
+			assert.Check(t, len(errs) == len(tc.expectedErrors), "errs: %+v", errs)
+
+			for _, expected := range tc.expectedErrors {
+				assert.Check(t, is.ErrorContains(err, expected))
+			}
+		})
+	}
+
+}
+
+func TestEndpointIPAMConfigWithInvalidConfig(t *testing.T) {
+	testcases := []struct {
+		name           string
+		ipamConfig     *EndpointIPAMConfig
+		expectedErrors []string
+	}{
+		{
+			name: "valid config",
+			ipamConfig: &EndpointIPAMConfig{
+				IPv4Address:  "192.168.100.10",
+				IPv6Address:  "2a01:d2:af:420b:25c1:1816:bb33:855c",
+				LinkLocalIPs: []string{"169.254.169.254", "fe80::42:a8ff:fe33:6230"},
+			},
+		},
+		{
+			name: "invalid IP addresses",
+			ipamConfig: &EndpointIPAMConfig{
+				IPv4Address:  "foo",
+				IPv6Address:  "bar",
+				LinkLocalIPs: []string{"baz", "foobar"},
+			},
+			expectedErrors: []string{
+				"invalid IPv4 address: foo",
+				"invalid IPv6 address: bar",
+				"invalid link-local IP address: baz",
+				"invalid link-local IP address: foobar",
+			},
+		},
+		{
+			name:       "ipv6 address with a zone",
+			ipamConfig: &EndpointIPAMConfig{IPv6Address: "fe80::1cc0:3e8c:119f:c2e1%ens18"},
+			expectedErrors: []string{
+				"invalid IPv6 address: fe80::1cc0:3e8c:119f:c2e1%ens18",
+			},
+		},
+		{
+			name: "unspecified address is invalid",
+			ipamConfig: &EndpointIPAMConfig{
+				IPv4Address:  "0.0.0.0",
+				IPv6Address:  "::",
+				LinkLocalIPs: []string{"0.0.0.0", "::"},
+			},
+			expectedErrors: []string{
+				"invalid IPv4 address: 0.0.0.0",
+				"invalid IPv6 address: ::",
+				"invalid link-local IP address: 0.0.0.0",
+				"invalid link-local IP address: ::",
+			},
+		},
+		{
+			name: "empty link-local",
+			ipamConfig: &EndpointIPAMConfig{
+				LinkLocalIPs: []string{""},
+			},
+			expectedErrors: []string{"invalid link-local IP address:"},
+		},
+	}
+
+	for _, tc := range testcases {
+		tc := tc
+		t.Run(tc.name, func(t *testing.T) {
+			t.Parallel()
+
+			err := tc.ipamConfig.Validate()
+			if tc.expectedErrors == nil {
+				assert.NilError(t, err)
+				return
+			}
+
+			if _, ok := err.(interface{ Unwrap() []error }); !ok {
+				t.Fatal("returned error isn't a multierror")
+			}
+			errs := err.(interface{ Unwrap() []error }).Unwrap()
+			assert.Check(t, len(errs) == len(tc.expectedErrors), "errs: %+v", errs)
+
+			for _, expected := range tc.expectedErrors {
+				assert.Check(t, is.ErrorContains(err, expected))
+			}
+		})
+	}
+}