/* Copyright 2023 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package servicecidrs import ( "context" "testing" "time" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" v1 "k8s.io/api/core/v1" networkingapiv1alpha1 "k8s.io/api/networking/v1alpha1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes/fake" k8stesting "k8s.io/client-go/testing" "k8s.io/client-go/tools/cache" "k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controlplane/controller/defaultservicecidr" "k8s.io/kubernetes/pkg/registry/core/service/ipallocator" "k8s.io/kubernetes/test/utils/ktesting" netutils "k8s.io/utils/net" "k8s.io/utils/ptr" ) type testController struct { *Controller servicecidrsStore cache.Store ipaddressesStore cache.Store } func newController(ctx context.Context, t *testing.T, cidrs []*networkingapiv1alpha1.ServiceCIDR, ips []*networkingapiv1alpha1.IPAddress) (*fake.Clientset, *testController) { client := fake.NewSimpleClientset() informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc()) serviceCIDRInformer := informerFactory.Networking().V1alpha1().ServiceCIDRs() cidrStore := serviceCIDRInformer.Informer().GetStore() for _, obj := range cidrs { err := cidrStore.Add(obj) if err != nil { t.Fatal(err) } } ipAddressInformer := informerFactory.Networking().V1alpha1().IPAddresses() ipStore := ipAddressInformer.Informer().GetStore() for _, obj := range ips { err := ipStore.Add(obj) if err != nil { t.Fatal(err) } } controller := NewController( ctx, serviceCIDRInformer, ipAddressInformer, client) var alwaysReady = func() bool { return true } controller.serviceCIDRsSynced = alwaysReady controller.ipAddressSynced = alwaysReady return client, &testController{ controller, cidrStore, ipStore, } } func TestControllerSync(t *testing.T) { now := time.Now() // ServiceCIDR that is just being deleted deletingServiceCIDR := makeServiceCIDR("deleting-cidr", "192.168.0.0/24", "2001:db2::/64") deletingServiceCIDR.Finalizers = []string{ServiceCIDRProtectionFinalizer} deletingServiceCIDR.DeletionTimestamp = ptr.To[metav1.Time](metav1.Now()) // ServiceCIDR that has been deleted for longer than the deletionGracePeriod deletedServiceCIDR := makeServiceCIDR("deleted-cidr", "192.168.0.0/24", "2001:db2::/64") deletedServiceCIDR.Finalizers = []string{ServiceCIDRProtectionFinalizer} deletedServiceCIDR.DeletionTimestamp = ptr.To[metav1.Time](metav1.NewTime(now.Add(-deletionGracePeriod - 1*time.Second))) testCases := []struct { name string cidrs []*networkingapiv1alpha1.ServiceCIDR ips []*networkingapiv1alpha1.IPAddress cidrSynced string actions [][]string // verb and resource and subresource }{ { name: "no existing service CIDRs", }, { name: "default service CIDR must have finalizer", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), }, cidrSynced: defaultservicecidr.DefaultServiceCIDRName, actions: [][]string{{"patch", "servicecidrs", ""}, {"patch", "servicecidrs", "status"}}, }, { name: "service CIDR must have finalizer", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ makeServiceCIDR("no-finalizer", "192.168.0.0/24", "2001:db2::/64"), }, cidrSynced: "no-finalizer", actions: [][]string{{"patch", "servicecidrs", ""}, {"patch", "servicecidrs", "status"}}, }, { name: "service CIDR being deleted must remove the finalizer", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ deletedServiceCIDR, }, cidrSynced: deletedServiceCIDR.Name, actions: [][]string{{"patch", "servicecidrs", ""}}, }, { name: "service CIDR being deleted but within the grace period must be requeued not remove the finalizer", // TODO: assert is actually requeued cidrs: []*networkingapiv1alpha1.ServiceCIDR{ deletingServiceCIDR, }, cidrSynced: deletingServiceCIDR.Name, actions: [][]string{}, }, { name: "service CIDR being deleted with IPv4 addresses should update the status", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ deletedServiceCIDR, }, ips: []*networkingapiv1alpha1.IPAddress{ makeIPAddress("192.168.0.1"), }, cidrSynced: deletedServiceCIDR.Name, actions: [][]string{{"patch", "servicecidrs", "status"}}, }, { name: "service CIDR being deleted and overlapping same range and IPv4 addresses should remove the finalizer", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ deletedServiceCIDR, makeServiceCIDR("overlapping", "192.168.0.0/24", "2001:db2::/64"), }, ips: []*networkingapiv1alpha1.IPAddress{ makeIPAddress("192.168.0.1"), }, cidrSynced: deletedServiceCIDR.Name, actions: [][]string{{"patch", "servicecidrs", ""}}, }, { name: "service CIDR being deleted and overlapping and IPv4 addresses should remove the finalizer", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ deletedServiceCIDR, makeServiceCIDR("overlapping", "192.168.0.0/16", "2001:db2::/64"), }, ips: []*networkingapiv1alpha1.IPAddress{ makeIPAddress("192.168.0.1"), }, cidrSynced: deletedServiceCIDR.Name, actions: [][]string{{"patch", "servicecidrs", ""}}, }, { name: "service CIDR being deleted and not overlapping and IPv4 addresses should update the status", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ deletedServiceCIDR, makeServiceCIDR("overlapping", "192.168.255.0/26", "2001:db2::/64"), }, ips: []*networkingapiv1alpha1.IPAddress{ makeIPAddress("192.168.0.1"), }, cidrSynced: deletedServiceCIDR.Name, actions: [][]string{{"patch", "servicecidrs", "status"}}, }, { name: "service CIDR being deleted with IPv6 addresses should update the status", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ deletedServiceCIDR, }, ips: []*networkingapiv1alpha1.IPAddress{ makeIPAddress("2001:db2::1"), }, cidrSynced: deletedServiceCIDR.Name, actions: [][]string{{"patch", "servicecidrs", "status"}}, }, { name: "service CIDR being deleted and overlapping same range and IPv6 addresses should remove the finalizer", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ deletedServiceCIDR, makeServiceCIDR("overlapping", "192.168.0.0/24", "2001:db2::/64"), }, ips: []*networkingapiv1alpha1.IPAddress{ makeIPAddress("2001:db2::1"), }, cidrSynced: deletedServiceCIDR.Name, actions: [][]string{{"patch", "servicecidrs", ""}}, }, { name: "service CIDR being deleted and overlapping and IPv6 addresses should remove the finalizer", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ deletedServiceCIDR, makeServiceCIDR("overlapping", "192.168.0.0/16", "2001:db2::/48"), }, ips: []*networkingapiv1alpha1.IPAddress{ makeIPAddress("2001:db2::1"), }, cidrSynced: deletedServiceCIDR.Name, actions: [][]string{{"patch", "servicecidrs", ""}}, }, { name: "service CIDR being deleted and not overlapping and IPv6 addresses should update the status", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ deletedServiceCIDR, makeServiceCIDR("overlapping", "192.168.255.0/26", "2001:db2:a:b::/64"), }, ips: []*networkingapiv1alpha1.IPAddress{ makeIPAddress("2001:db2::1"), }, cidrSynced: deletedServiceCIDR.Name, actions: [][]string{{"patch", "servicecidrs", "status"}}, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { tCtx := ktesting.Init(t) client, controller := newController(tCtx, t, tc.cidrs, tc.ips) // server side apply does not play well with fake client go // so we skup the errors and only assert on the actions // https://github.com/kubernetes/kubernetes/issues/99953 _ = controller.sync(tCtx, tc.cidrSynced) expectAction(t, client.Actions(), tc.actions) }) } } func makeServiceCIDR(name, primary, secondary string) *networkingapiv1alpha1.ServiceCIDR { serviceCIDR := &networkingapiv1alpha1.ServiceCIDR{ ObjectMeta: metav1.ObjectMeta{ Name: name, }, Spec: networkingapiv1alpha1.ServiceCIDRSpec{}, } serviceCIDR.Spec.CIDRs = append(serviceCIDR.Spec.CIDRs, primary) if secondary != "" { serviceCIDR.Spec.CIDRs = append(serviceCIDR.Spec.CIDRs, secondary) } return serviceCIDR } func makeIPAddress(name string) *networkingapiv1alpha1.IPAddress { family := string(v1.IPv4Protocol) if netutils.IsIPv6String(name) { family = string(v1.IPv6Protocol) } return &networkingapiv1alpha1.IPAddress{ ObjectMeta: metav1.ObjectMeta{ Name: name, Labels: map[string]string{ networkingapiv1alpha1.LabelIPAddressFamily: family, networkingapiv1alpha1.LabelManagedBy: ipallocator.ControllerName, }, }, } } func expectAction(t *testing.T, actions []k8stesting.Action, expected [][]string) { t.Helper() if len(actions) != len(expected) { t.Fatalf("Expected at least %d actions, got %d \ndiff: %v", len(expected), len(actions), cmp.Diff(expected, actions)) } for i, action := range actions { verb := expected[i][0] if action.GetVerb() != verb { t.Errorf("Expected action %d verb to be %s, got %s", i, verb, action.GetVerb()) } resource := expected[i][1] if action.GetResource().Resource != resource { t.Errorf("Expected action %d resource to be %s, got %s", i, resource, action.GetResource().Resource) } subresource := expected[i][2] if action.GetSubresource() != subresource { t.Errorf("Expected action %d subresource to be %s, got %s", i, subresource, action.GetSubresource()) } } } func TestController_canDeleteCIDR(t *testing.T) { tests := []struct { name string cidrs []*networkingapiv1alpha1.ServiceCIDR ips []*networkingapiv1alpha1.IPAddress cidrSynced *networkingapiv1alpha1.ServiceCIDR want bool }{ { name: "empty", cidrSynced: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), want: true, }, { name: "CIDR and no IPs", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), }, cidrSynced: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), want: true, }, { name: "CIDR with IPs", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), }, ips: []*networkingapiv1alpha1.IPAddress{ makeIPAddress("192.168.0.24"), }, cidrSynced: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), want: false, }, { name: "CIDR without IPs", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), }, ips: []*networkingapiv1alpha1.IPAddress{ makeIPAddress("192.168.1.24"), }, cidrSynced: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), want: true, }, { name: "CIDR with IPv4 address referencing the subnet address", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), }, ips: []*networkingapiv1alpha1.IPAddress{ makeIPAddress("192.168.0.0"), }, cidrSynced: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), want: true, }, { name: "CIDR with IPv4 address referencing the broadcast address", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), }, ips: []*networkingapiv1alpha1.IPAddress{ makeIPAddress("192.168.0.255"), }, cidrSynced: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), want: true, }, { name: "CIDR with IPv6 address referencing the broadcast address", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), }, ips: []*networkingapiv1alpha1.IPAddress{ makeIPAddress("2001:0db2::ffff:ffff:ffff:ffff"), }, cidrSynced: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), want: false, }, { name: "CIDR with same range overlapping and IPs", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), makeServiceCIDR("overlapping", "192.168.0.0/24", "2001:db2::/64"), }, ips: []*networkingapiv1alpha1.IPAddress{ makeIPAddress("192.168.0.23"), }, cidrSynced: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), want: true, }, { name: "CIDR with smaller range overlapping and IPs", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), makeServiceCIDR("overlapping", "192.168.0.0/26", "2001:db2::/64"), }, ips: []*networkingapiv1alpha1.IPAddress{ makeIPAddress("192.168.0.23"), }, cidrSynced: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), want: true, }, { name: "CIDR with smaller range overlapping but IPs orphan", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), makeServiceCIDR("overlapping", "192.168.0.0/28", "2001:db2::/64"), }, ips: []*networkingapiv1alpha1.IPAddress{ makeIPAddress("192.168.0.23"), }, cidrSynced: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), want: false, }, { name: "CIDR with larger range overlapping and IPs", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), makeServiceCIDR("overlapping", "192.168.0.0/16", "2001:db2::/64"), }, ips: []*networkingapiv1alpha1.IPAddress{ makeIPAddress("192.168.0.23"), }, cidrSynced: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), want: true, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { tCtx := ktesting.Init(t) _, controller := newController(tCtx, t, tc.cidrs, tc.ips) err := controller.syncCIDRs() if err != nil { t.Fatal(err) } got, err := controller.canDeleteCIDR(tCtx, tc.cidrSynced) if err != nil { t.Fatal(err) } if got != tc.want { t.Errorf("Controller.canDeleteCIDR() = %v, want %v", got, tc.want) } }) } } func TestController_ipToCidrs(t *testing.T) { tests := []struct { name string cidrs []*networkingapiv1alpha1.ServiceCIDR ip *networkingapiv1alpha1.IPAddress want []string }{ { name: "empty", ip: makeIPAddress("192.168.0.23"), want: []string{}, }, { name: "one CIDR", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), makeServiceCIDR("unrelated", "10.0.0.0/24", ""), makeServiceCIDR("unrelated2", "10.0.0.0/16", ""), }, ip: makeIPAddress("192.168.0.23"), want: []string{defaultservicecidr.DefaultServiceCIDRName}, }, { name: "two equal CIDR", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), makeServiceCIDR("overlapping", "192.168.0.0/24", "2001:db2::/96"), makeServiceCIDR("unrelated", "10.0.0.0/24", ""), makeServiceCIDR("unrelated2", "10.0.0.0/16", ""), }, ip: makeIPAddress("192.168.0.23"), want: []string{defaultservicecidr.DefaultServiceCIDRName, "overlapping"}, }, { name: "three CIDR - two same and one larger", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), makeServiceCIDR("overlapping", "192.168.0.0/24", "2001:db2::/64"), makeServiceCIDR("overlapping2", "192.168.0.0/26", "2001:db2::/96"), makeServiceCIDR("unrelated", "10.0.0.0/24", ""), makeServiceCIDR("unrelated2", "10.0.0.0/16", ""), }, ip: makeIPAddress("192.168.0.23"), want: []string{defaultservicecidr.DefaultServiceCIDRName, "overlapping", "overlapping2"}, }, { name: "three CIDR - two same and one larger - IPv4 subnet address", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), makeServiceCIDR("overlapping", "192.168.0.0/24", "2001:db2::/64"), makeServiceCIDR("overlapping2", "192.168.0.0/26", "2001:db2::/96"), makeServiceCIDR("unrelated", "10.0.0.0/24", ""), makeServiceCIDR("unrelated2", "10.0.0.0/16", ""), }, ip: makeIPAddress("192.168.0.0"), want: []string{}, }, { name: "three CIDR - two same and one larger - IPv4 broadcast address", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), makeServiceCIDR("overlapping", "192.168.0.0/24", "2001:db2::/64"), makeServiceCIDR("overlapping2", "192.168.0.0/26", "2001:db2::/96"), makeServiceCIDR("unrelated", "10.0.0.0/24", ""), makeServiceCIDR("unrelated2", "10.0.0.0/16", ""), }, ip: makeIPAddress("192.168.0.63"), // broadcast for 192.168.0.0/26 want: []string{defaultservicecidr.DefaultServiceCIDRName, "overlapping"}, }, { name: "three CIDR - two same and one larger - IPv6 subnet address", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), makeServiceCIDR("overlapping", "192.168.0.0/24", "2001:db2::/64"), makeServiceCIDR("overlapping2", "192.168.0.0/26", "2001:db2::/96"), makeServiceCIDR("unrelated", "10.0.0.0/24", ""), makeServiceCIDR("unrelated2", "10.0.0.0/16", ""), }, ip: makeIPAddress("2001:db2::"), want: []string{}, }, { name: "three CIDR - two same and one larger - IPv6 broadcast address", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), makeServiceCIDR("overlapping", "192.168.0.0/24", "2001:db2::/64"), makeServiceCIDR("overlapping2", "192.168.0.0/26", "2001:db2::/96"), makeServiceCIDR("unrelated", "10.0.0.0/24", ""), makeServiceCIDR("unrelated2", "10.0.0.0/16", ""), }, ip: makeIPAddress("2001:0db2::ffff:ffff:ffff:ffff"), want: []string{defaultservicecidr.DefaultServiceCIDRName, "overlapping"}, }} for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tCtx := ktesting.Init(t) _, controller := newController(tCtx, t, tt.cidrs, nil) err := controller.syncCIDRs() if err != nil { t.Fatal(err) } if got := controller.containingServiceCIDRs(tt.ip); !cmp.Equal(got, tt.want, cmpopts.SortSlices(func(a, b string) bool { return a < b })) { t.Errorf("Controller.ipToCidrs() = %v, want %v", got, tt.want) } }) } } func TestController_cidrToCidrs(t *testing.T) { tests := []struct { name string cidrs []*networkingapiv1alpha1.ServiceCIDR cidr *networkingapiv1alpha1.ServiceCIDR want []string }{ { name: "empty", cidr: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), want: []string{}, }, { name: "one CIDR", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), makeServiceCIDR("unrelated", "10.0.0.0/24", ""), makeServiceCIDR("unrelated2", "10.0.0.0/16", ""), }, cidr: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), want: []string{defaultservicecidr.DefaultServiceCIDRName}, }, { name: "two equal CIDR", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), makeServiceCIDR("overlapping", "192.168.0.0/24", "2001:db2::/96"), makeServiceCIDR("unrelated", "10.0.0.0/24", ""), makeServiceCIDR("unrelated2", "10.0.0.0/16", ""), }, cidr: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), want: []string{defaultservicecidr.DefaultServiceCIDRName, "overlapping"}, }, { name: "three CIDR - two same and one larger", cidrs: []*networkingapiv1alpha1.ServiceCIDR{ makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), makeServiceCIDR("overlapping", "192.168.0.0/24", "2001:db2::/64"), makeServiceCIDR("overlapping2", "192.168.0.0/26", "2001:db2::/96"), makeServiceCIDR("unrelated", "10.0.0.0/24", ""), makeServiceCIDR("unrelated2", "10.0.0.0/16", ""), }, cidr: makeServiceCIDR(defaultservicecidr.DefaultServiceCIDRName, "192.168.0.0/24", "2001:db2::/64"), want: []string{defaultservicecidr.DefaultServiceCIDRName, "overlapping", "overlapping2"}, }} for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tCtx := ktesting.Init(t) _, controller := newController(tCtx, t, tt.cidrs, nil) err := controller.syncCIDRs() if err != nil { t.Fatal(err) } if got := controller.overlappingServiceCIDRs(tt.cidr); !cmp.Equal(got, tt.want, cmpopts.SortSlices(func(a, b string) bool { return a < b })) { t.Errorf("Controller.cidrToCidrs() = %v, want %v", got, tt.want) } }) } }