...

Source file src/k8s.io/kubernetes/pkg/controller/nodeipam/ipam/cloud_cidr_allocator_test.go

Documentation: k8s.io/kubernetes/pkg/controller/nodeipam/ipam

     1  //go:build !providerless
     2  // +build !providerless
     3  
     4  /*
     5  Copyright 2018 The Kubernetes Authors.
     6  
     7  Licensed under the Apache License, Version 2.0 (the "License");
     8  you may not use this file except in compliance with the License.
     9  You may obtain a copy of the License at
    10  
    11      http://www.apache.org/licenses/LICENSE-2.0
    12  
    13  Unless required by applicable law or agreed to in writing, software
    14  distributed under the License is distributed on an "AS IS" BASIS,
    15  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16  See the License for the specific language governing permissions and
    17  limitations under the License.
    18  */
    19  
    20  package ipam
    21  
    22  import (
    23  	"fmt"
    24  	"testing"
    25  	"time"
    26  
    27  	v1 "k8s.io/api/core/v1"
    28  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    29  	"k8s.io/client-go/informers"
    30  	"k8s.io/client-go/kubernetes/fake"
    31  	"k8s.io/klog/v2/ktesting"
    32  	netutils "k8s.io/utils/net"
    33  )
    34  
    35  func hasNodeInProcessing(ca *cloudCIDRAllocator, name string) bool {
    36  	ca.lock.Lock()
    37  	defer ca.lock.Unlock()
    38  
    39  	_, found := ca.nodesInProcessing[name]
    40  	return found
    41  }
    42  
    43  func TestBoundedRetries(t *testing.T) {
    44  	clientSet := fake.NewSimpleClientset()
    45  	updateChan := make(chan string, 1) // need to buffer as we are using only on go routine
    46  	sharedInfomer := informers.NewSharedInformerFactory(clientSet, 1*time.Hour)
    47  	ca := &cloudCIDRAllocator{
    48  		client:            clientSet,
    49  		nodeUpdateChannel: updateChan,
    50  		nodeLister:        sharedInfomer.Core().V1().Nodes().Lister(),
    51  		nodesSynced:       sharedInfomer.Core().V1().Nodes().Informer().HasSynced,
    52  		nodesInProcessing: map[string]*nodeProcessingInfo{},
    53  	}
    54  	logger, ctx := ktesting.NewTestContext(t)
    55  	go ca.worker(ctx)
    56  	nodeName := "testNode"
    57  	ca.AllocateOrOccupyCIDR(logger, &v1.Node{
    58  		ObjectMeta: metav1.ObjectMeta{
    59  			Name: nodeName,
    60  		},
    61  	})
    62  	for hasNodeInProcessing(ca, nodeName) {
    63  		// wait for node to finish processing (should terminate and not time out)
    64  	}
    65  }
    66  
    67  func withinExpectedRange(got time.Duration, expected time.Duration) bool {
    68  	return got >= expected/2 && got <= 3*expected/2
    69  }
    70  
    71  func TestNodeUpdateRetryTimeout(t *testing.T) {
    72  	for _, tc := range []struct {
    73  		count int
    74  		want  time.Duration
    75  	}{
    76  		{count: 0, want: 250 * time.Millisecond},
    77  		{count: 1, want: 500 * time.Millisecond},
    78  		{count: 2, want: 1000 * time.Millisecond},
    79  		{count: 3, want: 2000 * time.Millisecond},
    80  		{count: 50, want: 5000 * time.Millisecond},
    81  	} {
    82  		t.Run(fmt.Sprintf("count %d", tc.count), func(t *testing.T) {
    83  			if got := nodeUpdateRetryTimeout(tc.count); !withinExpectedRange(got, tc.want) {
    84  				t.Errorf("nodeUpdateRetryTimeout(tc.count) = %v; want %v", got, tc.want)
    85  			}
    86  		})
    87  	}
    88  }
    89  
    90  func TestNeedPodCIDRsUpdate(t *testing.T) {
    91  	for _, tc := range []struct {
    92  		desc         string
    93  		cidrs        []string
    94  		nodePodCIDR  string
    95  		nodePodCIDRs []string
    96  		want         bool
    97  		wantErr      bool
    98  	}{
    99  		{
   100  			desc:         "want error - invalid cidr",
   101  			cidrs:        []string{"10.10.10.0/24"},
   102  			nodePodCIDR:  "10.10..0/24",
   103  			nodePodCIDRs: []string{"10.10..0/24"},
   104  			want:         true,
   105  		},
   106  		{
   107  			desc:         "want error - cidr len 2 but not dual stack",
   108  			cidrs:        []string{"10.10.10.0/24", "10.10.11.0/24"},
   109  			nodePodCIDR:  "10.10.10.0/24",
   110  			nodePodCIDRs: []string{"10.10.10.0/24", "2001:db8::/64"},
   111  			wantErr:      true,
   112  		},
   113  		{
   114  			desc:         "want false - matching v4 only cidr",
   115  			cidrs:        []string{"10.10.10.0/24"},
   116  			nodePodCIDR:  "10.10.10.0/24",
   117  			nodePodCIDRs: []string{"10.10.10.0/24"},
   118  			want:         false,
   119  		},
   120  		{
   121  			desc:  "want false - nil node.Spec.PodCIDR",
   122  			cidrs: []string{"10.10.10.0/24"},
   123  			want:  true,
   124  		},
   125  		{
   126  			desc:         "want true - non matching v4 only cidr",
   127  			cidrs:        []string{"10.10.10.0/24"},
   128  			nodePodCIDR:  "10.10.11.0/24",
   129  			nodePodCIDRs: []string{"10.10.11.0/24"},
   130  			want:         true,
   131  		},
   132  		{
   133  			desc:         "want false - matching v4 and v6 cidrs",
   134  			cidrs:        []string{"10.10.10.0/24", "2001:db8::/64"},
   135  			nodePodCIDR:  "10.10.10.0/24",
   136  			nodePodCIDRs: []string{"10.10.10.0/24", "2001:db8::/64"},
   137  			want:         false,
   138  		},
   139  		{
   140  			desc:         "want false - matching v4 and v6 cidrs, different strings but same CIDRs",
   141  			cidrs:        []string{"10.10.10.0/24", "2001:db8::/64"},
   142  			nodePodCIDR:  "10.10.10.0/24",
   143  			nodePodCIDRs: []string{"10.10.10.0/24", "2001:db8:0::/64"},
   144  			want:         false,
   145  		},
   146  		{
   147  			desc:         "want true - matching v4 and non matching v6 cidrs",
   148  			cidrs:        []string{"10.10.10.0/24", "2001:db8::/64"},
   149  			nodePodCIDR:  "10.10.10.0/24",
   150  			nodePodCIDRs: []string{"10.10.10.0/24", "2001:dba::/64"},
   151  			want:         true,
   152  		},
   153  		{
   154  			desc:  "want true - nil node.Spec.PodCIDRs",
   155  			cidrs: []string{"10.10.10.0/24", "2001:db8::/64"},
   156  			want:  true,
   157  		},
   158  		{
   159  			desc:         "want true - matching v6 and non matching v4 cidrs",
   160  			cidrs:        []string{"10.10.10.0/24", "2001:db8::/64"},
   161  			nodePodCIDR:  "10.10.1.0/24",
   162  			nodePodCIDRs: []string{"10.10.1.0/24", "2001:db8::/64"},
   163  			want:         true,
   164  		},
   165  		{
   166  			desc:         "want true - missing v6",
   167  			cidrs:        []string{"10.10.10.0/24", "2001:db8::/64"},
   168  			nodePodCIDR:  "10.10.10.0/24",
   169  			nodePodCIDRs: []string{"10.10.10.0/24"},
   170  			want:         true,
   171  		},
   172  	} {
   173  		var node v1.Node
   174  		node.Spec.PodCIDR = tc.nodePodCIDR
   175  		node.Spec.PodCIDRs = tc.nodePodCIDRs
   176  		netCIDRs, err := netutils.ParseCIDRs(tc.cidrs)
   177  		if err != nil {
   178  			t.Errorf("failed to parse %v as CIDRs: %v", tc.cidrs, err)
   179  		}
   180  		logger, _ := ktesting.NewTestContext(t)
   181  		t.Run(tc.desc, func(t *testing.T) {
   182  			got, err := needPodCIDRsUpdate(logger, &node, netCIDRs)
   183  			if tc.wantErr == (err == nil) {
   184  				t.Errorf("err: %v, wantErr: %v", err, tc.wantErr)
   185  			}
   186  			if err == nil && got != tc.want {
   187  				t.Errorf("got: %v, want: %v", got, tc.want)
   188  			}
   189  		})
   190  	}
   191  }
   192  

View as plain text