...

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

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

     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 set
    18  
    19  import (
    20  	"reflect"
    21  	"testing"
    22  
    23  	rbacv1 "k8s.io/api/rbac/v1"
    24  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    25  	"k8s.io/apimachinery/pkg/runtime"
    26  	"k8s.io/cli-runtime/pkg/resource"
    27  	cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
    28  )
    29  
    30  func TestValidate(t *testing.T) {
    31  	tf := cmdtesting.NewTestFactory().WithNamespace("test")
    32  	defer tf.Cleanup()
    33  
    34  	tests := map[string]struct {
    35  		options   *SubjectOptions
    36  		expectErr bool
    37  	}{
    38  		"test-missing-subjects": {
    39  			options: &SubjectOptions{
    40  				Users:           []string{},
    41  				Groups:          []string{},
    42  				ServiceAccounts: []string{},
    43  			},
    44  			expectErr: true,
    45  		},
    46  		"test-invalid-serviceaccounts": {
    47  			options: &SubjectOptions{
    48  				Users:           []string{},
    49  				Groups:          []string{},
    50  				ServiceAccounts: []string{"foo"},
    51  			},
    52  			expectErr: true,
    53  		},
    54  		"test-missing-serviceaccounts-name": {
    55  			options: &SubjectOptions{
    56  				Users:           []string{},
    57  				Groups:          []string{},
    58  				ServiceAccounts: []string{"foo:"},
    59  			},
    60  			expectErr: true,
    61  		},
    62  		"test-missing-serviceaccounts-namespace": {
    63  			options: &SubjectOptions{
    64  				Infos: []*resource.Info{
    65  					{
    66  						Object: &rbacv1.ClusterRoleBinding{
    67  							ObjectMeta: metav1.ObjectMeta{
    68  								Name: "clusterrolebinding",
    69  							},
    70  							RoleRef: rbacv1.RoleRef{
    71  								APIGroup: "rbac.authorization.k8s.io",
    72  								Kind:     "ClusterRole",
    73  								Name:     "role",
    74  							},
    75  						},
    76  					},
    77  				},
    78  				Users:           []string{},
    79  				Groups:          []string{},
    80  				ServiceAccounts: []string{":foo"},
    81  			},
    82  			expectErr: true,
    83  		},
    84  		"test-valid-case": {
    85  			options: &SubjectOptions{
    86  				Infos: []*resource.Info{
    87  					{
    88  						Object: &rbacv1.RoleBinding{
    89  							ObjectMeta: metav1.ObjectMeta{
    90  								Name:      "rolebinding",
    91  								Namespace: "one",
    92  							},
    93  							RoleRef: rbacv1.RoleRef{
    94  								APIGroup: "rbac.authorization.k8s.io",
    95  								Kind:     "ClusterRole",
    96  								Name:     "role",
    97  							},
    98  						},
    99  					},
   100  				},
   101  				Users:           []string{"foo"},
   102  				Groups:          []string{"foo"},
   103  				ServiceAccounts: []string{"ns:foo"},
   104  			},
   105  			expectErr: false,
   106  		},
   107  	}
   108  
   109  	for name, test := range tests {
   110  		err := test.options.Validate()
   111  		if test.expectErr && err != nil {
   112  			continue
   113  		}
   114  		if !test.expectErr && err != nil {
   115  			t.Errorf("%s: unexpected error: %v", name, err)
   116  		}
   117  	}
   118  }
   119  
   120  func TestUpdateSubjectForObject(t *testing.T) {
   121  	tests := []struct {
   122  		Name     string
   123  		obj      runtime.Object
   124  		subjects []rbacv1.Subject
   125  		expected []rbacv1.Subject
   126  		wantErr  bool
   127  	}{
   128  		{
   129  			Name: "invalid object type",
   130  			obj: &rbacv1.Role{
   131  				ObjectMeta: metav1.ObjectMeta{
   132  					Name:      "role",
   133  					Namespace: "one",
   134  				},
   135  			},
   136  			wantErr: true,
   137  		},
   138  		{
   139  			Name: "add resource with users in rolebinding",
   140  			obj: &rbacv1.RoleBinding{
   141  				ObjectMeta: metav1.ObjectMeta{
   142  					Name:      "rolebinding",
   143  					Namespace: "one",
   144  				},
   145  				Subjects: []rbacv1.Subject{
   146  					{
   147  						APIGroup: "rbac.authorization.k8s.io",
   148  						Kind:     "User",
   149  						Name:     "a",
   150  					},
   151  				},
   152  			},
   153  			subjects: []rbacv1.Subject{
   154  				{
   155  					APIGroup: "rbac.authorization.k8s.io",
   156  					Kind:     "User",
   157  					Name:     "a",
   158  				},
   159  				{
   160  					APIGroup: "rbac.authorization.k8s.io",
   161  					Kind:     "User",
   162  					Name:     "b",
   163  				},
   164  			},
   165  			expected: []rbacv1.Subject{
   166  				{
   167  					APIGroup: "rbac.authorization.k8s.io",
   168  					Kind:     "User",
   169  					Name:     "a",
   170  				},
   171  				{
   172  					APIGroup: "rbac.authorization.k8s.io",
   173  					Kind:     "User",
   174  					Name:     "b",
   175  				},
   176  			},
   177  			wantErr: false,
   178  		},
   179  		{
   180  			Name: "add resource with groups in rolebinding",
   181  			obj: &rbacv1.RoleBinding{
   182  				ObjectMeta: metav1.ObjectMeta{
   183  					Name:      "rolebinding",
   184  					Namespace: "one",
   185  				},
   186  				Subjects: []rbacv1.Subject{
   187  					{
   188  						APIGroup: "rbac.authorization.k8s.io",
   189  						Kind:     "Group",
   190  						Name:     "a",
   191  					},
   192  				},
   193  			},
   194  			subjects: []rbacv1.Subject{
   195  				{
   196  					APIGroup: "rbac.authorization.k8s.io",
   197  					Kind:     "Group",
   198  					Name:     "a",
   199  				},
   200  				{
   201  					APIGroup: "rbac.authorization.k8s.io",
   202  					Kind:     "Group",
   203  					Name:     "b",
   204  				},
   205  			},
   206  			expected: []rbacv1.Subject{
   207  				{
   208  					APIGroup: "rbac.authorization.k8s.io",
   209  					Kind:     "Group",
   210  					Name:     "a",
   211  				},
   212  				{
   213  					APIGroup: "rbac.authorization.k8s.io",
   214  					Kind:     "Group",
   215  					Name:     "b",
   216  				},
   217  			},
   218  			wantErr: false,
   219  		},
   220  		{
   221  			Name: "add resource with serviceaccounts in rolebinding",
   222  			obj: &rbacv1.RoleBinding{
   223  				ObjectMeta: metav1.ObjectMeta{
   224  					Name:      "rolebinding",
   225  					Namespace: "one",
   226  				},
   227  				Subjects: []rbacv1.Subject{
   228  					{
   229  						Kind:      "ServiceAccount",
   230  						Namespace: "one",
   231  						Name:      "a",
   232  					},
   233  				},
   234  			},
   235  			subjects: []rbacv1.Subject{
   236  				{
   237  					Kind:      "ServiceAccount",
   238  					Namespace: "one",
   239  					Name:      "a",
   240  				},
   241  				{
   242  					Kind:      "ServiceAccount",
   243  					Namespace: "one",
   244  					Name:      "b",
   245  				},
   246  			},
   247  			expected: []rbacv1.Subject{
   248  				{
   249  					Kind:      "ServiceAccount",
   250  					Namespace: "one",
   251  					Name:      "a",
   252  				},
   253  				{
   254  					Kind:      "ServiceAccount",
   255  					Namespace: "one",
   256  					Name:      "b",
   257  				},
   258  			},
   259  			wantErr: false,
   260  		},
   261  		{
   262  			Name: "add resource with serviceaccounts in clusterrolebinding",
   263  			obj: &rbacv1.ClusterRoleBinding{
   264  				ObjectMeta: metav1.ObjectMeta{
   265  					Name: "clusterrolebinding",
   266  				},
   267  				Subjects: []rbacv1.Subject{
   268  					{
   269  						APIGroup: "rbac.authorization.k8s.io",
   270  						Kind:     "User",
   271  						Name:     "a",
   272  					},
   273  					{
   274  						APIGroup: "rbac.authorization.k8s.io",
   275  						Kind:     "Group",
   276  						Name:     "a",
   277  					},
   278  				},
   279  			},
   280  			subjects: []rbacv1.Subject{
   281  				{
   282  					Kind:      "ServiceAccount",
   283  					Namespace: "one",
   284  					Name:      "a",
   285  				},
   286  			},
   287  			expected: []rbacv1.Subject{
   288  				{
   289  					APIGroup: "rbac.authorization.k8s.io",
   290  					Kind:     "User",
   291  					Name:     "a",
   292  				},
   293  				{
   294  					APIGroup: "rbac.authorization.k8s.io",
   295  					Kind:     "Group",
   296  					Name:     "a",
   297  				},
   298  				{
   299  					Kind:      "ServiceAccount",
   300  					Namespace: "one",
   301  					Name:      "a",
   302  				},
   303  			},
   304  			wantErr: false,
   305  		},
   306  	}
   307  	for _, tt := range tests {
   308  		if _, err := updateSubjectForObject(tt.obj, tt.subjects, addSubjects); (err != nil) != tt.wantErr {
   309  			t.Errorf("%q. updateSubjectForObject() error = %v, wantErr %v", tt.Name, err, tt.wantErr)
   310  		}
   311  
   312  		want := tt.expected
   313  		var got []rbacv1.Subject
   314  		switch t := tt.obj.(type) {
   315  		case *rbacv1.RoleBinding:
   316  			got = t.Subjects
   317  		case *rbacv1.ClusterRoleBinding:
   318  			got = t.Subjects
   319  		}
   320  		if !reflect.DeepEqual(got, want) {
   321  			t.Errorf("%q. updateSubjectForObject() failed", tt.Name)
   322  			t.Errorf("Got: %v", got)
   323  			t.Errorf("Want: %v", want)
   324  		}
   325  	}
   326  }
   327  
   328  func TestAddSubject(t *testing.T) {
   329  	tests := []struct {
   330  		Name       string
   331  		existing   []rbacv1.Subject
   332  		subjects   []rbacv1.Subject
   333  		expected   []rbacv1.Subject
   334  		wantChange bool
   335  	}{
   336  		{
   337  			Name: "add resource with users",
   338  			existing: []rbacv1.Subject{
   339  				{
   340  					APIGroup: "rbac.authorization.k8s.io",
   341  					Kind:     "User",
   342  					Name:     "a",
   343  				},
   344  				{
   345  					APIGroup: "rbac.authorization.k8s.io",
   346  					Kind:     "User",
   347  					Name:     "b",
   348  				},
   349  			},
   350  			subjects: []rbacv1.Subject{
   351  				{
   352  					APIGroup: "rbac.authorization.k8s.io",
   353  					Kind:     "User",
   354  					Name:     "a",
   355  				},
   356  			},
   357  			expected: []rbacv1.Subject{
   358  				{
   359  					APIGroup: "rbac.authorization.k8s.io",
   360  					Kind:     "User",
   361  					Name:     "a",
   362  				},
   363  				{
   364  					APIGroup: "rbac.authorization.k8s.io",
   365  					Kind:     "User",
   366  					Name:     "b",
   367  				},
   368  			},
   369  			wantChange: false,
   370  		},
   371  		{
   372  			Name: "add resource with serviceaccounts",
   373  			existing: []rbacv1.Subject{
   374  				{
   375  					Kind:      "ServiceAccount",
   376  					Namespace: "one",
   377  					Name:      "a",
   378  				},
   379  				{
   380  					Kind:      "ServiceAccount",
   381  					Namespace: "one",
   382  					Name:      "b",
   383  				},
   384  			},
   385  			subjects: []rbacv1.Subject{
   386  				{
   387  					Kind:      "ServiceAccount",
   388  					Namespace: "two",
   389  					Name:      "a",
   390  				},
   391  			},
   392  			expected: []rbacv1.Subject{
   393  				{
   394  					Kind:      "ServiceAccount",
   395  					Namespace: "one",
   396  					Name:      "a",
   397  				},
   398  				{
   399  					Kind:      "ServiceAccount",
   400  					Namespace: "one",
   401  					Name:      "b",
   402  				},
   403  				{
   404  					Kind:      "ServiceAccount",
   405  					Namespace: "two",
   406  					Name:      "a",
   407  				},
   408  			},
   409  			wantChange: true,
   410  		},
   411  	}
   412  	for _, tt := range tests {
   413  		changed := false
   414  		var got []rbacv1.Subject
   415  		if changed, got = addSubjects(tt.existing, tt.subjects); (changed != false) != tt.wantChange {
   416  			t.Errorf("%q. addSubjects() changed = %v, wantChange = %v", tt.Name, changed, tt.wantChange)
   417  		}
   418  
   419  		want := tt.expected
   420  		if !reflect.DeepEqual(got, want) {
   421  			t.Errorf("%q. addSubjects() failed", tt.Name)
   422  			t.Errorf("Got: %v", got)
   423  			t.Errorf("Want: %v", want)
   424  		}
   425  	}
   426  }
   427  

View as plain text