...

Source file src/k8s.io/kubernetes/pkg/util/flag/flags_test.go

Documentation: k8s.io/kubernetes/pkg/util/flag

     1  /*
     2  Copyright 2016 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 flag
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  	"strings"
    23  	"testing"
    24  
    25  	"github.com/spf13/pflag"
    26  
    27  	v1 "k8s.io/api/core/v1"
    28  	apiequality "k8s.io/apimachinery/pkg/api/equality"
    29  	"k8s.io/apimachinery/pkg/api/resource"
    30  	kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
    31  )
    32  
    33  func TestIPVar(t *testing.T) {
    34  	defaultIP := "0.0.0.0"
    35  	testCases := []struct {
    36  		argc      string
    37  		expectErr bool
    38  		expectVal string
    39  	}{
    40  
    41  		{
    42  			argc:      "blah --ip=1.2.3.4",
    43  			expectVal: "1.2.3.4",
    44  		},
    45  		{
    46  			argc:      "blah --ip=1.2.3.4a",
    47  			expectErr: true,
    48  			expectVal: defaultIP,
    49  		},
    50  	}
    51  	for _, tc := range testCases {
    52  		fs := pflag.NewFlagSet("blah", pflag.PanicOnError)
    53  		ip := defaultIP
    54  		fs.Var(&IPVar{&ip}, "ip", "the ip")
    55  
    56  		var err error
    57  		func() {
    58  			defer func() {
    59  				if r := recover(); r != nil {
    60  					err = r.(error)
    61  				}
    62  			}()
    63  			fs.Parse(strings.Split(tc.argc, " "))
    64  		}()
    65  
    66  		if tc.expectErr && err == nil {
    67  			t.Errorf("did not observe an expected error")
    68  			continue
    69  		}
    70  		if !tc.expectErr && err != nil {
    71  			t.Errorf("observed an unexpected error: %v", err)
    72  			continue
    73  		}
    74  		if tc.expectVal != ip {
    75  			t.Errorf("unexpected ip: expected %q, saw %q", tc.expectVal, ip)
    76  		}
    77  	}
    78  }
    79  
    80  func TestIPPortVar(t *testing.T) {
    81  	defaultIPPort := "0.0.0.0:8080"
    82  	testCases := []struct {
    83  		desc      string
    84  		argc      string
    85  		expectErr bool
    86  		expectVal string
    87  	}{
    88  
    89  		{
    90  			desc:      "valid ipv4 1",
    91  			argc:      "blah --ipport=0.0.0.0",
    92  			expectVal: "0.0.0.0",
    93  		},
    94  		{
    95  			desc:      "valid ipv4 2",
    96  			argc:      "blah --ipport=127.0.0.1",
    97  			expectVal: "127.0.0.1",
    98  		},
    99  
   100  		{
   101  			desc:      "invalid IP",
   102  			argc:      "blah --ipport=invalidip",
   103  			expectErr: true,
   104  			expectVal: defaultIPPort,
   105  		},
   106  		{
   107  			desc:      "valid ipv4 with port",
   108  			argc:      "blah --ipport=0.0.0.0:8080",
   109  			expectVal: "0.0.0.0:8080",
   110  		},
   111  		{
   112  			desc:      "invalid ipv4 with invalid port",
   113  			argc:      "blah --ipport=0.0.0.0:invalidport",
   114  			expectErr: true,
   115  			expectVal: defaultIPPort,
   116  		},
   117  		{
   118  			desc:      "invalid IP with port",
   119  			argc:      "blah --ipport=invalidip:8080",
   120  			expectErr: true,
   121  			expectVal: defaultIPPort,
   122  		},
   123  		{
   124  			desc:      "valid ipv6 1",
   125  			argc:      "blah --ipport=::1",
   126  			expectVal: "::1",
   127  		},
   128  		{
   129  			desc:      "valid ipv6 2",
   130  			argc:      "blah --ipport=::",
   131  			expectVal: "::",
   132  		},
   133  		{
   134  			desc:      "valid ipv6 with port",
   135  			argc:      "blah --ipport=[::1]:8080",
   136  			expectVal: "[::1]:8080",
   137  		},
   138  		{
   139  			desc:      "invalid ipv6 with port without bracket",
   140  			argc:      "blah --ipport=fd00:f00d:600d:f00d:8080",
   141  			expectErr: true,
   142  			expectVal: defaultIPPort,
   143  		},
   144  	}
   145  	for _, tc := range testCases {
   146  		fs := pflag.NewFlagSet("blah", pflag.PanicOnError)
   147  		ipport := defaultIPPort
   148  		fs.Var(&IPPortVar{&ipport}, "ipport", "the ip:port")
   149  
   150  		var err error
   151  		func() {
   152  			defer func() {
   153  				if r := recover(); r != nil {
   154  					err = r.(error)
   155  				}
   156  			}()
   157  			fs.Parse(strings.Split(tc.argc, " "))
   158  		}()
   159  
   160  		if tc.expectErr && err == nil {
   161  			t.Errorf("%q: Did not observe an expected error", tc.desc)
   162  			continue
   163  		}
   164  		if !tc.expectErr && err != nil {
   165  			t.Errorf("%q: Observed an unexpected error: %v", tc.desc, err)
   166  			continue
   167  		}
   168  		if tc.expectVal != ipport {
   169  			t.Errorf("%q: Unexpected ipport: expected %q, saw %q", tc.desc, tc.expectVal, ipport)
   170  		}
   171  	}
   172  }
   173  
   174  func TestReservedMemoryVar(t *testing.T) {
   175  	resourceNameHugepages1Gi := v1.ResourceName(fmt.Sprintf("%s1Gi", v1.ResourceHugePagesPrefix))
   176  	memory1Gi := resource.MustParse("1Gi")
   177  	testCases := []struct {
   178  		desc      string
   179  		argc      string
   180  		expectErr bool
   181  		expectVal []kubeletconfig.MemoryReservation
   182  	}{
   183  		{
   184  			desc: "valid input",
   185  			argc: "blah --reserved-memory=0:memory=1Gi",
   186  			expectVal: []kubeletconfig.MemoryReservation{
   187  				{
   188  					NumaNode: 0,
   189  					Limits: v1.ResourceList{
   190  						v1.ResourceMemory: memory1Gi,
   191  					},
   192  				},
   193  			},
   194  		},
   195  		{
   196  			desc: "valid input with multiple memory types",
   197  			argc: "blah --reserved-memory=0:memory=1Gi,hugepages-1Gi=1Gi",
   198  			expectVal: []kubeletconfig.MemoryReservation{
   199  				{
   200  					NumaNode: 0,
   201  					Limits: v1.ResourceList{
   202  						v1.ResourceMemory:        memory1Gi,
   203  						resourceNameHugepages1Gi: memory1Gi,
   204  					},
   205  				},
   206  			},
   207  		},
   208  		{
   209  			desc: "valid input with multiple reserved-memory arguments",
   210  			argc: "blah --reserved-memory=0:memory=1Gi,hugepages-1Gi=1Gi --reserved-memory=1:memory=1Gi",
   211  			expectVal: []kubeletconfig.MemoryReservation{
   212  				{
   213  					NumaNode: 0,
   214  					Limits: v1.ResourceList{
   215  						v1.ResourceMemory:        memory1Gi,
   216  						resourceNameHugepages1Gi: memory1Gi,
   217  					},
   218  				},
   219  				{
   220  					NumaNode: 1,
   221  					Limits: v1.ResourceList{
   222  						v1.ResourceMemory: memory1Gi,
   223  					},
   224  				},
   225  			},
   226  		},
   227  		{
   228  			desc: "valid input with ';' as separator for multiple reserved-memory arguments",
   229  			argc: "blah --reserved-memory=0:memory=1Gi,hugepages-1Gi=1Gi;1:memory=1Gi",
   230  			expectVal: []kubeletconfig.MemoryReservation{
   231  				{
   232  					NumaNode: 0,
   233  					Limits: v1.ResourceList{
   234  						v1.ResourceMemory:        memory1Gi,
   235  						resourceNameHugepages1Gi: memory1Gi,
   236  					},
   237  				},
   238  				{
   239  					NumaNode: 1,
   240  					Limits: v1.ResourceList{
   241  						v1.ResourceMemory: memory1Gi,
   242  					},
   243  				},
   244  			},
   245  		},
   246  		{
   247  			desc:      "invalid input",
   248  			argc:      "blah --reserved-memory=bad-input",
   249  			expectVal: nil,
   250  			expectErr: true,
   251  		},
   252  		{
   253  			desc:      "invalid input without memory types",
   254  			argc:      "blah --reserved-memory=0:",
   255  			expectVal: nil,
   256  			expectErr: true,
   257  		},
   258  		{
   259  			desc:      "invalid input with non-integer NUMA node",
   260  			argc:      "blah --reserved-memory=a:memory=1Gi",
   261  			expectVal: nil,
   262  			expectErr: true,
   263  		},
   264  		{
   265  			desc:      "invalid input with invalid limit",
   266  			argc:      "blah --reserved-memory=0:memory=",
   267  			expectVal: nil,
   268  			expectErr: true,
   269  		},
   270  		{
   271  			desc:      "invalid input with invalid memory type",
   272  			argc:      "blah --reserved-memory=0:type=1Gi",
   273  			expectVal: nil,
   274  			expectErr: true,
   275  		},
   276  		{
   277  			desc:      "invalid input with invalid quantity",
   278  			argc:      "blah --reserved-memory=0:memory=1Be",
   279  			expectVal: nil,
   280  			expectErr: true,
   281  		},
   282  	}
   283  	for _, tc := range testCases {
   284  		fs := pflag.NewFlagSet("blah", pflag.PanicOnError)
   285  
   286  		var reservedMemory []kubeletconfig.MemoryReservation
   287  		fs.Var(&ReservedMemoryVar{Value: &reservedMemory}, "reserved-memory", "--reserved-memory 0:memory=1Gi,hugepages-1M=2Gi")
   288  
   289  		var err error
   290  		func() {
   291  			defer func() {
   292  				if r := recover(); r != nil {
   293  					err = r.(error)
   294  				}
   295  			}()
   296  			fs.Parse(strings.Split(tc.argc, " "))
   297  		}()
   298  
   299  		if tc.expectErr && err == nil {
   300  			t.Fatalf("%q: Did not observe an expected error", tc.desc)
   301  		}
   302  		if !tc.expectErr && err != nil {
   303  			t.Fatalf("%q: Observed an unexpected error: %v", tc.desc, err)
   304  		}
   305  		if !apiequality.Semantic.DeepEqual(reservedMemory, tc.expectVal) {
   306  			t.Fatalf("%q: Unexpected reserved-error: expected %v, saw %v", tc.desc, tc.expectVal, reservedMemory)
   307  		}
   308  	}
   309  }
   310  
   311  func TestTaintsVar(t *testing.T) {
   312  	cases := []struct {
   313  		f   string
   314  		err bool
   315  		t   []v1.Taint
   316  	}{
   317  		{
   318  			f: "",
   319  			t: []v1.Taint(nil),
   320  		},
   321  		{
   322  			f: "--t=foo=bar:NoSchedule",
   323  			t: []v1.Taint{{Key: "foo", Value: "bar", Effect: "NoSchedule"}},
   324  		},
   325  		{
   326  			f: "--t=baz:NoSchedule",
   327  			t: []v1.Taint{{Key: "baz", Value: "", Effect: "NoSchedule"}},
   328  		},
   329  		{
   330  			f: "--t=foo=bar:NoSchedule,baz:NoSchedule,bing=bang:PreferNoSchedule,qux=:NoSchedule",
   331  			t: []v1.Taint{
   332  				{Key: "foo", Value: "bar", Effect: v1.TaintEffectNoSchedule},
   333  				{Key: "baz", Value: "", Effect: "NoSchedule"},
   334  				{Key: "bing", Value: "bang", Effect: v1.TaintEffectPreferNoSchedule},
   335  				{Key: "qux", Value: "", Effect: "NoSchedule"},
   336  			},
   337  		},
   338  		{
   339  			f: "--t=dedicated-for=user1:NoExecute,baz:NoSchedule,foo-bar=:NoSchedule",
   340  			t: []v1.Taint{
   341  				{Key: "dedicated-for", Value: "user1", Effect: "NoExecute"},
   342  				{Key: "baz", Value: "", Effect: "NoSchedule"},
   343  				{Key: "foo-bar", Value: "", Effect: "NoSchedule"},
   344  			},
   345  		},
   346  	}
   347  
   348  	for i, c := range cases {
   349  		args := append([]string{"test"}, strings.Fields(c.f)...)
   350  		cli := pflag.NewFlagSet("test", pflag.ContinueOnError)
   351  		var taints []v1.Taint
   352  		cli.Var(RegisterWithTaintsVar{Value: &taints}, "t", "bar")
   353  
   354  		err := cli.Parse(args)
   355  		if err == nil && c.err {
   356  			t.Errorf("[%v] expected error", i)
   357  			continue
   358  		}
   359  		if err != nil && !c.err {
   360  			t.Errorf("[%v] unexpected error: %v", i, err)
   361  			continue
   362  		}
   363  		if !reflect.DeepEqual(c.t, taints) {
   364  			t.Errorf("[%v] unexpected taints:\n\texpected:\n\t\t%#v\n\tgot:\n\t\t%#v", i, c.t, taints)
   365  		}
   366  	}
   367  
   368  }
   369  

View as plain text