...

Source file src/github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/iam/iamclient/dcliamclient_test.go

Documentation: github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/iam/iamclient

     1  // Copyright 2022 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package iamclient
    16  
    17  import (
    18  	"context"
    19  	"reflect"
    20  	"testing"
    21  
    22  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/apis/iam/v1beta1"
    23  
    24  	dcliam "github.com/GoogleCloudPlatform/declarative-resource-client-library/services/google/iam"
    25  	dclunstruct "github.com/GoogleCloudPlatform/declarative-resource-client-library/unstructured"
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  )
    28  
    29  // These variables need to be initialized here because the DCL structs expect
    30  // string pointers.
    31  var (
    32  	emptyEtag        = ""
    33  	testEtag         = "ACAB"
    34  	testRole1        = "roles/computeAdmin"
    35  	testRole2        = "roles/viewer"
    36  	testTitle1       = "FooBar"
    37  	testTitle2       = "BarBaz"
    38  	testDescription1 = "test description"
    39  	testDescription2 = "second description"
    40  	testExpression1  = "request.time < timestamp(\"2020-01-01T00:00:00Z\")"
    41  	testExpression2  = "true"
    42  	testMember1      = "foo@bar.iam.gserviceaccount.com"
    43  )
    44  
    45  func TestDCLPolicyFromKRMPolicy(t *testing.T) {
    46  	tests := []struct {
    47  		name           string
    48  		dclResource    *dclunstruct.Resource
    49  		krmPolicy      *v1beta1.IAMPolicy
    50  		expectedResult *dcliam.Policy
    51  		hasError       bool
    52  	}{
    53  		{
    54  			name: "iam policy no bindings, empty etag",
    55  			krmPolicy: &v1beta1.IAMPolicy{
    56  				TypeMeta: metav1.TypeMeta{
    57  					Kind:       "IAMPolicy",
    58  					APIVersion: "v1beta1",
    59  				},
    60  				Spec: v1beta1.IAMPolicySpec{
    61  					ResourceReference: v1beta1.ResourceReference{
    62  						Kind: "DataprocCluster",
    63  					},
    64  					Bindings: []v1beta1.IAMPolicyBinding{},
    65  					Etag:     "",
    66  				},
    67  			},
    68  			dclResource: &dclunstruct.Resource{
    69  				STV: dclunstruct.ServiceTypeVersion{
    70  					Service: "dataproc",
    71  					Type:    "Cluster",
    72  					Version: "ga",
    73  				},
    74  			},
    75  			expectedResult: &dcliam.Policy{
    76  				Bindings: []dcliam.Binding{},
    77  				Etag:     &emptyEtag,
    78  				Version:  nil,
    79  				Resource: &dclunstruct.Resource{
    80  					STV: dclunstruct.ServiceTypeVersion{
    81  						Service: "dataproc",
    82  						Type:    "Cluster",
    83  						Version: "ga",
    84  					},
    85  				},
    86  			},
    87  		},
    88  		{
    89  			name: "iam policy with bindings no conditions",
    90  			krmPolicy: &v1beta1.IAMPolicy{
    91  				TypeMeta: metav1.TypeMeta{
    92  					Kind:       "IAMPolicy",
    93  					APIVersion: "v1beta1",
    94  				},
    95  				Spec: v1beta1.IAMPolicySpec{
    96  					ResourceReference: v1beta1.ResourceReference{},
    97  					Bindings: []v1beta1.IAMPolicyBinding{
    98  						{
    99  							Members: []v1beta1.Member{
   100  								"foo@bar.iam.gserviceaccount.com",
   101  							},
   102  							Role: testRole1,
   103  						},
   104  					},
   105  					Etag: "",
   106  				},
   107  			},
   108  			dclResource: &dclunstruct.Resource{
   109  				STV: dclunstruct.ServiceTypeVersion{
   110  					Service: "dataproc",
   111  					Type:    "Cluster",
   112  					Version: "ga",
   113  				},
   114  			},
   115  			expectedResult: &dcliam.Policy{
   116  				Bindings: []dcliam.Binding{
   117  					{
   118  						Role: &testRole1,
   119  						Members: []string{
   120  							"foo@bar.iam.gserviceaccount.com",
   121  						},
   122  					},
   123  				},
   124  				Etag:    &emptyEtag,
   125  				Version: nil,
   126  				Resource: &dclunstruct.Resource{
   127  					STV: dclunstruct.ServiceTypeVersion{
   128  						Service: "dataproc",
   129  						Type:    "Cluster",
   130  						Version: "ga",
   131  					},
   132  				},
   133  			},
   134  		},
   135  		{
   136  			name: "iam policy with single binding with conditions",
   137  			krmPolicy: &v1beta1.IAMPolicy{
   138  				TypeMeta: metav1.TypeMeta{
   139  					Kind:       "IAMPolicy",
   140  					APIVersion: "v1beta1",
   141  				},
   142  				Spec: v1beta1.IAMPolicySpec{
   143  					ResourceReference: v1beta1.ResourceReference{},
   144  					Bindings: []v1beta1.IAMPolicyBinding{
   145  						{
   146  							Members: []v1beta1.Member{
   147  								"foo@bar.iam.gserviceaccount.com",
   148  							},
   149  							Role: testRole1,
   150  							Condition: &v1beta1.IAMCondition{
   151  								Title:       testTitle1,
   152  								Description: testDescription1,
   153  								Expression:  testExpression1,
   154  							},
   155  						},
   156  					},
   157  				},
   158  			},
   159  			dclResource: &dclunstruct.Resource{
   160  				STV: dclunstruct.ServiceTypeVersion{
   161  					Service: "dataproc",
   162  					Type:    "Cluster",
   163  					Version: "ga",
   164  				},
   165  			},
   166  			expectedResult: &dcliam.Policy{
   167  				Bindings: []dcliam.Binding{
   168  					{
   169  						Role: &testRole1,
   170  						Members: []string{
   171  							"foo@bar.iam.gserviceaccount.com",
   172  						},
   173  						Condition: &dcliam.Condition{
   174  							Title:       &testTitle1,
   175  							Description: &testDescription1,
   176  							Expression:  &testExpression1,
   177  						},
   178  					},
   179  				},
   180  				Etag: &emptyEtag,
   181  				Resource: &dclunstruct.Resource{
   182  					STV: dclunstruct.ServiceTypeVersion{
   183  						Service: "dataproc",
   184  						Type:    "Cluster",
   185  						Version: "ga",
   186  					},
   187  				},
   188  			},
   189  		},
   190  		{
   191  			name: "iam policy with multiple bindings/member/conditions",
   192  			krmPolicy: &v1beta1.IAMPolicy{
   193  				TypeMeta: metav1.TypeMeta{
   194  					Kind:       "IAMPolicy",
   195  					APIVersion: "v1beta1",
   196  				},
   197  				Spec: v1beta1.IAMPolicySpec{
   198  					ResourceReference: v1beta1.ResourceReference{},
   199  					Bindings: []v1beta1.IAMPolicyBinding{
   200  						{
   201  							Members: []v1beta1.Member{
   202  								"foo@bar.iam.gserviceaccount.com",
   203  								"user@test.iam.gserviceaccount.com",
   204  							},
   205  							Role: testRole1,
   206  							Condition: &v1beta1.IAMCondition{
   207  								Title:       testTitle1,
   208  								Description: testDescription1,
   209  								Expression:  testExpression1,
   210  							},
   211  						},
   212  						{
   213  							Role: "roles/viewer",
   214  							Condition: &v1beta1.IAMCondition{
   215  								Title:       testTitle2,
   216  								Description: testDescription2,
   217  								Expression:  testExpression2,
   218  							},
   219  						},
   220  					},
   221  				},
   222  			},
   223  			dclResource: &dclunstruct.Resource{
   224  				STV: dclunstruct.ServiceTypeVersion{
   225  					Service: "dataproc",
   226  					Type:    "Cluster",
   227  					Version: "ga",
   228  				},
   229  			},
   230  			expectedResult: &dcliam.Policy{
   231  				Bindings: []dcliam.Binding{
   232  					{
   233  						Role: &testRole1,
   234  						Members: []string{
   235  							"foo@bar.iam.gserviceaccount.com",
   236  							"user@test.iam.gserviceaccount.com",
   237  						},
   238  						Condition: &dcliam.Condition{
   239  							Title:       &testTitle1,
   240  							Description: &testDescription1,
   241  							Expression:  &testExpression1,
   242  						},
   243  					},
   244  					{
   245  						Role: &testRole2,
   246  						Condition: &dcliam.Condition{
   247  							Title:       &testTitle2,
   248  							Description: &testDescription2,
   249  							Expression:  &testExpression2,
   250  						},
   251  					},
   252  				},
   253  				Etag: &emptyEtag,
   254  				Resource: &dclunstruct.Resource{
   255  					STV: dclunstruct.ServiceTypeVersion{
   256  						Service: "dataproc",
   257  						Type:    "Cluster",
   258  						Version: "ga",
   259  					},
   260  				},
   261  			},
   262  		},
   263  		{
   264  			name: "iam policy with audit config",
   265  			krmPolicy: &v1beta1.IAMPolicy{
   266  				TypeMeta: metav1.TypeMeta{
   267  					Kind:       "IAMPolicy",
   268  					APIVersion: "v1beta1",
   269  				},
   270  				Spec: v1beta1.IAMPolicySpec{
   271  					ResourceReference: v1beta1.ResourceReference{},
   272  					AuditConfigs: []v1beta1.IAMPolicyAuditConfig{
   273  						{
   274  							Service: "allServices",
   275  							AuditLogConfigs: []v1beta1.AuditLogConfig{
   276  								{
   277  									LogType: "DATA_READ",
   278  									ExemptedMembers: []v1beta1.Member{
   279  										"foo@bar.iam.gserviceaccount.com",
   280  									},
   281  								},
   282  							},
   283  						},
   284  					},
   285  				},
   286  			},
   287  			dclResource: &dclunstruct.Resource{
   288  				STV: dclunstruct.ServiceTypeVersion{
   289  					Service: "dataproc",
   290  					Type:    "Cluster",
   291  					Version: "ga",
   292  				},
   293  			},
   294  			expectedResult: &dcliam.Policy{},
   295  			hasError:       true,
   296  		},
   297  		{
   298  			name: "iam policy with etag set by partial policy controller",
   299  			krmPolicy: &v1beta1.IAMPolicy{
   300  				TypeMeta: metav1.TypeMeta{
   301  					Kind:       "IAMPolicy",
   302  					APIVersion: "v1beta1",
   303  				},
   304  				Spec: v1beta1.IAMPolicySpec{
   305  					ResourceReference: v1beta1.ResourceReference{
   306  						Kind: "DataprocCluster",
   307  					},
   308  					Bindings: []v1beta1.IAMPolicyBinding{},
   309  					Etag:     testEtag,
   310  				},
   311  			},
   312  			dclResource: &dclunstruct.Resource{
   313  				STV: dclunstruct.ServiceTypeVersion{
   314  					Service: "dataproc",
   315  					Type:    "Cluster",
   316  					Version: "ga",
   317  				},
   318  			},
   319  			expectedResult: &dcliam.Policy{
   320  				Bindings: []dcliam.Binding{},
   321  				Etag:     &testEtag,
   322  				Resource: &dclunstruct.Resource{
   323  					STV: dclunstruct.ServiceTypeVersion{
   324  						Service: "dataproc",
   325  						Type:    "Cluster",
   326  						Version: "ga",
   327  					},
   328  				},
   329  			},
   330  		},
   331  	}
   332  	for _, tc := range tests {
   333  		tc := tc
   334  		t.Run(tc.name, func(t *testing.T) {
   335  			actual, err := newDCLPolicyFromKRMPolicy(tc.krmPolicy, tc.dclResource)
   336  			if tc.hasError {
   337  				if err == nil {
   338  					t.Fatalf("expected to get error when converting IAMPolicy from DCLPolicyResource")
   339  				}
   340  				return
   341  			}
   342  			if err != nil {
   343  				t.Fatalf("unexpected error: %v", err)
   344  			}
   345  			if !reflect.DeepEqual(actual, tc.expectedResult) {
   346  				t.Fatalf("got %v, want %v", actual, tc.expectedResult)
   347  			}
   348  		})
   349  	}
   350  }
   351  
   352  func TestIAMPolicyFromDCLResource(t *testing.T) {
   353  	tests := []struct {
   354  		name           string
   355  		dclResource    *dclunstruct.Resource
   356  		origPolicy     *v1beta1.IAMPolicy
   357  		expectedResult *v1beta1.IAMPolicy
   358  		hasError       bool
   359  	}{
   360  		{
   361  			name: "iam policy no bindings",
   362  			dclResource: &dclunstruct.Resource{
   363  				STV: dclunstruct.ServiceTypeVersion{
   364  					Service: "iam",
   365  					Type:    "Policy",
   366  					Version: "ga",
   367  				},
   368  				Object: map[string]interface{}{
   369  					"etag": testEtag,
   370  				},
   371  			},
   372  			origPolicy: &v1beta1.IAMPolicy{
   373  				TypeMeta: metav1.TypeMeta{
   374  					Kind:       "IAMPolicy",
   375  					APIVersion: "v1beta1",
   376  				},
   377  				ObjectMeta: metav1.ObjectMeta{},
   378  				Spec: v1beta1.IAMPolicySpec{
   379  					ResourceReference: v1beta1.ResourceReference{
   380  						Kind: "KindBar",
   381  					},
   382  				},
   383  			},
   384  			expectedResult: &v1beta1.IAMPolicy{
   385  				Spec: v1beta1.IAMPolicySpec{
   386  					ResourceReference: v1beta1.ResourceReference{
   387  						Kind: "KindBar",
   388  					},
   389  					Bindings:     nil,
   390  					AuditConfigs: nil,
   391  					Etag:         testEtag,
   392  				},
   393  			},
   394  		},
   395  		{
   396  			name: "iam policy with binding no conditions",
   397  			dclResource: &dclunstruct.Resource{
   398  				STV: dclunstruct.ServiceTypeVersion{
   399  					Service: "iam",
   400  					Type:    "Policy",
   401  					Version: "ga",
   402  				},
   403  				Object: map[string]interface{}{
   404  					"etag": testEtag,
   405  					"bindings": []interface{}{
   406  						map[string]interface{}{
   407  							"members": []interface{}{
   408  								"foo@bar.iam.gserviceaccount.com",
   409  							},
   410  							"role": testRole1,
   411  						},
   412  					},
   413  				},
   414  			},
   415  			origPolicy: &v1beta1.IAMPolicy{
   416  				TypeMeta: metav1.TypeMeta{
   417  					Kind:       "IAMPolicy",
   418  					APIVersion: "v1beta1",
   419  				},
   420  				ObjectMeta: metav1.ObjectMeta{},
   421  				Spec: v1beta1.IAMPolicySpec{
   422  					ResourceReference: v1beta1.ResourceReference{
   423  						Kind: "KindBar",
   424  					},
   425  				},
   426  			},
   427  			expectedResult: &v1beta1.IAMPolicy{
   428  				Spec: v1beta1.IAMPolicySpec{
   429  					ResourceReference: v1beta1.ResourceReference{
   430  						Kind: "KindBar",
   431  					},
   432  					Bindings: []v1beta1.IAMPolicyBinding{
   433  						{
   434  							Members: []v1beta1.Member{
   435  								"foo@bar.iam.gserviceaccount.com",
   436  							},
   437  							Role: testRole1,
   438  						},
   439  					},
   440  					Etag: testEtag,
   441  				},
   442  			},
   443  		},
   444  		{
   445  			name: "iam policy with binding with condition",
   446  			dclResource: &dclunstruct.Resource{
   447  				STV: dclunstruct.ServiceTypeVersion{
   448  					Service: "iam",
   449  					Type:    "Policy",
   450  					Version: "ga",
   451  				},
   452  				Object: map[string]interface{}{
   453  					"etag": testEtag,
   454  					"bindings": []interface{}{
   455  						map[string]interface{}{
   456  							"members": []interface{}{
   457  								"foo@bar.iam.gserviceaccount.com",
   458  							},
   459  							"role": testRole1,
   460  							"condition": map[string]interface{}{
   461  								"title":       testTitle1,
   462  								"description": testDescription1,
   463  								"expression":  testExpression1,
   464  							},
   465  						},
   466  					},
   467  				},
   468  			},
   469  			origPolicy: &v1beta1.IAMPolicy{
   470  				TypeMeta: metav1.TypeMeta{
   471  					Kind:       "IAMPolicy",
   472  					APIVersion: "v1beta1",
   473  				},
   474  				ObjectMeta: metav1.ObjectMeta{},
   475  				Spec: v1beta1.IAMPolicySpec{
   476  					ResourceReference: v1beta1.ResourceReference{
   477  						Kind: "KindBar",
   478  					},
   479  				},
   480  			},
   481  			expectedResult: &v1beta1.IAMPolicy{
   482  				Spec: v1beta1.IAMPolicySpec{
   483  					ResourceReference: v1beta1.ResourceReference{
   484  						Kind: "KindBar",
   485  					},
   486  					Bindings: []v1beta1.IAMPolicyBinding{
   487  						{
   488  							Members: []v1beta1.Member{
   489  								"foo@bar.iam.gserviceaccount.com",
   490  							},
   491  							Role: testRole1,
   492  							Condition: &v1beta1.IAMCondition{
   493  								Title:       testTitle1,
   494  								Description: testDescription1,
   495  								Expression:  testExpression1,
   496  							},
   497  						},
   498  					},
   499  					Etag: testEtag,
   500  				},
   501  			},
   502  		},
   503  		{
   504  			name: "iam policy with mulitple bindings/members/conditions",
   505  			dclResource: &dclunstruct.Resource{
   506  				STV: dclunstruct.ServiceTypeVersion{
   507  					Service: "iam",
   508  					Type:    "Policy",
   509  					Version: "ga",
   510  				},
   511  				Object: map[string]interface{}{
   512  					"etag": testEtag,
   513  					"bindings": []interface{}{
   514  						map[string]interface{}{
   515  							"members": []interface{}{
   516  								"foo@bar.iam.gserviceaccount.com",
   517  								"user@test.iam.gserviceaccount.com",
   518  							},
   519  							"role": testRole1,
   520  							"condition": map[string]interface{}{
   521  								"title":       testTitle1,
   522  								"description": testDescription1,
   523  								"expression":  testExpression1,
   524  							},
   525  						},
   526  						map[string]interface{}{
   527  							"role": testRole2,
   528  							"condition": map[string]interface{}{
   529  								"title":       testTitle2,
   530  								"description": testDescription2,
   531  								"expression":  testExpression2,
   532  							},
   533  						},
   534  					},
   535  				},
   536  			},
   537  			origPolicy: &v1beta1.IAMPolicy{
   538  				TypeMeta: metav1.TypeMeta{
   539  					Kind:       "IAMPolicy",
   540  					APIVersion: "v1beta1",
   541  				},
   542  				ObjectMeta: metav1.ObjectMeta{},
   543  				Spec: v1beta1.IAMPolicySpec{
   544  					ResourceReference: v1beta1.ResourceReference{
   545  						Kind: "KindBar",
   546  					},
   547  				},
   548  			},
   549  			expectedResult: &v1beta1.IAMPolicy{
   550  				Spec: v1beta1.IAMPolicySpec{
   551  					ResourceReference: v1beta1.ResourceReference{
   552  						Kind: "KindBar",
   553  					},
   554  					Bindings: []v1beta1.IAMPolicyBinding{
   555  						{
   556  							Members: []v1beta1.Member{
   557  								"foo@bar.iam.gserviceaccount.com",
   558  								"user@test.iam.gserviceaccount.com",
   559  							},
   560  							Role: testRole1,
   561  							Condition: &v1beta1.IAMCondition{
   562  								Title:       testTitle1,
   563  								Description: testDescription1,
   564  								Expression:  testExpression1,
   565  							},
   566  						},
   567  						{
   568  							Role: testRole2,
   569  							Condition: &v1beta1.IAMCondition{
   570  								Title:       testTitle2,
   571  								Description: testDescription2,
   572  								Expression:  testExpression2,
   573  							},
   574  						},
   575  					},
   576  					Etag: testEtag,
   577  				},
   578  			},
   579  		},
   580  		{
   581  			name: "error from wrong type",
   582  			dclResource: &dclunstruct.Resource{
   583  				STV: dclunstruct.ServiceTypeVersion{
   584  					Service: "binaryauthorization",
   585  					Type:    "Policy",
   586  					Version: "ga",
   587  				},
   588  				Object: map[string]interface{}{
   589  					"etag": testEtag,
   590  				},
   591  			},
   592  			origPolicy:     &v1beta1.IAMPolicy{},
   593  			expectedResult: &v1beta1.IAMPolicy{},
   594  			hasError:       true,
   595  		},
   596  		{
   597  			name: "error from empty DCLObject etag",
   598  			dclResource: &dclunstruct.Resource{
   599  				STV: dclunstruct.ServiceTypeVersion{
   600  					Service: "iam",
   601  					Type:    "Policy",
   602  					Version: "ga",
   603  				},
   604  				Object: map[string]interface{}{
   605  					"etag": emptyEtag,
   606  				},
   607  			},
   608  			origPolicy: &v1beta1.IAMPolicy{
   609  				TypeMeta: metav1.TypeMeta{
   610  					Kind:       "IAMPolicy",
   611  					APIVersion: "v1beta1",
   612  				},
   613  				ObjectMeta: metav1.ObjectMeta{},
   614  				Spec: v1beta1.IAMPolicySpec{
   615  					ResourceReference: v1beta1.ResourceReference{
   616  						Kind: "KindBar",
   617  					},
   618  				},
   619  			},
   620  			expectedResult: &v1beta1.IAMPolicy{
   621  				Spec: v1beta1.IAMPolicySpec{
   622  					ResourceReference: v1beta1.ResourceReference{
   623  						Kind: "KindBar",
   624  					},
   625  					Bindings:     nil,
   626  					AuditConfigs: nil,
   627  					Etag:         testEtag,
   628  				},
   629  			},
   630  			hasError: true,
   631  		},
   632  	}
   633  	for _, tc := range tests {
   634  		tc := tc
   635  		t.Run(tc.name, func(t *testing.T) {
   636  			actual, err := newIAMPolicyFromDCLResource(tc.dclResource, tc.origPolicy)
   637  			if tc.hasError {
   638  				if err == nil {
   639  					t.Fatalf("expected to get error when converting IAMPolicy from DCLPolicyResource")
   640  				}
   641  				return
   642  			}
   643  			if err != nil {
   644  				t.Fatalf("unexpected error: %v", err)
   645  			}
   646  			if !reflect.DeepEqual(actual, tc.expectedResult) {
   647  				t.Fatalf("got %v, want %v", actual, tc.expectedResult)
   648  			}
   649  		})
   650  	}
   651  }
   652  
   653  func TestDCLMemberFromKRMMember(t *testing.T) {
   654  	tests := []struct {
   655  		name           string
   656  		dclResource    *dclunstruct.Resource
   657  		krmMember      *v1beta1.IAMPolicyMember
   658  		expectedResult *dcliam.Member
   659  		hasError       bool
   660  	}{
   661  		{
   662  			name: "simple iam policy member",
   663  			dclResource: &dclunstruct.Resource{
   664  				STV: dclunstruct.ServiceTypeVersion{
   665  					Service: "dataproc",
   666  					Type:    "Cluster",
   667  					Version: "ga",
   668  				},
   669  			},
   670  			krmMember: &v1beta1.IAMPolicyMember{
   671  				TypeMeta: metav1.TypeMeta{
   672  					Kind:       "IAMPolicyMember",
   673  					APIVersion: "v1beta1",
   674  				},
   675  				Spec: v1beta1.IAMPolicyMemberSpec{
   676  					ResourceReference: v1beta1.ResourceReference{
   677  						Kind: "DataprocCluster",
   678  					},
   679  					Member: v1beta1.Member(testMember1),
   680  					Role:   testRole1,
   681  				},
   682  			},
   683  			expectedResult: &dcliam.Member{
   684  				Role:   &testRole1,
   685  				Member: &testMember1,
   686  				Resource: &dclunstruct.Resource{
   687  					STV: dclunstruct.ServiceTypeVersion{
   688  						Service: "dataproc",
   689  						Type:    "Cluster",
   690  						Version: "ga",
   691  					},
   692  				},
   693  			},
   694  		},
   695  		{
   696  			name: "error from both member and memberFrom used",
   697  			dclResource: &dclunstruct.Resource{
   698  				STV: dclunstruct.ServiceTypeVersion{
   699  					Service: "dataproc",
   700  					Type:    "Cluster",
   701  					Version: "ga",
   702  				},
   703  			},
   704  			krmMember: &v1beta1.IAMPolicyMember{
   705  				TypeMeta: metav1.TypeMeta{
   706  					Kind:       "IAMPolicyMember",
   707  					APIVersion: "v1beta1",
   708  				},
   709  				Spec: v1beta1.IAMPolicyMemberSpec{
   710  					ResourceReference: v1beta1.ResourceReference{
   711  						Kind: "DataprocCluster",
   712  					},
   713  					Member: v1beta1.Member(testMember1),
   714  					MemberFrom: &v1beta1.MemberSource{
   715  						ServiceAccountRef: &v1beta1.MemberReference{
   716  							Namespace: "ns-a",
   717  							Name:      "foobar",
   718  						},
   719  					},
   720  					Role: testRole1,
   721  				},
   722  			},
   723  			hasError: true,
   724  		},
   725  		{
   726  			name: "error from neither member and memberFrom used",
   727  			dclResource: &dclunstruct.Resource{
   728  				STV: dclunstruct.ServiceTypeVersion{
   729  					Service: "dataproc",
   730  					Type:    "Cluster",
   731  					Version: "ga",
   732  				},
   733  			},
   734  			krmMember: &v1beta1.IAMPolicyMember{
   735  				TypeMeta: metav1.TypeMeta{
   736  					Kind:       "IAMPolicyMember",
   737  					APIVersion: "v1beta1",
   738  				},
   739  				Spec: v1beta1.IAMPolicyMemberSpec{
   740  					ResourceReference: v1beta1.ResourceReference{
   741  						Kind: "DataprocCluster",
   742  					},
   743  					Role: testRole1,
   744  				},
   745  			},
   746  			hasError: true,
   747  		},
   748  		{
   749  			name: "error from member having conditions",
   750  			dclResource: &dclunstruct.Resource{
   751  				STV: dclunstruct.ServiceTypeVersion{
   752  					Service: "dataproc",
   753  					Type:    "Cluster",
   754  					Version: "ga",
   755  				},
   756  			},
   757  			krmMember: &v1beta1.IAMPolicyMember{
   758  				TypeMeta: metav1.TypeMeta{
   759  					Kind:       "IAMPolicyMember",
   760  					APIVersion: "v1beta1",
   761  				},
   762  				Spec: v1beta1.IAMPolicyMemberSpec{
   763  					ResourceReference: v1beta1.ResourceReference{
   764  						Kind: "DataprocCluster",
   765  					},
   766  					Role:   testRole1,
   767  					Member: v1beta1.Member(testMember1),
   768  					Condition: &v1beta1.IAMCondition{
   769  						Title:       testTitle1,
   770  						Description: testDescription1,
   771  						Expression:  testExpression1,
   772  					},
   773  				},
   774  			},
   775  			hasError: true,
   776  		},
   777  	}
   778  	for _, tc := range tests {
   779  		tc := tc
   780  		t.Run(tc.name, func(t *testing.T) {
   781  			// Unit tests will not include testing the `memberFrom` field. This will
   782  			// instead be tested in the integration tests because `memberFrom` will require
   783  			// calling on an actual TF-based resource to resolve (which should not occur
   784  			// in unit tests).
   785  			actual, err := newDCLPolicyMemberFromKRMPolicyMember(context.TODO(), tc.krmMember, tc.dclResource, "", nil)
   786  			if tc.hasError {
   787  				if err == nil {
   788  					t.Fatalf("expected to get error when converting IAMPolicy from DCLPolicyResource")
   789  				}
   790  				return
   791  			}
   792  			if err != nil {
   793  				t.Fatalf("unexpected error: %v", err)
   794  			}
   795  			if !reflect.DeepEqual(actual, tc.expectedResult) {
   796  				t.Fatalf("got %v, want %v", actual, tc.expectedResult)
   797  			}
   798  		})
   799  	}
   800  }
   801  
   802  func TestKRMMemberFromDCLMember(t *testing.T) {
   803  	tests := []struct {
   804  		name           string
   805  		dclResource    *dclunstruct.Resource
   806  		krmMember      *v1beta1.IAMPolicyMember
   807  		expectedResult *v1beta1.IAMPolicyMember
   808  		hasError       bool
   809  	}{
   810  		{
   811  			name: "simple dcl policy member",
   812  			dclResource: &dclunstruct.Resource{
   813  				Object: map[string]interface{}{
   814  					"role":   testRole1,
   815  					"member": testMember1,
   816  				},
   817  				STV: dclunstruct.ServiceTypeVersion{
   818  					Service: "iam",
   819  					Type:    "PolicyMember",
   820  					Version: "ga",
   821  				},
   822  			},
   823  			krmMember: &v1beta1.IAMPolicyMember{
   824  				ObjectMeta: metav1.ObjectMeta{
   825  					Name: "FooBar",
   826  				},
   827  				Spec: v1beta1.IAMPolicyMemberSpec{
   828  					ResourceReference: v1beta1.ResourceReference{
   829  						Kind:       "DataprocCluster",
   830  						Name:       "Dep",
   831  						APIVersion: "v1beta1",
   832  					},
   833  					Member: v1beta1.Member(testMember1),
   834  				},
   835  			},
   836  			expectedResult: &v1beta1.IAMPolicyMember{
   837  				ObjectMeta: metav1.ObjectMeta{
   838  					Name: "FooBar",
   839  				},
   840  				Spec: v1beta1.IAMPolicyMemberSpec{
   841  					Role:   testRole1,
   842  					Member: v1beta1.Member(testMember1),
   843  					ResourceReference: v1beta1.ResourceReference{
   844  						Kind:       "DataprocCluster",
   845  						Name:       "Dep",
   846  						APIVersion: "v1beta1",
   847  					},
   848  				},
   849  			},
   850  		},
   851  		{
   852  			name: "error from wrong type",
   853  			dclResource: &dclunstruct.Resource{
   854  				Object: map[string]interface{}{
   855  					"role":   testRole1,
   856  					"member": testMember1,
   857  				},
   858  				STV: dclunstruct.ServiceTypeVersion{
   859  					Service: "dataproc",
   860  					Type:    "Member",
   861  					Version: "ga",
   862  				},
   863  			},
   864  			hasError: true,
   865  		},
   866  	}
   867  	for _, tc := range tests {
   868  		tc := tc
   869  		t.Run(tc.name, func(t *testing.T) {
   870  			actual, err := newIAMPolicyMemberFromDCLResource(tc.dclResource, tc.krmMember)
   871  			if tc.hasError {
   872  				if err == nil {
   873  					t.Fatalf("expected to get error when converting IAMPolicy from DCLPolicyResource")
   874  				}
   875  				return
   876  			}
   877  			if err != nil {
   878  				t.Fatalf("unexpected error: %v", err)
   879  			}
   880  			if !reflect.DeepEqual(actual, tc.expectedResult) {
   881  				t.Fatalf("got %v, want %v", actual, tc.expectedResult)
   882  			}
   883  		})
   884  	}
   885  }
   886  

View as plain text