...

Source file src/k8s.io/kubernetes/cmd/kube-apiserver/app/options/validation_test.go

Documentation: k8s.io/kubernetes/cmd/kube-apiserver/app/options

     1  /*
     2  Copyright 2019 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 options
    18  
    19  import (
    20  	"net"
    21  	"testing"
    22  
    23  	utilnet "k8s.io/apimachinery/pkg/util/net"
    24  	apiserveroptions "k8s.io/apiserver/pkg/server/options"
    25  	utilfeature "k8s.io/apiserver/pkg/util/feature"
    26  	featuregatetesting "k8s.io/component-base/featuregate/testing"
    27  	netutils "k8s.io/utils/net"
    28  
    29  	"k8s.io/kubernetes/pkg/features"
    30  )
    31  
    32  func makeOptionsWithCIDRs(serviceCIDR string, secondaryServiceCIDR string) *ServerRunOptions {
    33  	value := serviceCIDR
    34  	if len(secondaryServiceCIDR) > 0 {
    35  		value = value + "," + secondaryServiceCIDR
    36  	}
    37  
    38  	var primaryCIDR, secondaryCIDR net.IPNet
    39  	if len(serviceCIDR) > 0 {
    40  		_, cidr, _ := netutils.ParseCIDRSloppy(serviceCIDR)
    41  		if cidr != nil {
    42  			primaryCIDR = *(cidr)
    43  		}
    44  	}
    45  
    46  	if len(secondaryServiceCIDR) > 0 {
    47  		_, cidr, _ := netutils.ParseCIDRSloppy(secondaryServiceCIDR)
    48  		if cidr != nil {
    49  			secondaryCIDR = *(cidr)
    50  		}
    51  	}
    52  	return &ServerRunOptions{
    53  		Extra: Extra{
    54  			ServiceClusterIPRanges:         value,
    55  			PrimaryServiceClusterIPRange:   primaryCIDR,
    56  			SecondaryServiceClusterIPRange: secondaryCIDR,
    57  		},
    58  	}
    59  }
    60  
    61  func TestClusterServiceIPRange(t *testing.T) {
    62  	testCases := []struct {
    63  		name         string
    64  		options      *ServerRunOptions
    65  		expectErrors bool
    66  		gate         bool
    67  	}{
    68  		{
    69  			name:         "no service cidr",
    70  			expectErrors: true,
    71  			options:      makeOptionsWithCIDRs("", ""),
    72  		},
    73  		{
    74  			name:         "only secondary service cidr",
    75  			expectErrors: true,
    76  			options:      makeOptionsWithCIDRs("", "10.0.0.0/16"),
    77  		},
    78  		{
    79  			name:         "primary and secondary are provided but not dual stack v4-v4",
    80  			expectErrors: true,
    81  			options:      makeOptionsWithCIDRs("10.0.0.0/16", "11.0.0.0/16"),
    82  		},
    83  		{
    84  			name:         "primary and secondary are provided but not dual stack v6-v6",
    85  			expectErrors: true,
    86  			options:      makeOptionsWithCIDRs("2000::/108", "3000::/108"),
    87  		},
    88  		{
    89  			name:         "service cidr is too big",
    90  			expectErrors: true,
    91  			options:      makeOptionsWithCIDRs("10.0.0.0/8", ""),
    92  		},
    93  		{
    94  			name:         "service cidr IPv4 is too big but gate enbled",
    95  			expectErrors: false,
    96  			options:      makeOptionsWithCIDRs("10.0.0.0/8", ""),
    97  			gate:         true,
    98  		},
    99  		{
   100  			name:         "service cidr IPv6 is too big but gate enbled",
   101  			expectErrors: false,
   102  			options:      makeOptionsWithCIDRs("2001:db8::/64", ""),
   103  			gate:         true,
   104  		},
   105  		{
   106  			name:         "service cidr IPv6 is too big and gate enbled",
   107  			expectErrors: false,
   108  			options:      makeOptionsWithCIDRs("2001:db8::/12", ""),
   109  			gate:         true,
   110  		},
   111  		{
   112  			name:         "dual-stack secondary cidr too big",
   113  			expectErrors: true,
   114  			options:      makeOptionsWithCIDRs("10.0.0.0/16", "3000::/64"),
   115  		},
   116  		{
   117  			name:         "dual-stack secondary cidr too big gate enabled",
   118  			expectErrors: false,
   119  			options:      makeOptionsWithCIDRs("10.0.0.0/16", "3000::/48"),
   120  			gate:         true,
   121  		},
   122  		{
   123  			name:         "more than two entries",
   124  			expectErrors: true,
   125  			options:      makeOptionsWithCIDRs("10.0.0.0/16,244.0.0.0/16", "3000::/108"),
   126  		},
   127  		/* success cases */
   128  		{
   129  			name:         "valid primary",
   130  			expectErrors: false,
   131  			options:      makeOptionsWithCIDRs("10.0.0.0/16", ""),
   132  		},
   133  		{
   134  			name:         "valid primary, class E range",
   135  			expectErrors: false,
   136  			options:      makeOptionsWithCIDRs("244.0.0.0/16", ""),
   137  		},
   138  		{
   139  			name:         "valid v4-v6 dual stack",
   140  			expectErrors: false,
   141  			options:      makeOptionsWithCIDRs("10.0.0.0/16", "3000::/108"),
   142  		},
   143  		{
   144  			name:         "valid v6-v4 dual stack",
   145  			expectErrors: false,
   146  			options:      makeOptionsWithCIDRs("3000::/108", "10.0.0.0/16"),
   147  		},
   148  	}
   149  
   150  	for _, tc := range testCases {
   151  		t.Run(tc.name, func(t *testing.T) {
   152  			defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.MultiCIDRServiceAllocator, tc.gate)()
   153  
   154  			errs := validateClusterIPFlags(tc.options.Extra)
   155  			if len(errs) > 0 && !tc.expectErrors {
   156  				t.Errorf("expected no errors, errors found %+v", errs)
   157  			}
   158  
   159  			if len(errs) == 0 && tc.expectErrors {
   160  				t.Errorf("expected errors, no errors found")
   161  			}
   162  		})
   163  	}
   164  }
   165  
   166  func TestValidatePublicIPServiceClusterIPRangeIPFamilies(t *testing.T) {
   167  	_, ipv4cidr, err := netutils.ParseCIDRSloppy("192.168.0.0/24")
   168  	if err != nil {
   169  		t.Fatalf("Unexpected error %v", err)
   170  	}
   171  
   172  	_, ipv6cidr, err := netutils.ParseCIDRSloppy("2001:db8::/112")
   173  	if err != nil {
   174  		t.Fatalf("Unexpected error %v", err)
   175  	}
   176  
   177  	ipv4address := netutils.ParseIPSloppy("192.168.1.1")
   178  	ipv6address := netutils.ParseIPSloppy("2001:db8::1")
   179  
   180  	tests := []struct {
   181  		name    string
   182  		generic apiserveroptions.ServerRunOptions
   183  		extra   Extra
   184  		wantErr bool
   185  	}{
   186  		{
   187  			name: "master endpoint reconciler - IPv4 families",
   188  			extra: Extra{
   189  				EndpointReconcilerType:       "master-count",
   190  				PrimaryServiceClusterIPRange: *ipv4cidr,
   191  			},
   192  			generic: apiserveroptions.ServerRunOptions{
   193  				AdvertiseAddress: ipv4address,
   194  			},
   195  			wantErr: false,
   196  		},
   197  		{
   198  			name: "master endpoint reconciler - IPv6 families",
   199  			extra: Extra{
   200  				EndpointReconcilerType:       "master-count",
   201  				PrimaryServiceClusterIPRange: *ipv6cidr,
   202  			},
   203  			generic: apiserveroptions.ServerRunOptions{
   204  				AdvertiseAddress: ipv6address,
   205  			},
   206  			wantErr: false,
   207  		},
   208  		{
   209  			name: "master endpoint reconciler - wrong IP families",
   210  			extra: Extra{
   211  				EndpointReconcilerType:       "master-count",
   212  				PrimaryServiceClusterIPRange: *ipv4cidr,
   213  			},
   214  			generic: apiserveroptions.ServerRunOptions{
   215  				AdvertiseAddress: ipv6address,
   216  			},
   217  			wantErr: true,
   218  		},
   219  		{
   220  			name: "master endpoint reconciler - wrong IP families",
   221  			extra: Extra{
   222  				EndpointReconcilerType:       "master-count",
   223  				PrimaryServiceClusterIPRange: *ipv6cidr,
   224  			},
   225  			generic: apiserveroptions.ServerRunOptions{
   226  				AdvertiseAddress: ipv4address,
   227  			},
   228  			wantErr: true,
   229  		},
   230  		{
   231  			name: "lease endpoint reconciler - IPv4 families",
   232  			extra: Extra{
   233  				EndpointReconcilerType:       "lease",
   234  				PrimaryServiceClusterIPRange: *ipv4cidr,
   235  			},
   236  			generic: apiserveroptions.ServerRunOptions{
   237  				AdvertiseAddress: ipv4address,
   238  			},
   239  			wantErr: false,
   240  		},
   241  		{
   242  			name: "lease endpoint reconciler - IPv6 families",
   243  			extra: Extra{
   244  				EndpointReconcilerType:       "lease",
   245  				PrimaryServiceClusterIPRange: *ipv6cidr,
   246  			},
   247  			generic: apiserveroptions.ServerRunOptions{
   248  				AdvertiseAddress: ipv6address,
   249  			},
   250  			wantErr: false,
   251  		},
   252  		{
   253  			name: "lease endpoint reconciler - wrong IP families",
   254  			extra: Extra{
   255  				EndpointReconcilerType:       "lease",
   256  				PrimaryServiceClusterIPRange: *ipv4cidr,
   257  			},
   258  			generic: apiserveroptions.ServerRunOptions{
   259  				AdvertiseAddress: ipv6address,
   260  			},
   261  			wantErr: true,
   262  		},
   263  		{
   264  			name: "lease endpoint reconciler - wrong IP families",
   265  			extra: Extra{
   266  				EndpointReconcilerType:       "lease",
   267  				PrimaryServiceClusterIPRange: *ipv6cidr,
   268  			},
   269  			generic: apiserveroptions.ServerRunOptions{
   270  				AdvertiseAddress: ipv4address,
   271  			},
   272  			wantErr: true,
   273  		},
   274  		{
   275  			name: "none endpoint reconciler - wrong IP families",
   276  			extra: Extra{
   277  				EndpointReconcilerType:       "none",
   278  				PrimaryServiceClusterIPRange: *ipv4cidr,
   279  			},
   280  			generic: apiserveroptions.ServerRunOptions{
   281  				AdvertiseAddress: ipv6address,
   282  			},
   283  			wantErr: false,
   284  		},
   285  	}
   286  	for _, tt := range tests {
   287  		t.Run(tt.name, func(t *testing.T) {
   288  			errs := validatePublicIPServiceClusterIPRangeIPFamilies(tt.extra, tt.generic)
   289  			if (len(errs) > 0) != tt.wantErr {
   290  				t.Fatalf("completedConfig.New() errors = %+v, wantErr %v", errs, tt.wantErr)
   291  			}
   292  		})
   293  	}
   294  }
   295  
   296  func getIPnetFromCIDR(cidr string) *net.IPNet {
   297  	_, ipnet, _ := netutils.ParseCIDRSloppy(cidr)
   298  	return ipnet
   299  }
   300  
   301  func TestValidateServiceNodePort(t *testing.T) {
   302  	testCases := []struct {
   303  		name         string
   304  		options      *ServerRunOptions
   305  		expectErrors bool
   306  	}{
   307  		{
   308  			name:         "validate port less than 0",
   309  			options:      makeOptionsWithPort(-1, 30065, 1),
   310  			expectErrors: true,
   311  		},
   312  		{
   313  			name:         "validate port more than 65535",
   314  			options:      makeOptionsWithPort(65536, 30065, 1),
   315  			expectErrors: true,
   316  		},
   317  		{
   318  			name:         "validate port equal 0",
   319  			options:      makeOptionsWithPort(0, 0, 1),
   320  			expectErrors: true,
   321  		},
   322  		{
   323  			name:         "validate port less than base",
   324  			options:      makeOptionsWithPort(30064, 30065, 1),
   325  			expectErrors: true,
   326  		},
   327  		{
   328  			name:         "validate port minus base more than size",
   329  			options:      makeOptionsWithPort(30067, 30065, 1),
   330  			expectErrors: true,
   331  		},
   332  		{
   333  			name:         "validate success",
   334  			options:      makeOptionsWithPort(30067, 30065, 5),
   335  			expectErrors: false,
   336  		},
   337  	}
   338  
   339  	for _, tc := range testCases {
   340  		t.Run(tc.name, func(t *testing.T) {
   341  			errs := validateServiceNodePort(tc.options.Extra)
   342  			if errs != nil && !tc.expectErrors {
   343  				t.Errorf("expected no errors, error found %+v", errs)
   344  			}
   345  		})
   346  	}
   347  }
   348  
   349  func makeOptionsWithPort(kubernetesServiceNodePort int, base int, size int) *ServerRunOptions {
   350  	var portRange = utilnet.PortRange{
   351  		Base: base,
   352  		Size: size,
   353  	}
   354  	return &ServerRunOptions{
   355  		Extra: Extra{
   356  			ServiceNodePortRange:      portRange,
   357  			KubernetesServiceNodePort: kubernetesServiceNodePort,
   358  		},
   359  	}
   360  }
   361  
   362  func TestValidateMaxCIDRRange(t *testing.T) {
   363  	testCases := []struct {
   364  		// tc.cidr, tc.maxCIDRBits, tc.cidrFlag) tc.expectedErrorMessage
   365  		name                 string
   366  		cidr                 net.IPNet
   367  		maxCIDRBits          int
   368  		cidrFlag             string
   369  		expectedErrorMessage string
   370  		expectErrors         bool
   371  	}{
   372  		{
   373  			name:                 "valid ipv4 cidr",
   374  			cidr:                 *getIPnetFromCIDR("10.92.0.0/12"),
   375  			maxCIDRBits:          20,
   376  			cidrFlag:             "--service-cluster-ip-range",
   377  			expectedErrorMessage: "",
   378  			expectErrors:         false,
   379  		},
   380  		{
   381  			name:                 "valid ipv6 cidr",
   382  			cidr:                 *getIPnetFromCIDR("3000::/108"),
   383  			maxCIDRBits:          20,
   384  			cidrFlag:             "--service-cluster-ip-range",
   385  			expectedErrorMessage: "",
   386  			expectErrors:         false,
   387  		},
   388  		{
   389  			name:                 "ipv4 cidr too big",
   390  			cidr:                 *getIPnetFromCIDR("10.92.0.0/8"),
   391  			maxCIDRBits:          20,
   392  			cidrFlag:             "--service-cluster-ip-range",
   393  			expectedErrorMessage: "specified --service-cluster-ip-range is too large; for 32-bit addresses, the mask must be >= 12",
   394  			expectErrors:         true,
   395  		},
   396  		{
   397  			name:                 "ipv6 cidr too big",
   398  			cidr:                 *getIPnetFromCIDR("3000::/64"),
   399  			maxCIDRBits:          20,
   400  			cidrFlag:             "--service-cluster-ip-range",
   401  			expectedErrorMessage: "specified --service-cluster-ip-range is too large; for 128-bit addresses, the mask must be >= 108",
   402  			expectErrors:         true,
   403  		},
   404  	}
   405  
   406  	for _, tc := range testCases {
   407  		t.Run(tc.name, func(t *testing.T) {
   408  			err := validateMaxCIDRRange(tc.cidr, tc.maxCIDRBits, tc.cidrFlag)
   409  			if err != nil && !tc.expectErrors {
   410  				t.Errorf("expected no errors, error found %+v", err)
   411  			}
   412  
   413  			if err == nil && tc.expectErrors {
   414  				t.Errorf("expected errors, no errors found")
   415  			}
   416  
   417  			if err != nil && tc.expectErrors && err.Error() != tc.expectedErrorMessage {
   418  				t.Errorf("Expected error message: \"%s\"\nGot: \"%s\"", tc.expectedErrorMessage, err.Error())
   419  			}
   420  		})
   421  	}
   422  }
   423  

View as plain text