...

Source file src/k8s.io/kubernetes/cmd/kubeadm/app/features/features_test.go

Documentation: k8s.io/kubernetes/cmd/kubeadm/app/features

     1  /*
     2  Copyright 2017 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 features
    18  
    19  import (
    20  	"reflect"
    21  	"testing"
    22  
    23  	"k8s.io/apimachinery/pkg/util/version"
    24  	"k8s.io/component-base/featuregate"
    25  )
    26  
    27  func TestKnownFeatures(t *testing.T) {
    28  	var someFeatures = FeatureList{
    29  		"feature2": {FeatureSpec: featuregate.FeatureSpec{Default: true, PreRelease: featuregate.Alpha}},
    30  		"feature1": {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.Beta}},
    31  		"feature3": {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.GA}},
    32  		"hidden":   {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.GA}, HiddenInHelpText: true},
    33  	}
    34  
    35  	r := KnownFeatures(&someFeatures)
    36  
    37  	if len(r) != 3 {
    38  		t.Errorf("KnownFeatures returned %d values, expected 3", len(r))
    39  	}
    40  
    41  	// check the first value is feature1 (the list should be sorted); prerelease and default should be present
    42  	f1 := "feature1=true|false (BETA - default=false)"
    43  	if r[0] != f1 {
    44  		t.Errorf("KnownFeatures returned %s values, expected %s", r[0], f1)
    45  	}
    46  	// check the second value is feature2; prerelease and default should be present
    47  	f2 := "feature2=true|false (ALPHA - default=true)"
    48  	if r[1] != f2 {
    49  		t.Errorf("KnownFeatures returned %s values, expected %s", r[1], f2)
    50  	}
    51  	// check the second value is feature3; prerelease should not be shown for GA features; default should be present
    52  	f3 := "feature3=true|false (default=false)"
    53  	if r[2] != f3 {
    54  		t.Errorf("KnownFeatures returned %s values, expected %s", r[2], f3)
    55  	}
    56  }
    57  
    58  func TestNewFeatureGate(t *testing.T) {
    59  	var someFeatures = FeatureList{
    60  		"feature1":   {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.Beta}},
    61  		"feature2":   {FeatureSpec: featuregate.FeatureSpec{Default: true, PreRelease: featuregate.Alpha}},
    62  		"deprecated": {FeatureSpec: featuregate.FeatureSpec{Default: true, PreRelease: featuregate.Deprecated}},
    63  	}
    64  
    65  	var tests = []struct {
    66  		value                string
    67  		expectedError        bool
    68  		expectedFeaturesGate map[string]bool
    69  	}{
    70  		{ //invalid value (missing =)
    71  			value:         "invalidValue",
    72  			expectedError: true,
    73  		},
    74  		{ //invalid value (missing =)
    75  			value:         "feature1=true,invalidValue",
    76  			expectedError: true,
    77  		},
    78  		{ //invalid value (not a boolean)
    79  			value:         "feature1=notABoolean",
    80  			expectedError: true,
    81  		},
    82  		{ //invalid value (not a boolean)
    83  			value:         "feature1=true,feature2=notABoolean",
    84  			expectedError: true,
    85  		},
    86  		{ //unrecognized feature-gate key
    87  			value:         "unknownFeature=false",
    88  			expectedError: true,
    89  		},
    90  		{ //unrecognized feature-gate key
    91  			value:         "feature1=true,unknownFeature=false",
    92  			expectedError: true,
    93  		},
    94  		{ //deprecated feature-gate key
    95  			value:                "deprecated=true",
    96  			expectedError:        false,
    97  			expectedFeaturesGate: map[string]bool{"deprecated": true},
    98  		},
    99  		{ //one feature
   100  			value:                "feature1=true",
   101  			expectedError:        false,
   102  			expectedFeaturesGate: map[string]bool{"feature1": true},
   103  		},
   104  		{ //two features
   105  			value:                "feature1=true,feature2=false",
   106  			expectedError:        false,
   107  			expectedFeaturesGate: map[string]bool{"feature1": true, "feature2": false},
   108  		},
   109  	}
   110  
   111  	for _, test := range tests {
   112  		t.Run(test.value, func(t *testing.T) {
   113  			r, err := NewFeatureGate(&someFeatures, test.value)
   114  
   115  			if !test.expectedError && err != nil {
   116  				t.Errorf("NewFeatureGate failed when not expected: %v", err)
   117  				return
   118  			} else if test.expectedError && err == nil {
   119  				t.Error("NewFeatureGate didn't failed when expected")
   120  				return
   121  			}
   122  
   123  			if !reflect.DeepEqual(r, test.expectedFeaturesGate) {
   124  				t.Errorf("NewFeatureGate returned a unexpected value")
   125  			}
   126  		})
   127  	}
   128  }
   129  
   130  func TestValidateVersion(t *testing.T) {
   131  	var someFeatures = FeatureList{
   132  		"feature1": {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.Beta}},
   133  		"feature2": {FeatureSpec: featuregate.FeatureSpec{Default: true, PreRelease: featuregate.Alpha}, MinimumVersion: version.MustParseSemantic("v1.17.0").WithPreRelease("alpha.1")},
   134  	}
   135  
   136  	var tests = []struct {
   137  		name              string
   138  		requestedVersion  string
   139  		requestedFeatures map[string]bool
   140  		expectedError     bool
   141  	}{
   142  		{
   143  			name:              "no min version",
   144  			requestedFeatures: map[string]bool{"feature1": true},
   145  			expectedError:     false,
   146  		},
   147  		{
   148  			name:              "min version but correct value given",
   149  			requestedFeatures: map[string]bool{"feature2": true},
   150  			requestedVersion:  "v1.17.0",
   151  			expectedError:     false,
   152  		},
   153  		{
   154  			name:              "min version and incorrect value given",
   155  			requestedFeatures: map[string]bool{"feature2": true},
   156  			requestedVersion:  "v1.11.2",
   157  			expectedError:     true,
   158  		},
   159  	}
   160  
   161  	for _, test := range tests {
   162  		t.Run(test.name, func(t *testing.T) {
   163  			err := ValidateVersion(someFeatures, test.requestedFeatures, test.requestedVersion)
   164  			if !test.expectedError && err != nil {
   165  				t.Errorf("ValidateVersion failed when not expected: %v", err)
   166  				return
   167  			} else if test.expectedError && err == nil {
   168  				t.Error("ValidateVersion didn't failed when expected")
   169  				return
   170  			}
   171  		})
   172  	}
   173  }
   174  
   175  // TestEnabledDefaults tests that Enabled returns the default values for
   176  // each feature gate when no feature gates are specified.
   177  func TestEnabledDefaults(t *testing.T) {
   178  	for featureName, feature := range InitFeatureGates {
   179  		featureList := make(map[string]bool)
   180  
   181  		enabled := Enabled(featureList, featureName)
   182  		if enabled != feature.Default {
   183  			t.Errorf("Enabled returned %v instead of default value %v for feature %s", enabled, feature.Default, featureName)
   184  		}
   185  	}
   186  }
   187  
   188  func TestCheckDeprecatedFlags(t *testing.T) {
   189  	dummyMessage := "dummy message"
   190  	var someFeatures = FeatureList{
   191  		"feature1":   {FeatureSpec: featuregate.FeatureSpec{Default: false, PreRelease: featuregate.Beta}},
   192  		"deprecated": {FeatureSpec: featuregate.FeatureSpec{Default: true, PreRelease: featuregate.Deprecated}, DeprecationMessage: dummyMessage},
   193  	}
   194  
   195  	var tests = []struct {
   196  		name        string
   197  		features    map[string]bool
   198  		expectedMsg map[string]string
   199  	}{
   200  		{
   201  			name:        "deprecated feature",
   202  			features:    map[string]bool{"deprecated": true},
   203  			expectedMsg: map[string]string{"deprecated": dummyMessage},
   204  		},
   205  		{
   206  			name:        "valid feature",
   207  			features:    map[string]bool{"feature1": true},
   208  			expectedMsg: map[string]string{},
   209  		},
   210  		{
   211  			name:        "invalid feature",
   212  			features:    map[string]bool{"feature2": true},
   213  			expectedMsg: map[string]string{"feature2": "Unknown feature gate flag: feature2"},
   214  		},
   215  	}
   216  
   217  	for _, test := range tests {
   218  		t.Run(test.name, func(t *testing.T) {
   219  			msg := CheckDeprecatedFlags(&someFeatures, test.features)
   220  			if !reflect.DeepEqual(test.expectedMsg, msg) {
   221  				t.Errorf("CheckDeprecatedFlags() = %v, want %v", msg, test.expectedMsg)
   222  			}
   223  		})
   224  	}
   225  }
   226  
   227  func TestSupports(t *testing.T) {
   228  	tests := []struct {
   229  		name        string
   230  		featureName string
   231  		want        bool
   232  	}{
   233  		{
   234  			name:        "the feature is not supported",
   235  			featureName: "foo",
   236  			want:        false,
   237  		},
   238  		{
   239  			name:        "the feature is supported",
   240  			featureName: PublicKeysECDSA,
   241  			want:        true,
   242  		},
   243  	}
   244  	for _, test := range tests {
   245  		t.Run(test.name, func(t *testing.T) {
   246  			if got := Supports(InitFeatureGates, test.featureName); got != test.want {
   247  				t.Errorf("Supports() = %v, want %v", got, test.want)
   248  			}
   249  		})
   250  	}
   251  }
   252  

View as plain text