...

Source file src/k8s.io/kubectl/pkg/cmd/set/set_selector_test.go

Documentation: k8s.io/kubectl/pkg/cmd/set

     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 set
    18  
    19  import (
    20  	"reflect"
    21  	"strings"
    22  	"testing"
    23  
    24  	"github.com/stretchr/testify/assert"
    25  	batchv1 "k8s.io/api/batch/v1"
    26  	"k8s.io/api/core/v1"
    27  	extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
    28  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    29  	"k8s.io/apimachinery/pkg/runtime"
    30  	"k8s.io/cli-runtime/pkg/genericclioptions"
    31  	"k8s.io/cli-runtime/pkg/genericiooptions"
    32  	"k8s.io/cli-runtime/pkg/printers"
    33  	"k8s.io/cli-runtime/pkg/resource"
    34  )
    35  
    36  func TestUpdateSelectorForObjectTypes(t *testing.T) {
    37  	before := metav1.LabelSelector{MatchLabels: map[string]string{"fee": "true"},
    38  		MatchExpressions: []metav1.LabelSelectorRequirement{
    39  			{
    40  				Key:      "foo",
    41  				Operator: metav1.LabelSelectorOpIn,
    42  				Values:   []string{"on", "yes"},
    43  			},
    44  		}}
    45  
    46  	rc := v1.ReplicationController{}
    47  	ser := v1.Service{}
    48  	dep := extensionsv1beta1.Deployment{Spec: extensionsv1beta1.DeploymentSpec{Selector: &before}}
    49  	ds := extensionsv1beta1.DaemonSet{Spec: extensionsv1beta1.DaemonSetSpec{Selector: &before}}
    50  	rs := extensionsv1beta1.ReplicaSet{Spec: extensionsv1beta1.ReplicaSetSpec{Selector: &before}}
    51  	job := batchv1.Job{Spec: batchv1.JobSpec{Selector: &before}}
    52  	pvc := v1.PersistentVolumeClaim{Spec: v1.PersistentVolumeClaimSpec{Selector: &before}}
    53  	sa := v1.ServiceAccount{}
    54  	type args struct {
    55  		obj      runtime.Object
    56  		selector metav1.LabelSelector
    57  	}
    58  	tests := []struct {
    59  		name    string
    60  		args    args
    61  		wantErr bool
    62  	}{
    63  		{name: "rc",
    64  			args: args{
    65  				obj:      &rc,
    66  				selector: metav1.LabelSelector{},
    67  			},
    68  			wantErr: true,
    69  		},
    70  		{name: "ser",
    71  			args: args{
    72  				obj:      &ser,
    73  				selector: metav1.LabelSelector{},
    74  			},
    75  			wantErr: false,
    76  		},
    77  		{name: "dep",
    78  			args: args{
    79  				obj:      &dep,
    80  				selector: metav1.LabelSelector{},
    81  			},
    82  			wantErr: true,
    83  		},
    84  		{name: "ds",
    85  			args: args{
    86  				obj:      &ds,
    87  				selector: metav1.LabelSelector{},
    88  			},
    89  			wantErr: true,
    90  		},
    91  		{name: "rs",
    92  			args: args{
    93  				obj:      &rs,
    94  				selector: metav1.LabelSelector{},
    95  			},
    96  			wantErr: true,
    97  		},
    98  		{name: "job",
    99  			args: args{
   100  				obj:      &job,
   101  				selector: metav1.LabelSelector{},
   102  			},
   103  			wantErr: true,
   104  		},
   105  		{name: "pvc - no updates",
   106  			args: args{
   107  				obj:      &pvc,
   108  				selector: metav1.LabelSelector{},
   109  			},
   110  			wantErr: true,
   111  		},
   112  		{name: "sa - no selector",
   113  			args: args{
   114  				obj:      &sa,
   115  				selector: metav1.LabelSelector{},
   116  			},
   117  			wantErr: true,
   118  		},
   119  	}
   120  	for _, tt := range tests {
   121  		if err := updateSelectorForObject(tt.args.obj, tt.args.selector); (err != nil) != tt.wantErr {
   122  			t.Errorf("%q. updateSelectorForObject() error = %v, wantErr %v", tt.name, err, tt.wantErr)
   123  		}
   124  	}
   125  }
   126  
   127  func TestUpdateNewSelectorValuesForObject(t *testing.T) {
   128  	ser := v1.Service{}
   129  	type args struct {
   130  		obj      runtime.Object
   131  		selector metav1.LabelSelector
   132  	}
   133  	tests := []struct {
   134  		name    string
   135  		args    args
   136  		wantErr bool
   137  	}{
   138  		{name: "empty",
   139  			args: args{
   140  				obj: &ser,
   141  				selector: metav1.LabelSelector{
   142  					MatchLabels:      map[string]string{},
   143  					MatchExpressions: []metav1.LabelSelectorRequirement{},
   144  				},
   145  			},
   146  			wantErr: false,
   147  		},
   148  		{name: "label-only",
   149  			args: args{
   150  				obj: &ser,
   151  				selector: metav1.LabelSelector{
   152  					MatchLabels:      map[string]string{"b": "u"},
   153  					MatchExpressions: []metav1.LabelSelectorRequirement{},
   154  				},
   155  			},
   156  			wantErr: false,
   157  		},
   158  	}
   159  	for _, tt := range tests {
   160  		if err := updateSelectorForObject(tt.args.obj, tt.args.selector); (err != nil) != tt.wantErr {
   161  			t.Errorf("%q. updateSelectorForObject() error = %v, wantErr %v", tt.name, err, tt.wantErr)
   162  		}
   163  
   164  		assert.EqualValues(t, tt.args.selector.MatchLabels, ser.Spec.Selector, tt.name)
   165  
   166  	}
   167  }
   168  
   169  func TestUpdateOldSelectorValuesForObject(t *testing.T) {
   170  	ser := v1.Service{Spec: v1.ServiceSpec{Selector: map[string]string{"fee": "true"}}}
   171  	type args struct {
   172  		obj      runtime.Object
   173  		selector metav1.LabelSelector
   174  	}
   175  	tests := []struct {
   176  		name    string
   177  		args    args
   178  		wantErr bool
   179  	}{
   180  		{name: "empty",
   181  			args: args{
   182  				obj: &ser,
   183  				selector: metav1.LabelSelector{
   184  					MatchLabels:      map[string]string{},
   185  					MatchExpressions: []metav1.LabelSelectorRequirement{},
   186  				},
   187  			},
   188  			wantErr: false,
   189  		},
   190  		{name: "label-only",
   191  			args: args{
   192  				obj: &ser,
   193  				selector: metav1.LabelSelector{
   194  					MatchLabels:      map[string]string{"fee": "false", "x": "y"},
   195  					MatchExpressions: []metav1.LabelSelectorRequirement{},
   196  				},
   197  			},
   198  			wantErr: false,
   199  		},
   200  		{name: "expr-only - err",
   201  			args: args{
   202  				obj: &ser,
   203  				selector: metav1.LabelSelector{
   204  					MatchLabels: map[string]string{},
   205  					MatchExpressions: []metav1.LabelSelectorRequirement{
   206  						{
   207  							Key:      "a",
   208  							Operator: "In",
   209  							Values:   []string{"x", "y"},
   210  						},
   211  					},
   212  				},
   213  			},
   214  			wantErr: true,
   215  		},
   216  		{name: "both - err",
   217  			args: args{
   218  				obj: &ser,
   219  				selector: metav1.LabelSelector{
   220  					MatchLabels: map[string]string{"b": "u"},
   221  					MatchExpressions: []metav1.LabelSelectorRequirement{
   222  						{
   223  							Key:      "a",
   224  							Operator: "In",
   225  							Values:   []string{"x", "y"},
   226  						},
   227  					},
   228  				},
   229  			},
   230  			wantErr: true,
   231  		},
   232  	}
   233  	for _, tt := range tests {
   234  		err := updateSelectorForObject(tt.args.obj, tt.args.selector)
   235  		if (err != nil) != tt.wantErr {
   236  			t.Errorf("%q. updateSelectorForObject() error = %v, wantErr %v", tt.name, err, tt.wantErr)
   237  		} else if !tt.wantErr {
   238  			assert.EqualValues(t, tt.args.selector.MatchLabels, ser.Spec.Selector, tt.name)
   239  		}
   240  	}
   241  }
   242  
   243  func TestGetResourcesAndSelector(t *testing.T) {
   244  	type args struct {
   245  		args []string
   246  	}
   247  	tests := []struct {
   248  		name          string
   249  		args          args
   250  		wantResources []string
   251  		wantSelector  *metav1.LabelSelector
   252  		wantErr       bool
   253  	}{
   254  		{
   255  			name:          "basic match",
   256  			args:          args{args: []string{"rc/foo", "healthy=true"}},
   257  			wantResources: []string{"rc/foo"},
   258  			wantErr:       false,
   259  			wantSelector: &metav1.LabelSelector{
   260  				MatchLabels:      map[string]string{"healthy": "true"},
   261  				MatchExpressions: []metav1.LabelSelectorRequirement{},
   262  			},
   263  		},
   264  		{
   265  			name:          "basic expression",
   266  			args:          args{args: []string{"rc/foo", "buildType notin (debug, test)"}},
   267  			wantResources: []string{"rc/foo"},
   268  			wantErr:       false,
   269  			wantSelector: &metav1.LabelSelector{
   270  				MatchLabels: map[string]string{},
   271  				MatchExpressions: []metav1.LabelSelectorRequirement{
   272  					{
   273  						Key:      "buildType",
   274  						Operator: "NotIn",
   275  						Values:   []string{"debug", "test"},
   276  					},
   277  				},
   278  			},
   279  		},
   280  		{
   281  			name:          "selector error",
   282  			args:          args{args: []string{"rc/foo", "buildType notthis (debug, test)"}},
   283  			wantResources: []string{"rc/foo"},
   284  			wantErr:       true,
   285  			wantSelector: &metav1.LabelSelector{
   286  				MatchLabels:      map[string]string{},
   287  				MatchExpressions: []metav1.LabelSelectorRequirement{},
   288  			},
   289  		},
   290  		{
   291  			name:          "no resource and selector",
   292  			args:          args{args: []string{}},
   293  			wantResources: []string{},
   294  			wantErr:       false,
   295  			wantSelector:  nil,
   296  		},
   297  	}
   298  	for _, tt := range tests {
   299  		gotResources, gotSelector, err := getResourcesAndSelector(tt.args.args)
   300  		if err != nil {
   301  			if !tt.wantErr {
   302  				t.Errorf("%q. getResourcesAndSelector() error = %v, wantErr %v", tt.name, err, tt.wantErr)
   303  			}
   304  			continue
   305  		}
   306  		if !reflect.DeepEqual(gotResources, tt.wantResources) {
   307  			t.Errorf("%q. getResourcesAndSelector() gotResources = %v, want %v", tt.name, gotResources, tt.wantResources)
   308  		}
   309  		if !reflect.DeepEqual(gotSelector, tt.wantSelector) {
   310  			t.Errorf("%q. getResourcesAndSelector() gotSelector = %v, want %v", tt.name, gotSelector, tt.wantSelector)
   311  		}
   312  	}
   313  }
   314  
   315  func TestSelectorTest(t *testing.T) {
   316  	info := &resource.Info{
   317  		Object: &v1.Service{
   318  			TypeMeta:   metav1.TypeMeta{APIVersion: "v1", Kind: "Service"},
   319  			ObjectMeta: metav1.ObjectMeta{Namespace: "some-ns", Name: "cassandra"},
   320  		},
   321  	}
   322  
   323  	labelToSet, err := metav1.ParseToLabelSelector("environment=qa")
   324  	if err != nil {
   325  		t.Fatal(err)
   326  	}
   327  
   328  	iostreams, _, buf, _ := genericiooptions.NewTestIOStreams()
   329  	o := &SetSelectorOptions{
   330  		selector:       labelToSet,
   331  		ResourceFinder: genericclioptions.NewSimpleFakeResourceFinder(info),
   332  		Recorder:       genericclioptions.NoopRecorder{},
   333  		PrintObj:       (&printers.NamePrinter{}).PrintObj,
   334  		IOStreams:      iostreams,
   335  	}
   336  
   337  	if err := o.RunSelector(); err != nil {
   338  		t.Fatal(err)
   339  	}
   340  	if !strings.Contains(buf.String(), "service/cassandra") {
   341  		t.Errorf("did not set selector: %s", buf.String())
   342  	}
   343  }
   344  

View as plain text