...

Source file src/k8s.io/kubernetes/pkg/controller/servicecidrs/servicecidrs_controller_test.go

Documentation: k8s.io/kubernetes/pkg/controller/servicecidrs

     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  }
   604  

View as plain text