github.com/moby/docker@v26.1.3+incompatible/api/types/network/endpoint_test.go (about) 1 package network 2 3 import ( 4 "net" 5 "testing" 6 7 "gotest.tools/v3/assert" 8 is "gotest.tools/v3/assert/cmp" 9 ) 10 11 type subnetStub struct { 12 static bool 13 contains map[string]bool 14 } 15 16 func (stub subnetStub) IsStatic() bool { 17 return stub.static 18 } 19 20 func (stub subnetStub) Contains(addr net.IP) bool { 21 v, ok := stub.contains[addr.String()] 22 return ok && v 23 } 24 25 func TestEndpointIPAMConfigWithOutOfRangeAddrs(t *testing.T) { 26 testcases := []struct { 27 name string 28 ipamConfig *EndpointIPAMConfig 29 v4Subnets []NetworkSubnet 30 v6Subnets []NetworkSubnet 31 expectedErrors []string 32 }{ 33 { 34 name: "valid config", 35 ipamConfig: &EndpointIPAMConfig{ 36 IPv4Address: "192.168.100.10", 37 IPv6Address: "2a01:d2:af:420b:25c1:1816:bb33:855c", 38 LinkLocalIPs: []string{"169.254.169.254", "fe80::42:a8ff:fe33:6230"}, 39 }, 40 v4Subnets: []NetworkSubnet{ 41 subnetStub{static: true, contains: map[string]bool{"192.168.100.10": true}}, 42 }, 43 v6Subnets: []NetworkSubnet{ 44 subnetStub{static: true, contains: map[string]bool{"2a01:d2:af:420b:25c1:1816:bb33:855c": true}}, 45 }, 46 }, 47 { 48 name: "static addresses out of range", 49 ipamConfig: &EndpointIPAMConfig{ 50 IPv4Address: "192.168.100.10", 51 IPv6Address: "2a01:d2:af:420b:25c1:1816:bb33:855c", 52 }, 53 v4Subnets: []NetworkSubnet{ 54 subnetStub{static: true, contains: map[string]bool{"192.168.100.10": false}}, 55 }, 56 v6Subnets: []NetworkSubnet{ 57 subnetStub{static: true, contains: map[string]bool{"2a01:d2:af:420b:25c1:1816:bb33:855c": false}}, 58 }, 59 expectedErrors: []string{ 60 "no configured subnet or ip-range contain the IP address 192.168.100.10", 61 "no configured subnet or ip-range contain the IP address 2a01:d2:af:420b:25c1:1816:bb33:855c", 62 }, 63 }, 64 { 65 name: "static addresses with dynamic network subnets", 66 ipamConfig: &EndpointIPAMConfig{ 67 IPv4Address: "192.168.100.10", 68 IPv6Address: "2a01:d2:af:420b:25c1:1816:bb33:855c", 69 }, 70 v4Subnets: []NetworkSubnet{ 71 subnetStub{static: false}, 72 }, 73 v6Subnets: []NetworkSubnet{ 74 subnetStub{static: false}, 75 }, 76 expectedErrors: []string{ 77 "user specified IP address is supported only when connecting to networks with user configured subnets", 78 "user specified IP address is supported only when connecting to networks with user configured subnets", 79 }, 80 }, 81 } 82 83 for _, tc := range testcases { 84 tc := tc 85 t.Run(tc.name, func(t *testing.T) { 86 t.Parallel() 87 88 err := tc.ipamConfig.IsInRange(tc.v4Subnets, tc.v6Subnets) 89 if tc.expectedErrors == nil { 90 assert.NilError(t, err) 91 return 92 } 93 94 if _, ok := err.(interface{ Unwrap() []error }); !ok { 95 t.Fatal("returned error isn't a multierror") 96 } 97 errs := err.(interface{ Unwrap() []error }).Unwrap() 98 assert.Check(t, len(errs) == len(tc.expectedErrors), "errs: %+v", errs) 99 100 for _, expected := range tc.expectedErrors { 101 assert.Check(t, is.ErrorContains(err, expected)) 102 } 103 }) 104 } 105 106 } 107 108 func TestEndpointIPAMConfigWithInvalidConfig(t *testing.T) { 109 testcases := []struct { 110 name string 111 ipamConfig *EndpointIPAMConfig 112 expectedErrors []string 113 }{ 114 { 115 name: "valid config", 116 ipamConfig: &EndpointIPAMConfig{ 117 IPv4Address: "192.168.100.10", 118 IPv6Address: "2a01:d2:af:420b:25c1:1816:bb33:855c", 119 LinkLocalIPs: []string{"169.254.169.254", "fe80::42:a8ff:fe33:6230"}, 120 }, 121 }, 122 { 123 name: "invalid IP addresses", 124 ipamConfig: &EndpointIPAMConfig{ 125 IPv4Address: "foo", 126 IPv6Address: "bar", 127 LinkLocalIPs: []string{"baz", "foobar"}, 128 }, 129 expectedErrors: []string{ 130 "invalid IPv4 address: foo", 131 "invalid IPv6 address: bar", 132 "invalid link-local IP address: baz", 133 "invalid link-local IP address: foobar", 134 }, 135 }, 136 { 137 name: "ipv6 address with a zone", 138 ipamConfig: &EndpointIPAMConfig{IPv6Address: "fe80::1cc0:3e8c:119f:c2e1%ens18"}, 139 expectedErrors: []string{ 140 "invalid IPv6 address: fe80::1cc0:3e8c:119f:c2e1%ens18", 141 }, 142 }, 143 { 144 name: "unspecified address is invalid", 145 ipamConfig: &EndpointIPAMConfig{ 146 IPv4Address: "0.0.0.0", 147 IPv6Address: "::", 148 LinkLocalIPs: []string{"0.0.0.0", "::"}, 149 }, 150 expectedErrors: []string{ 151 "invalid IPv4 address: 0.0.0.0", 152 "invalid IPv6 address: ::", 153 "invalid link-local IP address: 0.0.0.0", 154 "invalid link-local IP address: ::", 155 }, 156 }, 157 { 158 name: "empty link-local", 159 ipamConfig: &EndpointIPAMConfig{ 160 LinkLocalIPs: []string{""}, 161 }, 162 expectedErrors: []string{"invalid link-local IP address:"}, 163 }, 164 } 165 166 for _, tc := range testcases { 167 tc := tc 168 t.Run(tc.name, func(t *testing.T) { 169 t.Parallel() 170 171 err := tc.ipamConfig.Validate() 172 if tc.expectedErrors == nil { 173 assert.NilError(t, err) 174 return 175 } 176 177 if _, ok := err.(interface{ Unwrap() []error }); !ok { 178 t.Fatal("returned error isn't a multierror") 179 } 180 errs := err.(interface{ Unwrap() []error }).Unwrap() 181 assert.Check(t, len(errs) == len(tc.expectedErrors), "errs: %+v", errs) 182 183 for _, expected := range tc.expectedErrors { 184 assert.Check(t, is.ErrorContains(err, expected)) 185 } 186 }) 187 } 188 }