k8s.io/kubernetes@v1.29.3/pkg/controller/servicecidrs/servicecidrs_controller_test.go (about) 1 /* 2 Copyright 2023 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package servicecidrs 18 19 import ( 20 "context" 21 "testing" 22 "time" 23 24 "github.com/google/go-cmp/cmp" 25 "github.com/google/go-cmp/cmp/cmpopts" 26 v1 "k8s.io/api/core/v1" 27 networkingapiv1alpha1 "k8s.io/api/networking/v1alpha1" 28 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 "k8s.io/client-go/informers" 30 "k8s.io/client-go/kubernetes/fake" 31 k8stesting "k8s.io/client-go/testing" 32 "k8s.io/client-go/tools/cache" 33 "k8s.io/kubernetes/pkg/controller" 34 "k8s.io/kubernetes/pkg/controlplane/controller/defaultservicecidr" 35 "k8s.io/kubernetes/pkg/registry/core/service/ipallocator" 36 netutils "k8s.io/utils/net" 37 "k8s.io/utils/ptr" 38 ) 39 40 type testController struct { 41 *Controller 42 servicecidrsStore cache.Store 43 ipaddressesStore cache.Store 44 } 45 46 func newController(t *testing.T, cidrs []*networkingapiv1alpha1.ServiceCIDR, ips []*networkingapiv1alpha1.IPAddress) (*fake.Clientset, *testController) { 47 client := fake.NewSimpleClientset() 48 49 informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc()) 50 51 serviceCIDRInformer := informerFactory.Networking().V1alpha1().ServiceCIDRs() 52 cidrStore := serviceCIDRInformer.Informer().GetStore() 53 for _, obj := range cidrs { 54 err := cidrStore.Add(obj) 55 if err != nil { 56 t.Fatal(err) 57 } 58 } 59 ipAddressInformer := informerFactory.Networking().V1alpha1().IPAddresses() 60 ipStore := ipAddressInformer.Informer().GetStore() 61 for _, obj := range ips { 62 err := ipStore.Add(obj) 63 if err != nil { 64 t.Fatal(err) 65 } 66 } 67 controller := NewController( 68 serviceCIDRInformer, 69 ipAddressInformer, 70 client) 71 72 var alwaysReady = func() bool { return true } 73 controller.serviceCIDRsSynced = alwaysReady 74 controller.ipAddressSynced = alwaysReady 75 76 return client, &testController{ 77 controller, 78 cidrStore, 79 ipStore, 80 } 81 } 82 83 func TestControllerSync(t *testing.T) { 84 now := time.Now() 85 86 // ServiceCIDR that is just being deleted 87 deletingServiceCIDR := makeServiceCIDR("deleting-cidr", "192.168.0.0/24", "2001:db2::/64") 88 deletingServiceCIDR.Finalizers = []string{ServiceCIDRProtectionFinalizer} 89 deletingServiceCIDR.DeletionTimestamp = ptr.To[metav1.Time](metav1.Now()) 90 91 // ServiceCIDR that has been deleted for longer than the deletionGracePeriod 92 deletedServiceCIDR := makeServiceCIDR("deleted-cidr", "192.168.0.0/24", "2001:db2::/64") 93 deletedServiceCIDR.Finalizers = []string{ServiceCIDRProtectionFinalizer} 94 deletedServiceCIDR.DeletionTimestamp = ptr.To[metav1.Time](metav1.NewTime(now.Add(-deletionGracePeriod - 1*time.Second))) 95 96 testCases := []struct { 97 name string 98 cidrs []*networkingapiv1alpha1.ServiceCIDR 99 ips []*networkingapiv1alpha1.IPAddress 100 cidrSynced string 101 actions [][]string // verb and resource and subresource 102 }{ 103 { 104 name: "no existing service CIDRs", 105 }, 106 { 107 name: "default service CIDR must have finalizer", 108 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 109 makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 110 }, 111 cidrSynced: defaultservicecidr.DefaultServiceCIDRName, 112 actions: [][]string{{"patch", "servicecidrs", ""}, {"patch", "servicecidrs", "status"}}, 113 }, 114 { 115 name: "service CIDR must have finalizer", 116 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 117 makeServiceCIDR("no-finalizer", "192.168.0.0/24", "2001:db2::/64"), 118 }, 119 cidrSynced: "no-finalizer", 120 actions: [][]string{{"patch", "servicecidrs", ""}, {"patch", "servicecidrs", "status"}}, 121 }, 122 { 123 name: "service CIDR being deleted must remove the finalizer", 124 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 125 deletedServiceCIDR, 126 }, 127 cidrSynced: deletedServiceCIDR.Name, 128 actions: [][]string{{"patch", "servicecidrs", ""}}, 129 }, 130 { 131 name: "service CIDR being deleted but within the grace period must be requeued not remove the finalizer", // TODO: assert is actually requeued 132 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 133 deletingServiceCIDR, 134 }, 135 cidrSynced: deletingServiceCIDR.Name, 136 actions: [][]string{}, 137 }, 138 { 139 name: "service CIDR being deleted with IPv4 addresses should update the status", 140 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 141 deletedServiceCIDR, 142 }, 143 ips: []*networkingapiv1alpha1.IPAddress{ 144 makeIPAddress("192.168.0.1"), 145 }, 146 cidrSynced: deletedServiceCIDR.Name, 147 actions: [][]string{{"patch", "servicecidrs", "status"}}, 148 }, 149 { 150 name: "service CIDR being deleted and overlapping same range and IPv4 addresses should remove the finalizer", 151 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 152 deletedServiceCIDR, 153 makeServiceCIDR("overlapping", "192.168.0.0/24", "2001:db2::/64"), 154 }, 155 ips: []*networkingapiv1alpha1.IPAddress{ 156 makeIPAddress("192.168.0.1"), 157 }, 158 cidrSynced: deletedServiceCIDR.Name, 159 actions: [][]string{{"patch", "servicecidrs", ""}}, 160 }, 161 { 162 name: "service CIDR being deleted and overlapping and IPv4 addresses should remove the finalizer", 163 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 164 deletedServiceCIDR, 165 makeServiceCIDR("overlapping", "192.168.0.0/16", "2001:db2::/64"), 166 }, 167 ips: []*networkingapiv1alpha1.IPAddress{ 168 makeIPAddress("192.168.0.1"), 169 }, 170 cidrSynced: deletedServiceCIDR.Name, 171 actions: [][]string{{"patch", "servicecidrs", ""}}, 172 }, 173 { 174 name: "service CIDR being deleted and not overlapping and IPv4 addresses should update the status", 175 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 176 deletedServiceCIDR, 177 makeServiceCIDR("overlapping", "192.168.255.0/26", "2001:db2::/64"), 178 }, 179 ips: []*networkingapiv1alpha1.IPAddress{ 180 makeIPAddress("192.168.0.1"), 181 }, 182 cidrSynced: deletedServiceCIDR.Name, 183 actions: [][]string{{"patch", "servicecidrs", "status"}}, 184 }, 185 { 186 name: "service CIDR being deleted with IPv6 addresses should update the status", 187 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 188 deletedServiceCIDR, 189 }, 190 ips: []*networkingapiv1alpha1.IPAddress{ 191 makeIPAddress("2001:db2::1"), 192 }, 193 cidrSynced: deletedServiceCIDR.Name, 194 actions: [][]string{{"patch", "servicecidrs", "status"}}, 195 }, 196 { 197 name: "service CIDR being deleted and overlapping same range and IPv6 addresses should remove the finalizer", 198 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 199 deletedServiceCIDR, 200 makeServiceCIDR("overlapping", "192.168.0.0/24", "2001:db2::/64"), 201 }, 202 ips: []*networkingapiv1alpha1.IPAddress{ 203 makeIPAddress("2001:db2::1"), 204 }, 205 cidrSynced: deletedServiceCIDR.Name, 206 actions: [][]string{{"patch", "servicecidrs", ""}}, 207 }, 208 { 209 name: "service CIDR being deleted and overlapping and IPv6 addresses should remove the finalizer", 210 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 211 deletedServiceCIDR, 212 makeServiceCIDR("overlapping", "192.168.0.0/16", "2001:db2::/48"), 213 }, 214 ips: []*networkingapiv1alpha1.IPAddress{ 215 makeIPAddress("2001:db2::1"), 216 }, 217 cidrSynced: deletedServiceCIDR.Name, 218 actions: [][]string{{"patch", "servicecidrs", ""}}, 219 }, 220 { 221 name: "service CIDR being deleted and not overlapping and IPv6 addresses should update the status", 222 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 223 deletedServiceCIDR, 224 makeServiceCIDR("overlapping", "192.168.255.0/26", "2001:db2:a:b::/64"), 225 }, 226 ips: []*networkingapiv1alpha1.IPAddress{ 227 makeIPAddress("2001:db2::1"), 228 }, 229 cidrSynced: deletedServiceCIDR.Name, 230 actions: [][]string{{"patch", "servicecidrs", "status"}}, 231 }, 232 } 233 234 for _, tc := range testCases { 235 t.Run(tc.name, func(t *testing.T) { 236 client, controller := newController(t, tc.cidrs, tc.ips) 237 // server side apply does not play well with fake client go 238 // so we skup the errors and only assert on the actions 239 // https://github.com/kubernetes/kubernetes/issues/99953 240 _ = controller.sync(context.Background(), tc.cidrSynced) 241 expectAction(t, client.Actions(), tc.actions) 242 243 }) 244 } 245 } 246 247 func makeServiceCIDR(name, primary, secondary string) *networkingapiv1alpha1.ServiceCIDR { 248 serviceCIDR := &networkingapiv1alpha1.ServiceCIDR{ 249 ObjectMeta: metav1.ObjectMeta{ 250 Name: name, 251 }, 252 Spec: networkingapiv1alpha1.ServiceCIDRSpec{}, 253 } 254 serviceCIDR.Spec.CIDRs = append(serviceCIDR.Spec.CIDRs, primary) 255 if secondary != "" { 256 serviceCIDR.Spec.CIDRs = append(serviceCIDR.Spec.CIDRs, secondary) 257 } 258 return serviceCIDR 259 } 260 261 func makeIPAddress(name string) *networkingapiv1alpha1.IPAddress { 262 family := string(v1.IPv4Protocol) 263 if netutils.IsIPv6String(name) { 264 family = string(v1.IPv6Protocol) 265 } 266 return &networkingapiv1alpha1.IPAddress{ 267 ObjectMeta: metav1.ObjectMeta{ 268 Name: name, 269 Labels: map[string]string{ 270 networkingapiv1alpha1.LabelIPAddressFamily: family, 271 networkingapiv1alpha1.LabelManagedBy: ipallocator.ControllerName, 272 }, 273 }, 274 } 275 } 276 277 func expectAction(t *testing.T, actions []k8stesting.Action, expected [][]string) { 278 t.Helper() 279 if len(actions) != len(expected) { 280 t.Fatalf("Expected at least %d actions, got %d \ndiff: %v", len(expected), len(actions), cmp.Diff(expected, actions)) 281 } 282 283 for i, action := range actions { 284 verb := expected[i][0] 285 if action.GetVerb() != verb { 286 t.Errorf("Expected action %d verb to be %s, got %s", i, verb, action.GetVerb()) 287 } 288 resource := expected[i][1] 289 if action.GetResource().Resource != resource { 290 t.Errorf("Expected action %d resource to be %s, got %s", i, resource, action.GetResource().Resource) 291 } 292 subresource := expected[i][2] 293 if action.GetSubresource() != subresource { 294 t.Errorf("Expected action %d subresource to be %s, got %s", i, subresource, action.GetSubresource()) 295 } 296 } 297 } 298 299 func TestController_canDeleteCIDR(t *testing.T) { 300 tests := []struct { 301 name string 302 cidrs []*networkingapiv1alpha1.ServiceCIDR 303 ips []*networkingapiv1alpha1.IPAddress 304 cidrSynced *networkingapiv1alpha1.ServiceCIDR 305 want bool 306 }{ 307 { 308 name: "empty", 309 cidrSynced: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 310 want: true, 311 }, 312 { 313 name: "CIDR and no IPs", 314 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 315 makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 316 }, 317 cidrSynced: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 318 want: true, 319 }, 320 { 321 name: "CIDR with IPs", 322 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 323 makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 324 }, 325 ips: []*networkingapiv1alpha1.IPAddress{ 326 makeIPAddress("192.168.0.24"), 327 }, 328 cidrSynced: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 329 want: false, 330 }, 331 { 332 name: "CIDR without IPs", 333 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 334 makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 335 }, 336 ips: []*networkingapiv1alpha1.IPAddress{ 337 makeIPAddress("192.168.1.24"), 338 }, 339 cidrSynced: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 340 want: true, 341 }, 342 { 343 name: "CIDR with IPv4 address referencing the subnet address", 344 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 345 makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 346 }, 347 ips: []*networkingapiv1alpha1.IPAddress{ 348 makeIPAddress("192.168.0.0"), 349 }, 350 cidrSynced: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 351 want: true, 352 }, 353 { 354 name: "CIDR with IPv4 address referencing the broadcast address", 355 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 356 makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 357 }, 358 ips: []*networkingapiv1alpha1.IPAddress{ 359 makeIPAddress("192.168.0.255"), 360 }, 361 cidrSynced: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 362 want: true, 363 }, 364 { 365 name: "CIDR with IPv6 address referencing the broadcast address", 366 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 367 makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 368 }, 369 ips: []*networkingapiv1alpha1.IPAddress{ 370 makeIPAddress("2001:0db2::ffff:ffff:ffff:ffff"), 371 }, 372 cidrSynced: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 373 want: false, 374 }, 375 { 376 name: "CIDR with same range overlapping and IPs", 377 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 378 makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 379 makeServiceCIDR("overlapping", "192.168.0.0/24", "2001:db2::/64"), 380 }, 381 ips: []*networkingapiv1alpha1.IPAddress{ 382 makeIPAddress("192.168.0.23"), 383 }, 384 cidrSynced: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 385 want: true, 386 }, 387 { 388 name: "CIDR with smaller range overlapping and IPs", 389 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 390 makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 391 makeServiceCIDR("overlapping", "192.168.0.0/26", "2001:db2::/64"), 392 }, 393 ips: []*networkingapiv1alpha1.IPAddress{ 394 makeIPAddress("192.168.0.23"), 395 }, 396 cidrSynced: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 397 want: true, 398 }, 399 { 400 name: "CIDR with smaller range overlapping but IPs orphan", 401 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 402 makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 403 makeServiceCIDR("overlapping", "192.168.0.0/28", "2001:db2::/64"), 404 }, 405 ips: []*networkingapiv1alpha1.IPAddress{ 406 makeIPAddress("192.168.0.23"), 407 }, 408 cidrSynced: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 409 want: false, 410 }, 411 { 412 name: "CIDR with larger range overlapping and IPs", 413 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 414 makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 415 makeServiceCIDR("overlapping", "192.168.0.0/16", "2001:db2::/64"), 416 }, 417 ips: []*networkingapiv1alpha1.IPAddress{ 418 makeIPAddress("192.168.0.23"), 419 }, 420 cidrSynced: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 421 want: true, 422 }, 423 } 424 for _, tc := range tests { 425 t.Run(tc.name, func(t *testing.T) { 426 _, controller := newController(t, tc.cidrs, tc.ips) 427 err := controller.syncCIDRs() 428 if err != nil { 429 t.Fatal(err) 430 } 431 432 got, err := controller.canDeleteCIDR(context.Background(), tc.cidrSynced) 433 if err != nil { 434 t.Fatal(err) 435 } 436 if got != tc.want { 437 t.Errorf("Controller.canDeleteCIDR() = %v, want %v", got, tc.want) 438 } 439 }) 440 } 441 } 442 443 func TestController_ipToCidrs(t *testing.T) { 444 tests := []struct { 445 name string 446 cidrs []*networkingapiv1alpha1.ServiceCIDR 447 ip *networkingapiv1alpha1.IPAddress 448 want []string 449 }{ 450 { 451 name: "empty", 452 ip: makeIPAddress("192.168.0.23"), 453 want: []string{}, 454 }, { 455 name: "one CIDR", 456 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 457 makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 458 makeServiceCIDR("unrelated", "10.0.0.0/24", ""), 459 makeServiceCIDR("unrelated2", "10.0.0.0/16", ""), 460 }, 461 ip: makeIPAddress("192.168.0.23"), 462 want: []string{defaultservicecidr.DefaultServiceCIDRName}, 463 }, { 464 name: "two equal CIDR", 465 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 466 makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 467 makeServiceCIDR("overlapping", "192.168.0.0/24", "2001:db2::/96"), 468 makeServiceCIDR("unrelated", "10.0.0.0/24", ""), 469 makeServiceCIDR("unrelated2", "10.0.0.0/16", ""), 470 }, 471 ip: makeIPAddress("192.168.0.23"), 472 want: []string{defaultservicecidr.DefaultServiceCIDRName, "overlapping"}, 473 }, { 474 name: "three CIDR - two same and one larger", 475 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 476 makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 477 makeServiceCIDR("overlapping", "192.168.0.0/24", "2001:db2::/64"), 478 makeServiceCIDR("overlapping2", "192.168.0.0/26", "2001:db2::/96"), 479 makeServiceCIDR("unrelated", "10.0.0.0/24", ""), 480 makeServiceCIDR("unrelated2", "10.0.0.0/16", ""), 481 }, 482 ip: makeIPAddress("192.168.0.23"), 483 want: []string{defaultservicecidr.DefaultServiceCIDRName, "overlapping", "overlapping2"}, 484 }, { 485 name: "three CIDR - two same and one larger - IPv4 subnet address", 486 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 487 makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 488 makeServiceCIDR("overlapping", "192.168.0.0/24", "2001:db2::/64"), 489 makeServiceCIDR("overlapping2", "192.168.0.0/26", "2001:db2::/96"), 490 makeServiceCIDR("unrelated", "10.0.0.0/24", ""), 491 makeServiceCIDR("unrelated2", "10.0.0.0/16", ""), 492 }, 493 ip: makeIPAddress("192.168.0.0"), 494 want: []string{}, 495 }, { 496 name: "three CIDR - two same and one larger - IPv4 broadcast address", 497 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 498 makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 499 makeServiceCIDR("overlapping", "192.168.0.0/24", "2001:db2::/64"), 500 makeServiceCIDR("overlapping2", "192.168.0.0/26", "2001:db2::/96"), 501 makeServiceCIDR("unrelated", "10.0.0.0/24", ""), 502 makeServiceCIDR("unrelated2", "10.0.0.0/16", ""), 503 }, 504 ip: makeIPAddress("192.168.0.63"), // broadcast for 192.168.0.0/26 505 want: []string{defaultservicecidr.DefaultServiceCIDRName, "overlapping"}, 506 }, { 507 name: "three CIDR - two same and one larger - IPv6 subnet address", 508 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 509 makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 510 makeServiceCIDR("overlapping", "192.168.0.0/24", "2001:db2::/64"), 511 makeServiceCIDR("overlapping2", "192.168.0.0/26", "2001:db2::/96"), 512 makeServiceCIDR("unrelated", "10.0.0.0/24", ""), 513 makeServiceCIDR("unrelated2", "10.0.0.0/16", ""), 514 }, 515 ip: makeIPAddress("2001:db2::"), 516 want: []string{}, 517 }, { 518 name: "three CIDR - two same and one larger - IPv6 broadcast address", 519 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 520 makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 521 makeServiceCIDR("overlapping", "192.168.0.0/24", "2001:db2::/64"), 522 makeServiceCIDR("overlapping2", "192.168.0.0/26", "2001:db2::/96"), 523 makeServiceCIDR("unrelated", "10.0.0.0/24", ""), 524 makeServiceCIDR("unrelated2", "10.0.0.0/16", ""), 525 }, 526 ip: makeIPAddress("2001:0db2::ffff:ffff:ffff:ffff"), 527 want: []string{defaultservicecidr.DefaultServiceCIDRName, "overlapping"}, 528 }} 529 for _, tt := range tests { 530 t.Run(tt.name, func(t *testing.T) { 531 _, controller := newController(t, tt.cidrs, nil) 532 err := controller.syncCIDRs() 533 if err != nil { 534 t.Fatal(err) 535 } 536 if got := controller.containingServiceCIDRs(tt.ip); !cmp.Equal(got, tt.want, cmpopts.SortSlices(func(a, b string) bool { return a < b })) { 537 t.Errorf("Controller.ipToCidrs() = %v, want %v", got, tt.want) 538 } 539 }) 540 } 541 } 542 543 func TestController_cidrToCidrs(t *testing.T) { 544 tests := []struct { 545 name string 546 cidrs []*networkingapiv1alpha1.ServiceCIDR 547 cidr *networkingapiv1alpha1.ServiceCIDR 548 want []string 549 }{ 550 { 551 name: "empty", 552 cidr: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 553 want: []string{}, 554 }, { 555 name: "one CIDR", 556 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 557 makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 558 makeServiceCIDR("unrelated", "10.0.0.0/24", ""), 559 makeServiceCIDR("unrelated2", "10.0.0.0/16", ""), 560 }, 561 cidr: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 562 want: []string{defaultservicecidr.DefaultServiceCIDRName}, 563 }, { 564 name: "two equal CIDR", 565 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 566 makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 567 makeServiceCIDR("overlapping", "192.168.0.0/24", "2001:db2::/96"), 568 makeServiceCIDR("unrelated", "10.0.0.0/24", ""), 569 makeServiceCIDR("unrelated2", "10.0.0.0/16", ""), 570 }, 571 cidr: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 572 want: []string{defaultservicecidr.DefaultServiceCIDRName, "overlapping"}, 573 }, { 574 name: "three CIDR - two same and one larger", 575 cidrs: []*networkingapiv1alpha1.ServiceCIDR{ 576 makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 577 makeServiceCIDR("overlapping", "192.168.0.0/24", "2001:db2::/64"), 578 makeServiceCIDR("overlapping2", "192.168.0.0/26", "2001:db2::/96"), 579 makeServiceCIDR("unrelated", "10.0.0.0/24", ""), 580 makeServiceCIDR("unrelated2", "10.0.0.0/16", ""), 581 }, 582 cidr: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), 583 want: []string{defaultservicecidr.DefaultServiceCIDRName, "overlapping", "overlapping2"}, 584 }} 585 for _, tt := range tests { 586 t.Run(tt.name, func(t *testing.T) { 587 _, controller := newController(t, tt.cidrs, nil) 588 err := controller.syncCIDRs() 589 if err != nil { 590 t.Fatal(err) 591 } 592 if got := controller.overlappingServiceCIDRs(tt.cidr); !cmp.Equal(got, tt.want, cmpopts.SortSlices(func(a, b string) bool { return a < b })) { 593 t.Errorf("Controller.cidrToCidrs() = %v, want %v", got, tt.want) 594 } 595 }) 596 } 597 }