...

Source file src/k8s.io/kubernetes/cmd/kubeadm/app/util/arguments_test.go

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

     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 util
    18  
    19  import (
    20  	"reflect"
    21  	"sort"
    22  	"testing"
    23  
    24  	kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
    25  )
    26  
    27  func TestArgumentsToCommand(t *testing.T) {
    28  	var tests = []struct {
    29  		name      string
    30  		base      []kubeadmapi.Arg
    31  		overrides []kubeadmapi.Arg
    32  		expected  []string
    33  	}{
    34  		{
    35  			name: "override an argument from the base",
    36  			base: []kubeadmapi.Arg{
    37  				{Name: "admission-control", Value: "NamespaceLifecycle"},
    38  				{Name: "allow-privileged", Value: "true"},
    39  			},
    40  			overrides: []kubeadmapi.Arg{
    41  				{Name: "admission-control", Value: "NamespaceLifecycle,LimitRanger"},
    42  			},
    43  			expected: []string{
    44  				"--admission-control=NamespaceLifecycle,LimitRanger",
    45  				"--allow-privileged=true",
    46  			},
    47  		},
    48  		{
    49  			name: "override an argument from the base and add duplicate",
    50  			base: []kubeadmapi.Arg{
    51  				{Name: "token-auth-file", Value: "/token"},
    52  				{Name: "tls-sni-cert-key", Value: "/some/path/"},
    53  			},
    54  			overrides: []kubeadmapi.Arg{
    55  				{Name: "tls-sni-cert-key", Value: "/some/new/path"},
    56  				{Name: "tls-sni-cert-key", Value: "/some/new/path/subpath"},
    57  			},
    58  			expected: []string{
    59  				"--tls-sni-cert-key=/some/new/path",
    60  				"--tls-sni-cert-key=/some/new/path/subpath",
    61  				"--token-auth-file=/token",
    62  			},
    63  		},
    64  		{
    65  			name: "override all duplicate arguments from base",
    66  			base: []kubeadmapi.Arg{
    67  				{Name: "token-auth-file", Value: "/token"},
    68  				{Name: "tls-sni-cert-key", Value: "foo"},
    69  				{Name: "tls-sni-cert-key", Value: "bar"},
    70  			},
    71  			overrides: []kubeadmapi.Arg{
    72  				{Name: "tls-sni-cert-key", Value: "/some/new/path"},
    73  			},
    74  			expected: []string{
    75  				"--tls-sni-cert-key=/some/new/path",
    76  				"--token-auth-file=/token",
    77  			},
    78  		},
    79  		{
    80  			name: "add an argument that is not in base",
    81  			base: []kubeadmapi.Arg{
    82  				{Name: "allow-privileged", Value: "true"},
    83  			},
    84  			overrides: []kubeadmapi.Arg{
    85  				{Name: "admission-control", Value: "NamespaceLifecycle,LimitRanger"},
    86  			},
    87  			expected: []string{
    88  				"--admission-control=NamespaceLifecycle,LimitRanger",
    89  				"--allow-privileged=true",
    90  			},
    91  		},
    92  		{
    93  			name: "allow empty strings in base",
    94  			base: []kubeadmapi.Arg{
    95  				{Name: "allow-privileged", Value: "true"},
    96  				{Name: "something-that-allows-empty-string", Value: ""},
    97  			},
    98  			overrides: []kubeadmapi.Arg{
    99  				{Name: "admission-control", Value: "NamespaceLifecycle,LimitRanger"},
   100  			},
   101  			expected: []string{
   102  				"--admission-control=NamespaceLifecycle,LimitRanger",
   103  				"--allow-privileged=true",
   104  				"--something-that-allows-empty-string=",
   105  			},
   106  		},
   107  		{
   108  			name: "allow empty strings in overrides",
   109  			base: []kubeadmapi.Arg{
   110  				{Name: "allow-privileged", Value: "true"},
   111  				{Name: "something-that-allows-empty-string", Value: "foo"},
   112  			},
   113  			overrides: []kubeadmapi.Arg{
   114  				{Name: "admission-control", Value: "NamespaceLifecycle,LimitRanger"},
   115  				{Name: "something-that-allows-empty-string", Value: ""},
   116  			},
   117  			expected: []string{
   118  				"--admission-control=NamespaceLifecycle,LimitRanger",
   119  				"--allow-privileged=true",
   120  				"--something-that-allows-empty-string=",
   121  			},
   122  		},
   123  	}
   124  
   125  	for _, rt := range tests {
   126  		t.Run(rt.name, func(t *testing.T) {
   127  			actual := ArgumentsToCommand(rt.base, rt.overrides)
   128  			if !reflect.DeepEqual(actual, rt.expected) {
   129  				t.Errorf("failed ArgumentsToCommand:\nexpected:\n%v\nsaw:\n%v", rt.expected, actual)
   130  			}
   131  		})
   132  	}
   133  }
   134  
   135  func TestArgumentsFromCommand(t *testing.T) {
   136  	var tests = []struct {
   137  		name     string
   138  		args     []string
   139  		expected []kubeadmapi.Arg
   140  	}{
   141  		{
   142  			name: "normal case",
   143  			args: []string{
   144  				"--admission-control=NamespaceLifecycle,LimitRanger",
   145  				"--allow-privileged=true",
   146  			},
   147  			expected: []kubeadmapi.Arg{
   148  				{Name: "admission-control", Value: "NamespaceLifecycle,LimitRanger"},
   149  				{Name: "allow-privileged", Value: "true"},
   150  			},
   151  		},
   152  		{
   153  			name: "test that feature-gates is working",
   154  			args: []string{
   155  				"--admission-control=NamespaceLifecycle,LimitRanger",
   156  				"--allow-privileged=true",
   157  				"--feature-gates=EnableFoo=true,EnableBar=false",
   158  			},
   159  			expected: []kubeadmapi.Arg{
   160  				{Name: "admission-control", Value: "NamespaceLifecycle,LimitRanger"},
   161  				{Name: "allow-privileged", Value: "true"},
   162  				{Name: "feature-gates", Value: "EnableFoo=true,EnableBar=false"},
   163  			},
   164  		},
   165  		{
   166  			name: "test that a binary can be the first arg",
   167  			args: []string{
   168  				"kube-apiserver",
   169  				"--admission-control=NamespaceLifecycle,LimitRanger",
   170  				"--allow-privileged=true",
   171  				"--feature-gates=EnableFoo=true,EnableBar=false",
   172  			},
   173  			expected: []kubeadmapi.Arg{
   174  				{Name: "admission-control", Value: "NamespaceLifecycle,LimitRanger"},
   175  				{Name: "allow-privileged", Value: "true"},
   176  				{Name: "feature-gates", Value: "EnableFoo=true,EnableBar=false"},
   177  			},
   178  		},
   179  		{
   180  			name: "allow duplicate args",
   181  			args: []string{
   182  				"--admission-control=NamespaceLifecycle,LimitRanger",
   183  				"--tls-sni-cert-key=/some/path",
   184  				"--tls-sni-cert-key=/some/path/subpath",
   185  			},
   186  			expected: []kubeadmapi.Arg{
   187  				{Name: "admission-control", Value: "NamespaceLifecycle,LimitRanger"},
   188  				{Name: "tls-sni-cert-key", Value: "/some/path"},
   189  				{Name: "tls-sni-cert-key", Value: "/some/path/subpath"},
   190  			},
   191  		},
   192  	}
   193  
   194  	for _, rt := range tests {
   195  		t.Run(rt.name, func(t *testing.T) {
   196  			actual := ArgumentsFromCommand(rt.args)
   197  			if !reflect.DeepEqual(actual, rt.expected) {
   198  				t.Errorf("failed ArgumentsFromCommand:\nexpected:\n%v\nsaw:\n%v", rt.expected, actual)
   199  			}
   200  		})
   201  	}
   202  }
   203  
   204  func TestRoundtrip(t *testing.T) {
   205  	var tests = []struct {
   206  		name string
   207  		args []string
   208  	}{
   209  		{
   210  			name: "normal case",
   211  			args: []string{
   212  				"--admission-control=NamespaceLifecycle,LimitRanger",
   213  				"--allow-privileged=true",
   214  			},
   215  		},
   216  		{
   217  			name: "test that feature-gates is working",
   218  			args: []string{
   219  				"--admission-control=NamespaceLifecycle,LimitRanger",
   220  				"--allow-privileged=true",
   221  				"--feature-gates=EnableFoo=true,EnableBar=false",
   222  			},
   223  		},
   224  	}
   225  
   226  	for _, rt := range tests {
   227  		t.Run(rt.name, func(t *testing.T) {
   228  			// These two methods should be each other's opposite functions, test that by chaining the methods and see if you get the same result back
   229  			actual := ArgumentsToCommand(ArgumentsFromCommand(rt.args), []kubeadmapi.Arg{})
   230  			sort.Strings(actual)
   231  			sort.Strings(rt.args)
   232  
   233  			if !reflect.DeepEqual(actual, rt.args) {
   234  				t.Errorf("failed TestRoundtrip:\nexpected:\n%v\nsaw:\n%v", rt.args, actual)
   235  			}
   236  		})
   237  	}
   238  }
   239  
   240  func TestParseArgument(t *testing.T) {
   241  	var tests = []struct {
   242  		name        string
   243  		arg         string
   244  		expectedKey string
   245  		expectedVal string
   246  		expectedErr bool
   247  	}{
   248  		{
   249  			name:        "arg cannot be empty",
   250  			arg:         "",
   251  			expectedErr: true,
   252  		},
   253  		{
   254  			name:        "arg must contain -- and =",
   255  			arg:         "a",
   256  			expectedErr: true,
   257  		},
   258  		{
   259  			name:        "arg must contain -- and =",
   260  			arg:         "a-z",
   261  			expectedErr: true,
   262  		},
   263  		{
   264  			name:        "arg must contain --",
   265  			arg:         "a=b",
   266  			expectedErr: true,
   267  		},
   268  		{
   269  			name:        "arg must contain a key",
   270  			arg:         "--=b",
   271  			expectedErr: true,
   272  		},
   273  		{
   274  			name:        "arg can contain key but no value",
   275  			arg:         "--a=",
   276  			expectedKey: "a",
   277  			expectedVal: "",
   278  			expectedErr: false,
   279  		},
   280  		{
   281  			name:        "simple case",
   282  			arg:         "--a=b",
   283  			expectedKey: "a",
   284  			expectedVal: "b",
   285  			expectedErr: false,
   286  		},
   287  		{
   288  			name:        "keys/values with '-' should be supported",
   289  			arg:         "--very-long-flag-name=some-value",
   290  			expectedKey: "very-long-flag-name",
   291  			expectedVal: "some-value",
   292  			expectedErr: false,
   293  		},
   294  		{
   295  			name:        "numbers should be handled correctly",
   296  			arg:         "--some-number=0.2",
   297  			expectedKey: "some-number",
   298  			expectedVal: "0.2",
   299  			expectedErr: false,
   300  		},
   301  		{
   302  			name:        "lists should be handled correctly",
   303  			arg:         "--admission-control=foo,bar,baz",
   304  			expectedKey: "admission-control",
   305  			expectedVal: "foo,bar,baz",
   306  			expectedErr: false,
   307  		},
   308  		{
   309  			name:        "more than one '=' should be allowed",
   310  			arg:         "--feature-gates=EnableFoo=true,EnableBar=false",
   311  			expectedKey: "feature-gates",
   312  			expectedVal: "EnableFoo=true,EnableBar=false",
   313  			expectedErr: false,
   314  		},
   315  	}
   316  
   317  	for _, rt := range tests {
   318  		t.Run(rt.name, func(t *testing.T) {
   319  			key, val, actual := parseArgument(rt.arg)
   320  			if (actual != nil) != rt.expectedErr {
   321  				t.Errorf("failed parseArgument:\nexpected error:\n%t\nsaw error:\n%v", rt.expectedErr, actual)
   322  			}
   323  			if (key != rt.expectedKey) || (val != rt.expectedVal) {
   324  				t.Errorf("failed parseArgument:\nexpected key: %s\nsaw key: %s\nexpected value: %s\nsaw value: %s", rt.expectedKey, key, rt.expectedVal, val)
   325  			}
   326  		})
   327  	}
   328  }
   329  

View as plain text