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