...

Source file src/github.com/GoogleCloudPlatform/k8s-config-connector/pkg/webhook/container_annotation_handler_test.go

Documentation: github.com/GoogleCloudPlatform/k8s-config-connector/pkg/webhook

     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 webhook
    16  
    17  import (
    18  	"testing"
    19  
    20  	dclmetadata "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/dcl/metadata"
    21  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/k8s"
    22  	testutil "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test"
    23  	testdclschemaloader "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/dclschemaloader"
    24  	testservicemappingloader "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/servicemappingloader"
    25  	testservicemetadataloader "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/servicemetadataloader"
    26  
    27  	"github.com/google/go-cmp/cmp"
    28  	"github.com/nasa9084/go-openapi"
    29  	corev1 "k8s.io/api/core/v1"
    30  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    31  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    32  )
    33  
    34  func TestHandleContainerAnnotationsForDCLBasedResources(t *testing.T) {
    35  	tests := []struct {
    36  		name   string
    37  		obj    *unstructured.Unstructured
    38  		newObj *unstructured.Unstructured
    39  		ns     *corev1.Namespace
    40  		schema *openapi.Schema
    41  		denied bool
    42  	}{
    43  		{
    44  			name: "no defaulting if resource supports neither containers nor hierarchical references",
    45  			obj: &unstructured.Unstructured{
    46  				Object: map[string]interface{}{
    47  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
    48  					"kind":       "Test6NoContainerOrHierarchicalRef",
    49  					"metadata": map[string]interface{}{
    50  						"name": "resource-name",
    51  					},
    52  				},
    53  			},
    54  			newObj: &unstructured.Unstructured{
    55  				Object: map[string]interface{}{
    56  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
    57  					"kind":       "Test6NoContainerOrHierarchicalRef",
    58  					"metadata": map[string]interface{}{
    59  						"name": "resource-name",
    60  					},
    61  				},
    62  			},
    63  			ns: &corev1.Namespace{
    64  				ObjectMeta: metav1.ObjectMeta{
    65  					Annotations: map[string]string{
    66  						k8s.ProjectIDAnnotation: "project-id-from-namespace-annotation",
    67  					},
    68  					Name: "namespace-name",
    69  				},
    70  			},
    71  			schema: &openapi.Schema{
    72  				Type: "object",
    73  			},
    74  		},
    75  
    76  		// Test defaulting of container annotations for resources which only
    77  		// support container annotations.
    78  		// TODO(b/186159460): Delete the following tests once all resources
    79  		// support hierarchical references.
    80  		{
    81  			name: "no defaulting if resource already has annotation (project-scoped resource which only supports container annotations)",
    82  			obj: &unstructured.Unstructured{
    83  				Object: map[string]interface{}{
    84  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
    85  					"kind":       "Test6OnlyContainer",
    86  					"metadata": map[string]interface{}{
    87  						"annotations": map[string]interface{}{
    88  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
    89  						},
    90  						"name": "resource-name",
    91  					},
    92  				},
    93  			},
    94  			newObj: &unstructured.Unstructured{
    95  				Object: map[string]interface{}{
    96  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
    97  					"kind":       "Test6OnlyContainer",
    98  					"metadata": map[string]interface{}{
    99  						"annotations": map[string]interface{}{
   100  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
   101  						},
   102  						"name": "resource-name",
   103  					},
   104  				},
   105  			},
   106  			ns: &corev1.Namespace{
   107  				ObjectMeta: metav1.ObjectMeta{
   108  					Annotations: map[string]string{
   109  						k8s.ProjectIDAnnotation: "project-id-from-namespace-annotation",
   110  					},
   111  					Name: "namespace-name",
   112  				},
   113  			},
   114  			schema: &openapi.Schema{
   115  				Type: "object",
   116  				Extension: map[string]interface{}{
   117  					"x-dcl-parent-container": "project",
   118  				},
   119  			},
   120  		},
   121  		{
   122  			name: "default resource-level annotation from namespace annotation (project-scoped resource which only supports container annotations)",
   123  			obj: &unstructured.Unstructured{
   124  				Object: map[string]interface{}{
   125  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   126  					"kind":       "Test6OnlyContainer",
   127  					"metadata": map[string]interface{}{
   128  						"name": "resource-name",
   129  					},
   130  				},
   131  			},
   132  			newObj: &unstructured.Unstructured{
   133  				Object: map[string]interface{}{
   134  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   135  					"kind":       "Test6OnlyContainer",
   136  					"metadata": map[string]interface{}{
   137  						"annotations": map[string]interface{}{
   138  							k8s.ProjectIDAnnotation: "project-id-from-namespace-annotation",
   139  						},
   140  						"name": "resource-name",
   141  					},
   142  				},
   143  			},
   144  			ns: &corev1.Namespace{
   145  				ObjectMeta: metav1.ObjectMeta{
   146  					Annotations: map[string]string{
   147  						k8s.ProjectIDAnnotation: "project-id-from-namespace-annotation",
   148  					},
   149  					Name: "namespace-name",
   150  				},
   151  			},
   152  			schema: &openapi.Schema{
   153  				Type: "object",
   154  				Extension: map[string]interface{}{
   155  					"x-dcl-parent-container": "project",
   156  				},
   157  			},
   158  		},
   159  		{
   160  			name: "default resource-level annotation from namespace annotation (folder-scoped resource which only supports container annotations)",
   161  			obj: &unstructured.Unstructured{
   162  				Object: map[string]interface{}{
   163  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   164  					"kind":       "Test6OnlyContainer",
   165  					"metadata": map[string]interface{}{
   166  						"name": "resource-name",
   167  					},
   168  				},
   169  			},
   170  			newObj: &unstructured.Unstructured{
   171  				Object: map[string]interface{}{
   172  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   173  					"kind":       "Test6OnlyContainer",
   174  					"metadata": map[string]interface{}{
   175  						"annotations": map[string]interface{}{
   176  							k8s.FolderIDAnnotation: "folder-id-from-namespace-annotation",
   177  						},
   178  						"name": "resource-name",
   179  					},
   180  				},
   181  			},
   182  			ns: &corev1.Namespace{
   183  				ObjectMeta: metav1.ObjectMeta{
   184  					Annotations: map[string]string{
   185  						k8s.FolderIDAnnotation: "folder-id-from-namespace-annotation",
   186  					},
   187  					Name: "namespace-name",
   188  				},
   189  			},
   190  			schema: &openapi.Schema{
   191  				Type: "object",
   192  				Extension: map[string]interface{}{
   193  					"x-dcl-parent-container": "folder",
   194  				},
   195  			},
   196  		},
   197  		{
   198  			name: "default resource-level annotation from namespace annotation (organization-scoped resource which only supports container annotations)",
   199  			obj: &unstructured.Unstructured{
   200  				Object: map[string]interface{}{
   201  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   202  					"kind":       "Test6OnlyContainer",
   203  					"metadata": map[string]interface{}{
   204  						"name": "resource-name",
   205  					},
   206  				},
   207  			},
   208  			newObj: &unstructured.Unstructured{
   209  				Object: map[string]interface{}{
   210  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   211  					"kind":       "Test6OnlyContainer",
   212  					"metadata": map[string]interface{}{
   213  						"annotations": map[string]interface{}{
   214  							k8s.OrgIDAnnotation: "organization-id-from-namespace-annotation",
   215  						},
   216  						"name": "resource-name",
   217  					},
   218  				},
   219  			},
   220  			ns: &corev1.Namespace{
   221  				ObjectMeta: metav1.ObjectMeta{
   222  					Annotations: map[string]string{
   223  						k8s.OrgIDAnnotation: "organization-id-from-namespace-annotation",
   224  					},
   225  					Name: "namespace-name",
   226  				},
   227  			},
   228  			schema: &openapi.Schema{
   229  				Type: "object",
   230  				Extension: map[string]interface{}{
   231  					"x-dcl-parent-container": "organization",
   232  				},
   233  			},
   234  		},
   235  		{
   236  			name: "default resource-level annotation from namespace name if namespace has no annotation (project-scoped resource which only supports container annotations)",
   237  			obj: &unstructured.Unstructured{
   238  				Object: map[string]interface{}{
   239  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   240  					"kind":       "Test6OnlyContainer",
   241  					"metadata": map[string]interface{}{
   242  						"name": "resource-name",
   243  					},
   244  				},
   245  			},
   246  			newObj: &unstructured.Unstructured{
   247  				Object: map[string]interface{}{
   248  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   249  					"kind":       "Test6OnlyContainer",
   250  					"metadata": map[string]interface{}{
   251  						"annotations": map[string]interface{}{
   252  							k8s.ProjectIDAnnotation: "namespace-name",
   253  						},
   254  						"name": "resource-name",
   255  					},
   256  				},
   257  			},
   258  			ns: &corev1.Namespace{
   259  				ObjectMeta: metav1.ObjectMeta{
   260  					Name: "namespace-name",
   261  				},
   262  			},
   263  			schema: &openapi.Schema{
   264  				Type: "object",
   265  				Extension: map[string]interface{}{
   266  					"x-dcl-parent-container": "project",
   267  				},
   268  			},
   269  		},
   270  		{
   271  			name: "deny resource if no namespace annotation (non-project-scoped resource which only supports container annotations)",
   272  			obj: &unstructured.Unstructured{
   273  				Object: map[string]interface{}{
   274  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   275  					"kind":       "Test6OnlyContainer",
   276  					"metadata": map[string]interface{}{
   277  						"name": "resource-name",
   278  					},
   279  				},
   280  			},
   281  			ns: &corev1.Namespace{
   282  				ObjectMeta: metav1.ObjectMeta{
   283  					Name: "namespace-name",
   284  				},
   285  			},
   286  			schema: &openapi.Schema{
   287  				Type: "object",
   288  				Extension: map[string]interface{}{
   289  					"x-dcl-parent-container": "folder",
   290  				},
   291  			},
   292  			denied: true,
   293  		},
   294  
   295  		// Test defaulting of hierarchical references for resources which
   296  		// support both container annotations and hierarchical references.
   297  		{
   298  			name: "no defaulting if resource already has reference (project-scoped resource which supports both container annotations and hierarchical references)",
   299  			obj: &unstructured.Unstructured{
   300  				Object: map[string]interface{}{
   301  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   302  					"kind":       "Test6BothContainerAndHierarchicalRef",
   303  					"metadata": map[string]interface{}{
   304  						"annotations": map[string]interface{}{
   305  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
   306  						},
   307  						"name": "resource-name",
   308  					},
   309  					"spec": map[string]interface{}{
   310  						"projectRef": map[string]interface{}{
   311  							"name": "project-id-from-spec",
   312  						},
   313  					},
   314  				},
   315  			},
   316  			newObj: &unstructured.Unstructured{
   317  				Object: map[string]interface{}{
   318  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   319  					"kind":       "Test6BothContainerAndHierarchicalRef",
   320  					"metadata": map[string]interface{}{
   321  						"annotations": map[string]interface{}{
   322  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
   323  						},
   324  						"name": "resource-name",
   325  					},
   326  					"spec": map[string]interface{}{
   327  						"projectRef": map[string]interface{}{
   328  							"name": "project-id-from-spec",
   329  						},
   330  					},
   331  				},
   332  			},
   333  			schema: &openapi.Schema{
   334  				Type: "object",
   335  				Properties: map[string]*openapi.Schema{
   336  					"project": &openapi.Schema{
   337  						Type: "string",
   338  						Extension: map[string]interface{}{
   339  							"x-dcl-references": []interface{}{
   340  								map[interface{}]interface{}{
   341  									"field":    "name",
   342  									"parent":   true,
   343  									"resource": "Cloudresourcemanager/Project",
   344  								},
   345  							},
   346  						},
   347  					},
   348  				},
   349  				Extension: map[string]interface{}{
   350  					"x-dcl-parent-container": "project",
   351  				},
   352  			},
   353  			ns: &corev1.Namespace{
   354  				ObjectMeta: metav1.ObjectMeta{
   355  					Annotations: map[string]string{
   356  						k8s.ProjectIDAnnotation: "project-id-from-namespace-annotation",
   357  					},
   358  					Name: "namespace-name",
   359  				},
   360  			},
   361  		},
   362  		{
   363  			name: "default reference from resource annotation (project-scoped resource which supports both container annotations and hierarchical references)",
   364  			obj: &unstructured.Unstructured{
   365  				Object: map[string]interface{}{
   366  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   367  					"kind":       "Test6BothContainerAndHierarchicalRef",
   368  					"metadata": map[string]interface{}{
   369  						"annotations": map[string]interface{}{
   370  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
   371  						},
   372  						"name": "resource-name",
   373  					},
   374  				},
   375  			},
   376  			newObj: &unstructured.Unstructured{
   377  				Object: map[string]interface{}{
   378  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   379  					"kind":       "Test6BothContainerAndHierarchicalRef",
   380  					"metadata": map[string]interface{}{
   381  						"annotations": map[string]interface{}{
   382  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
   383  						},
   384  						"name": "resource-name",
   385  					},
   386  					"spec": map[string]interface{}{
   387  						"projectRef": map[string]interface{}{
   388  							"external": "project-id-from-resource-annotation",
   389  						},
   390  					},
   391  				},
   392  			},
   393  			schema: &openapi.Schema{
   394  				Type: "object",
   395  				Properties: map[string]*openapi.Schema{
   396  					"project": &openapi.Schema{
   397  						Type: "string",
   398  						Extension: map[string]interface{}{
   399  							"x-dcl-references": []interface{}{
   400  								map[interface{}]interface{}{
   401  									"field":    "name",
   402  									"parent":   true,
   403  									"resource": "Cloudresourcemanager/Project",
   404  								},
   405  							},
   406  						},
   407  					},
   408  				},
   409  				Extension: map[string]interface{}{
   410  					"x-dcl-parent-container": "project",
   411  				},
   412  			},
   413  			ns: &corev1.Namespace{
   414  				ObjectMeta: metav1.ObjectMeta{
   415  					Annotations: map[string]string{
   416  						k8s.ProjectIDAnnotation: "project-id-from-namespace-annotation",
   417  					},
   418  					Name: "namespace-name",
   419  				},
   420  			},
   421  		},
   422  		{
   423  			name: "default reference from namespace annotation (project-scoped resource which supports both container annotations and hierarchical references)",
   424  			obj: &unstructured.Unstructured{
   425  				Object: map[string]interface{}{
   426  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   427  					"kind":       "Test6BothContainerAndHierarchicalRef",
   428  					"metadata": map[string]interface{}{
   429  						"name": "resource-name",
   430  					},
   431  				},
   432  			},
   433  			newObj: &unstructured.Unstructured{
   434  				Object: map[string]interface{}{
   435  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   436  					"kind":       "Test6BothContainerAndHierarchicalRef",
   437  					"metadata": map[string]interface{}{
   438  						"name": "resource-name",
   439  					},
   440  					"spec": map[string]interface{}{
   441  						"projectRef": map[string]interface{}{
   442  							"external": "project-id-from-namespace-annotation",
   443  						},
   444  					},
   445  				},
   446  			},
   447  			schema: &openapi.Schema{
   448  				Type: "object",
   449  				Properties: map[string]*openapi.Schema{
   450  					"project": &openapi.Schema{
   451  						Type: "string",
   452  						Extension: map[string]interface{}{
   453  							"x-dcl-references": []interface{}{
   454  								map[interface{}]interface{}{
   455  									"field":    "name",
   456  									"parent":   true,
   457  									"resource": "Cloudresourcemanager/Project",
   458  								},
   459  							},
   460  						},
   461  					},
   462  				},
   463  				Extension: map[string]interface{}{
   464  					"x-dcl-parent-container": "project",
   465  				},
   466  			},
   467  			ns: &corev1.Namespace{
   468  				ObjectMeta: metav1.ObjectMeta{
   469  					Annotations: map[string]string{
   470  						k8s.ProjectIDAnnotation: "project-id-from-namespace-annotation",
   471  					},
   472  					Name: "namespace-name",
   473  				},
   474  			},
   475  		},
   476  		{
   477  			name: "default reference from namespace name (project-scoped resource which supports both container annotations and hierarchical references)",
   478  			obj: &unstructured.Unstructured{
   479  				Object: map[string]interface{}{
   480  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   481  					"kind":       "Test6BothContainerAndHierarchicalRef",
   482  					"metadata": map[string]interface{}{
   483  						"name": "resource-name",
   484  					},
   485  				},
   486  			},
   487  			newObj: &unstructured.Unstructured{
   488  				Object: map[string]interface{}{
   489  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   490  					"kind":       "Test6BothContainerAndHierarchicalRef",
   491  					"metadata": map[string]interface{}{
   492  						"name": "resource-name",
   493  					},
   494  					"spec": map[string]interface{}{
   495  						"projectRef": map[string]interface{}{
   496  							"external": "namespace-name",
   497  						},
   498  					},
   499  				},
   500  			},
   501  			schema: &openapi.Schema{
   502  				Type: "object",
   503  				Properties: map[string]*openapi.Schema{
   504  					"project": &openapi.Schema{
   505  						Type: "string",
   506  						Extension: map[string]interface{}{
   507  							"x-dcl-references": []interface{}{
   508  								map[interface{}]interface{}{
   509  									"field":    "name",
   510  									"parent":   true,
   511  									"resource": "Cloudresourcemanager/Project",
   512  								},
   513  							},
   514  						},
   515  					},
   516  				},
   517  				Extension: map[string]interface{}{
   518  					"x-dcl-parent-container": "project",
   519  				},
   520  			},
   521  			ns: &corev1.Namespace{
   522  				ObjectMeta: metav1.ObjectMeta{
   523  					Name: "namespace-name",
   524  				},
   525  			},
   526  		},
   527  		{
   528  			name: "default reference from resource annotation (project-scoped resource which supports both container annotations and hierarchical references, but doesn't have a x-dcl-parent-container extension)",
   529  			obj: &unstructured.Unstructured{
   530  				Object: map[string]interface{}{
   531  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   532  					"kind":       "Test6BothContainerAndHierarchicalRef",
   533  					"metadata": map[string]interface{}{
   534  						"annotations": map[string]interface{}{
   535  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
   536  						},
   537  						"name": "resource-name",
   538  					},
   539  				},
   540  			},
   541  			newObj: &unstructured.Unstructured{
   542  				Object: map[string]interface{}{
   543  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   544  					"kind":       "Test6BothContainerAndHierarchicalRef",
   545  					"metadata": map[string]interface{}{
   546  						"annotations": map[string]interface{}{
   547  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
   548  						},
   549  						"name": "resource-name",
   550  					},
   551  					"spec": map[string]interface{}{
   552  						"projectRef": map[string]interface{}{
   553  							"external": "project-id-from-resource-annotation",
   554  						},
   555  					},
   556  				},
   557  			},
   558  			schema: &openapi.Schema{
   559  				Type: "object",
   560  				Properties: map[string]*openapi.Schema{
   561  					"project": &openapi.Schema{
   562  						Type: "string",
   563  						Extension: map[string]interface{}{
   564  							"x-dcl-references": []interface{}{
   565  								map[interface{}]interface{}{
   566  									"field":    "name",
   567  									"parent":   true,
   568  									"resource": "Cloudresourcemanager/Project",
   569  								},
   570  							},
   571  						},
   572  					},
   573  				},
   574  			},
   575  			ns: &corev1.Namespace{
   576  				ObjectMeta: metav1.ObjectMeta{
   577  					Annotations: map[string]string{
   578  						k8s.ProjectIDAnnotation: "project-id-from-namespace-annotation",
   579  					},
   580  					Name: "namespace-name",
   581  				},
   582  			},
   583  		},
   584  
   585  		// Test defaulting of hierarchical references for resources which
   586  		// only support hierarchical references.
   587  		{
   588  			name: "no defaulting if resource already has reference (project-scoped resource which only supports hierarchical references)",
   589  			obj: &unstructured.Unstructured{
   590  				Object: map[string]interface{}{
   591  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   592  					"kind":       "Test6OnlyHierarchicalRef",
   593  					"metadata": map[string]interface{}{
   594  						"annotations": map[string]interface{}{
   595  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
   596  						},
   597  						"name": "resource-name",
   598  					},
   599  					"spec": map[string]interface{}{
   600  						"projectRef": map[string]interface{}{
   601  							"name": "project-id-from-spec",
   602  						},
   603  					},
   604  				},
   605  			},
   606  			newObj: &unstructured.Unstructured{
   607  				Object: map[string]interface{}{
   608  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   609  					"kind":       "Test6OnlyHierarchicalRef",
   610  					"metadata": map[string]interface{}{
   611  						"annotations": map[string]interface{}{
   612  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
   613  						},
   614  						"name": "resource-name",
   615  					},
   616  					"spec": map[string]interface{}{
   617  						"projectRef": map[string]interface{}{
   618  							"name": "project-id-from-spec",
   619  						},
   620  					},
   621  				},
   622  			},
   623  			schema: &openapi.Schema{
   624  				Type: "object",
   625  				Properties: map[string]*openapi.Schema{
   626  					"project": &openapi.Schema{
   627  						Type: "string",
   628  						Extension: map[string]interface{}{
   629  							"x-dcl-references": []interface{}{
   630  								map[interface{}]interface{}{
   631  									"field":    "name",
   632  									"parent":   true,
   633  									"resource": "Cloudresourcemanager/Project",
   634  								},
   635  							},
   636  						},
   637  					},
   638  				},
   639  			},
   640  			ns: &corev1.Namespace{
   641  				ObjectMeta: metav1.ObjectMeta{
   642  					Annotations: map[string]string{
   643  						k8s.ProjectIDAnnotation: "project-id-from-namespace-annotation",
   644  					},
   645  					Name: "namespace-name",
   646  				},
   647  			},
   648  		},
   649  		{
   650  			name: "default reference from namespace annotation (project-scoped resource which only supports hierarchical references)",
   651  			obj: &unstructured.Unstructured{
   652  				Object: map[string]interface{}{
   653  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   654  					"kind":       "Test6OnlyHierarchicalRef",
   655  					"metadata": map[string]interface{}{
   656  						"annotations": map[string]interface{}{
   657  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
   658  						},
   659  						"name": "resource-name",
   660  					},
   661  				},
   662  			},
   663  			newObj: &unstructured.Unstructured{
   664  				Object: map[string]interface{}{
   665  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   666  					"kind":       "Test6OnlyHierarchicalRef",
   667  					"metadata": map[string]interface{}{
   668  						"annotations": map[string]interface{}{
   669  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
   670  						},
   671  						"name": "resource-name",
   672  					},
   673  					"spec": map[string]interface{}{
   674  						"projectRef": map[string]interface{}{
   675  							"external": "project-id-from-namespace-annotation",
   676  						},
   677  					},
   678  				},
   679  			},
   680  			schema: &openapi.Schema{
   681  				Type: "object",
   682  				Properties: map[string]*openapi.Schema{
   683  					"project": &openapi.Schema{
   684  						Type: "string",
   685  						Extension: map[string]interface{}{
   686  							"x-dcl-references": []interface{}{
   687  								map[interface{}]interface{}{
   688  									"field":    "name",
   689  									"parent":   true,
   690  									"resource": "Cloudresourcemanager/Project",
   691  								},
   692  							},
   693  						},
   694  					},
   695  				},
   696  			},
   697  			ns: &corev1.Namespace{
   698  				ObjectMeta: metav1.ObjectMeta{
   699  					Annotations: map[string]string{
   700  						k8s.ProjectIDAnnotation: "project-id-from-namespace-annotation",
   701  					},
   702  					Name: "namespace-name",
   703  				},
   704  			},
   705  		},
   706  		{
   707  			name: "default reference from namespace name (project-scoped resource which only supports hierarchical references)",
   708  			obj: &unstructured.Unstructured{
   709  				Object: map[string]interface{}{
   710  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   711  					"kind":       "Test6OnlyHierarchicalRef",
   712  					"metadata": map[string]interface{}{
   713  						"annotations": map[string]interface{}{
   714  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
   715  						},
   716  						"name": "resource-name",
   717  					},
   718  				},
   719  			},
   720  			newObj: &unstructured.Unstructured{
   721  				Object: map[string]interface{}{
   722  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   723  					"kind":       "Test6OnlyHierarchicalRef",
   724  					"metadata": map[string]interface{}{
   725  						"annotations": map[string]interface{}{
   726  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
   727  						},
   728  						"name": "resource-name",
   729  					},
   730  					"spec": map[string]interface{}{
   731  						"projectRef": map[string]interface{}{
   732  							"external": "namespace-name",
   733  						},
   734  					},
   735  				},
   736  			},
   737  			schema: &openapi.Schema{
   738  				Type: "object",
   739  				Properties: map[string]*openapi.Schema{
   740  					"project": &openapi.Schema{
   741  						Type: "string",
   742  						Extension: map[string]interface{}{
   743  							"x-dcl-references": []interface{}{
   744  								map[interface{}]interface{}{
   745  									"field":    "name",
   746  									"parent":   true,
   747  									"resource": "Cloudresourcemanager/Project",
   748  								},
   749  							},
   750  						},
   751  					},
   752  				},
   753  			},
   754  			ns: &corev1.Namespace{
   755  				ObjectMeta: metav1.ObjectMeta{
   756  					Name: "namespace-name",
   757  				},
   758  			},
   759  		},
   760  		{
   761  			name: "default reference from namespace annotation (multi-parent resource which only supports hierarchical references)",
   762  			obj: &unstructured.Unstructured{
   763  				Object: map[string]interface{}{
   764  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   765  					"kind":       "Test6OnlyHierarchicalRef",
   766  					"metadata": map[string]interface{}{
   767  						"annotations": map[string]interface{}{
   768  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
   769  						},
   770  						"name": "resource-name",
   771  					},
   772  				},
   773  			},
   774  			newObj: &unstructured.Unstructured{
   775  				Object: map[string]interface{}{
   776  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   777  					"kind":       "Test6OnlyHierarchicalRef",
   778  					"metadata": map[string]interface{}{
   779  						"annotations": map[string]interface{}{
   780  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
   781  						},
   782  						"name": "resource-name",
   783  					},
   784  					"spec": map[string]interface{}{
   785  						"folderRef": map[string]interface{}{
   786  							"external": "folder-id-from-namespace-annotation",
   787  						},
   788  					},
   789  				},
   790  			},
   791  			schema: &openapi.Schema{
   792  				Type: "object",
   793  				Properties: map[string]*openapi.Schema{
   794  					"parent": &openapi.Schema{
   795  						Type: "string",
   796  						Extension: map[string]interface{}{
   797  							"x-dcl-references": []interface{}{
   798  								map[interface{}]interface{}{
   799  									"field":    "name",
   800  									"parent":   true,
   801  									"resource": "Cloudresourcemanager/Project",
   802  								},
   803  								map[interface{}]interface{}{
   804  									"field":    "name",
   805  									"parent":   true,
   806  									"resource": "Cloudresourcemanager/Folder",
   807  								},
   808  								map[interface{}]interface{}{
   809  									"field":    "name",
   810  									"parent":   true,
   811  									"resource": "Cloudresourcemanager/Organization",
   812  								},
   813  							},
   814  						},
   815  					},
   816  				},
   817  			},
   818  			ns: &corev1.Namespace{
   819  				ObjectMeta: metav1.ObjectMeta{
   820  					Annotations: map[string]string{
   821  						k8s.FolderIDAnnotation: "folder-id-from-namespace-annotation",
   822  					},
   823  					Name: "namespace-name",
   824  				},
   825  			},
   826  		},
   827  		{
   828  			name: "default reference from namespace name (multi-parent resource which can be project-scoped and which only supports hierarchical references)",
   829  			obj: &unstructured.Unstructured{
   830  				Object: map[string]interface{}{
   831  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   832  					"kind":       "Test6OnlyHierarchicalRef",
   833  					"metadata": map[string]interface{}{
   834  						"annotations": map[string]interface{}{
   835  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
   836  						},
   837  						"name": "resource-name",
   838  					},
   839  				},
   840  			},
   841  			newObj: &unstructured.Unstructured{
   842  				Object: map[string]interface{}{
   843  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   844  					"kind":       "Test6OnlyHierarchicalRef",
   845  					"metadata": map[string]interface{}{
   846  						"annotations": map[string]interface{}{
   847  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
   848  						},
   849  						"name": "resource-name",
   850  					},
   851  					"spec": map[string]interface{}{
   852  						"projectRef": map[string]interface{}{
   853  							"external": "namespace-name",
   854  						},
   855  					},
   856  				},
   857  			},
   858  			schema: &openapi.Schema{
   859  				Type: "object",
   860  				Properties: map[string]*openapi.Schema{
   861  					"parent": &openapi.Schema{
   862  						Type: "string",
   863  						Extension: map[string]interface{}{
   864  							"x-dcl-references": []interface{}{
   865  								map[interface{}]interface{}{
   866  									"field":    "name",
   867  									"parent":   true,
   868  									"resource": "Cloudresourcemanager/Project",
   869  								},
   870  								map[interface{}]interface{}{
   871  									"field":    "name",
   872  									"parent":   true,
   873  									"resource": "Cloudresourcemanager/Folder",
   874  								},
   875  								map[interface{}]interface{}{
   876  									"field":    "name",
   877  									"parent":   true,
   878  									"resource": "Cloudresourcemanager/Organization",
   879  								},
   880  							},
   881  						},
   882  					},
   883  				},
   884  			},
   885  			ns: &corev1.Namespace{
   886  				ObjectMeta: metav1.ObjectMeta{
   887  					Name: "namespace-name",
   888  				},
   889  			},
   890  		},
   891  		{
   892  			name: "deny resource if more than one namespace annotation (multi-parent resource which only supports hierarchical references)",
   893  			obj: &unstructured.Unstructured{
   894  				Object: map[string]interface{}{
   895  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   896  					"kind":       "Test6OnlyHierarchicalRef",
   897  					"metadata": map[string]interface{}{
   898  						"name": "resource-name",
   899  					},
   900  				},
   901  			},
   902  			schema: &openapi.Schema{
   903  				Type: "object",
   904  				Properties: map[string]*openapi.Schema{
   905  					"parent": &openapi.Schema{
   906  						Type: "string",
   907  						Extension: map[string]interface{}{
   908  							"x-dcl-references": []interface{}{
   909  								map[interface{}]interface{}{
   910  									"field":    "name",
   911  									"parent":   true,
   912  									"resource": "Cloudresourcemanager/Project",
   913  								},
   914  								map[interface{}]interface{}{
   915  									"field":    "name",
   916  									"parent":   true,
   917  									"resource": "Cloudresourcemanager/Folder",
   918  								},
   919  								map[interface{}]interface{}{
   920  									"field":    "name",
   921  									"parent":   true,
   922  									"resource": "Cloudresourcemanager/Organization",
   923  								},
   924  							},
   925  						},
   926  					},
   927  				},
   928  			},
   929  			ns: &corev1.Namespace{
   930  				ObjectMeta: metav1.ObjectMeta{
   931  					Annotations: map[string]string{
   932  						k8s.FolderIDAnnotation: "folder-id-from-namespace-annotation",
   933  						k8s.OrgIDAnnotation:    "org-id-from-namespace-annotation",
   934  					},
   935  					Name: "namespace-name",
   936  				},
   937  			},
   938  			denied: true,
   939  		},
   940  		{
   941  			name: "deny resource if no namespace annotation (non-project-scoped resource which only supports hierarchical references)",
   942  			obj: &unstructured.Unstructured{
   943  				Object: map[string]interface{}{
   944  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   945  					"kind":       "Test6OnlyHierarchicalRef",
   946  					"metadata": map[string]interface{}{
   947  						"name": "resource-name",
   948  					},
   949  				},
   950  			},
   951  			schema: &openapi.Schema{
   952  				Type: "object",
   953  				Properties: map[string]*openapi.Schema{
   954  					"parent": &openapi.Schema{
   955  						Type: "string",
   956  						Extension: map[string]interface{}{
   957  							"x-dcl-references": []interface{}{
   958  								map[interface{}]interface{}{
   959  									"field":    "name",
   960  									"parent":   true,
   961  									"resource": "Cloudresourcemanager/Folder",
   962  								},
   963  								map[interface{}]interface{}{
   964  									"field":    "name",
   965  									"parent":   true,
   966  									"resource": "Cloudresourcemanager/Organization",
   967  								},
   968  							},
   969  						},
   970  					},
   971  				},
   972  			},
   973  			ns: &corev1.Namespace{
   974  				ObjectMeta: metav1.ObjectMeta{
   975  					Name: "namespace-name",
   976  				},
   977  			},
   978  			denied: true,
   979  		},
   980  		{
   981  			name: "allow resource even if no annotations found on resource/namespace as long as resource has reference (multi-parent resource which only supports hierarchical references)",
   982  			obj: &unstructured.Unstructured{
   983  				Object: map[string]interface{}{
   984  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   985  					"kind":       "Test6OnlyHierarchicalRef",
   986  					"metadata": map[string]interface{}{
   987  						"name": "resource-name",
   988  					},
   989  					"spec": map[string]interface{}{
   990  						"folderRef": map[string]interface{}{
   991  							"name": "folder-id-from-spec",
   992  						},
   993  					},
   994  				},
   995  			},
   996  			newObj: &unstructured.Unstructured{
   997  				Object: map[string]interface{}{
   998  					"apiVersion": "test6.cnrm.cloud.google.com/v1alpha1",
   999  					"kind":       "Test6OnlyHierarchicalRef",
  1000  					"metadata": map[string]interface{}{
  1001  						"name": "resource-name",
  1002  					},
  1003  					"spec": map[string]interface{}{
  1004  						"folderRef": map[string]interface{}{
  1005  							"name": "folder-id-from-spec",
  1006  						},
  1007  					},
  1008  				},
  1009  			},
  1010  			schema: &openapi.Schema{
  1011  				Type: "object",
  1012  				Properties: map[string]*openapi.Schema{
  1013  					"parent": &openapi.Schema{
  1014  						Type: "string",
  1015  						Extension: map[string]interface{}{
  1016  							"x-dcl-references": []interface{}{
  1017  								map[interface{}]interface{}{
  1018  									"field":    "name",
  1019  									"parent":   true,
  1020  									"resource": "Cloudresourcemanager/Folder",
  1021  								},
  1022  								map[interface{}]interface{}{
  1023  									"field":    "name",
  1024  									"parent":   true,
  1025  									"resource": "Cloudresourcemanager/Organization",
  1026  								},
  1027  							},
  1028  						},
  1029  					},
  1030  				},
  1031  			},
  1032  			ns: &corev1.Namespace{
  1033  				ObjectMeta: metav1.ObjectMeta{
  1034  					Name: "namespace-name",
  1035  				},
  1036  			},
  1037  		},
  1038  	}
  1039  
  1040  	smLoader := dclmetadata.NewFromServiceList(testservicemetadataloader.FakeServiceMetadataWithHierarchicalResources())
  1041  	for _, tc := range tests {
  1042  		tc := tc
  1043  		t.Run(tc.name, func(t *testing.T) {
  1044  			t.Parallel()
  1045  			dclSchemaKey := testdclschemaloader.DCLSchemaKeyForGVK(t, tc.obj.GroupVersionKind(), smLoader)
  1046  			dclSchemaMap := map[string]*openapi.Schema{
  1047  				dclSchemaKey: tc.schema,
  1048  
  1049  				// Add the following to the list of fake DCL schemas to allow for our
  1050  				// test to test resources that reference hierarchical resources
  1051  				// (e.g. "Cloudresourcemanager/Project").
  1052  				"cloudresourcemanager_ga_project": &openapi.Schema{},
  1053  				"cloudresourcemanager_ga_folder":  &openapi.Schema{},
  1054  			}
  1055  			dclSchemaLoader := testdclschemaloader.New(dclSchemaMap)
  1056  			response := handleContainerAnnotationsForDCLBasedResources(tc.obj, tc.ns, dclSchemaLoader, smLoader)
  1057  			if tc.denied {
  1058  				if response.Allowed {
  1059  					t.Fatalf("expected request to be denied, but was allowed. Response:\n%v", response)
  1060  				}
  1061  				return
  1062  			}
  1063  			if !response.Allowed {
  1064  				t.Fatalf("request was unexpectedly denied. Response:\n%v", response)
  1065  			}
  1066  			expectedResponse := constructPatchResponse(tc.obj, tc.newObj)
  1067  			if !testutil.Equals(t, expectedResponse, response) {
  1068  				diff := cmp.Diff(expectedResponse, response)
  1069  				t.Fatalf("unexpected diff in the response (-want +got):\n%v", diff)
  1070  			}
  1071  		})
  1072  	}
  1073  }
  1074  
  1075  func TestHandleContainerAnnotationsForTFBasedResources(t *testing.T) {
  1076  	tests := []struct {
  1077  		name string
  1078  		obj  *unstructured.Unstructured
  1079  		ns   *corev1.Namespace
  1080  
  1081  		newObj *unstructured.Unstructured
  1082  		denied bool
  1083  	}{
  1084  		{
  1085  			name: "no defaulting if resource supports neither containers nor hierarchical references",
  1086  			obj: &unstructured.Unstructured{
  1087  				Object: map[string]interface{}{
  1088  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1089  					"kind":       "Test4NoParentResource",
  1090  					"metadata": map[string]interface{}{
  1091  						"name": "resource-name",
  1092  					},
  1093  				},
  1094  			},
  1095  			newObj: &unstructured.Unstructured{
  1096  				Object: map[string]interface{}{
  1097  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1098  					"kind":       "Test4NoParentResource",
  1099  					"metadata": map[string]interface{}{
  1100  						"name": "resource-name",
  1101  					},
  1102  				},
  1103  			},
  1104  			ns: &corev1.Namespace{
  1105  				ObjectMeta: metav1.ObjectMeta{
  1106  					Annotations: map[string]string{
  1107  						k8s.ProjectIDAnnotation: "project-id-from-namespace-annotation",
  1108  					},
  1109  					Name: "namespace-name",
  1110  				},
  1111  			},
  1112  		},
  1113  
  1114  		// Test defaulting of container annotations for resources which only
  1115  		// support container annotations.
  1116  		// TODO(b/193177782): Delete the following tests once all resources
  1117  		// support hierarchical references.
  1118  		{
  1119  			name: "no defaulting if resource already has annotation (project-scoped resource which only supports container annotations)",
  1120  			obj: &unstructured.Unstructured{
  1121  				Object: map[string]interface{}{
  1122  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1123  					"kind":       "Test4ProjectScopedResourceWithOnlyContainerSupport",
  1124  					"metadata": map[string]interface{}{
  1125  						"annotations": map[string]interface{}{
  1126  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
  1127  						},
  1128  						"name": "resource-name",
  1129  					},
  1130  				},
  1131  			},
  1132  			newObj: &unstructured.Unstructured{
  1133  				Object: map[string]interface{}{
  1134  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1135  					"kind":       "Test4ProjectScopedResourceWithOnlyContainerSupport",
  1136  					"metadata": map[string]interface{}{
  1137  						"annotations": map[string]interface{}{
  1138  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
  1139  						},
  1140  						"name": "resource-name",
  1141  					},
  1142  				},
  1143  			},
  1144  			ns: &corev1.Namespace{
  1145  				ObjectMeta: metav1.ObjectMeta{
  1146  					Annotations: map[string]string{
  1147  						k8s.ProjectIDAnnotation: "project-id-from-namespace-annotation",
  1148  					},
  1149  					Name: "namespace-name",
  1150  				},
  1151  			},
  1152  		},
  1153  		{
  1154  			name: "default resource-level annotation from namespace annotation (project-scoped resource which only supports container annotations)",
  1155  			obj: &unstructured.Unstructured{
  1156  				Object: map[string]interface{}{
  1157  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1158  					"kind":       "Test4ProjectScopedResourceWithOnlyContainerSupport",
  1159  					"metadata": map[string]interface{}{
  1160  						"name": "resource-name",
  1161  					},
  1162  				},
  1163  			},
  1164  			newObj: &unstructured.Unstructured{
  1165  				Object: map[string]interface{}{
  1166  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1167  					"kind":       "Test4ProjectScopedResourceWithOnlyContainerSupport",
  1168  					"metadata": map[string]interface{}{
  1169  						"annotations": map[string]interface{}{
  1170  							k8s.ProjectIDAnnotation: "project-id-from-namespace-annotation",
  1171  						},
  1172  						"name": "resource-name",
  1173  					},
  1174  				},
  1175  			},
  1176  			ns: &corev1.Namespace{
  1177  				ObjectMeta: metav1.ObjectMeta{
  1178  					Annotations: map[string]string{
  1179  						k8s.ProjectIDAnnotation: "project-id-from-namespace-annotation",
  1180  					},
  1181  					Name: "namespace-name",
  1182  				},
  1183  			},
  1184  		},
  1185  		{
  1186  			name: "default resource-level annotation from namespace name if namespace has no annotation (project-scoped resource which only supports container annotations)",
  1187  			obj: &unstructured.Unstructured{
  1188  				Object: map[string]interface{}{
  1189  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1190  					"kind":       "Test4ProjectScopedResourceWithOnlyContainerSupport",
  1191  					"metadata": map[string]interface{}{
  1192  						"name": "resource-name",
  1193  					},
  1194  				},
  1195  			},
  1196  			newObj: &unstructured.Unstructured{
  1197  				Object: map[string]interface{}{
  1198  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1199  					"kind":       "Test4ProjectScopedResourceWithOnlyContainerSupport",
  1200  					"metadata": map[string]interface{}{
  1201  						"annotations": map[string]interface{}{
  1202  							k8s.ProjectIDAnnotation: "namespace-name",
  1203  						},
  1204  						"name": "resource-name",
  1205  					},
  1206  				},
  1207  			},
  1208  			ns: &corev1.Namespace{
  1209  				ObjectMeta: metav1.ObjectMeta{
  1210  					Name: "namespace-name",
  1211  				},
  1212  			},
  1213  		},
  1214  		{
  1215  			name: "no defaulting if resource already has annotation (multi-parent resource which only supports container annotations)",
  1216  			obj: &unstructured.Unstructured{
  1217  				Object: map[string]interface{}{
  1218  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1219  					"kind":       "Test4MultiParentResourceWithOnlyContainerSupport",
  1220  					"metadata": map[string]interface{}{
  1221  						"annotations": map[string]interface{}{
  1222  							k8s.FolderIDAnnotation: "folder-id-from-resource-annotation",
  1223  						},
  1224  						"name": "resource-name",
  1225  					},
  1226  				},
  1227  			},
  1228  			newObj: &unstructured.Unstructured{
  1229  				Object: map[string]interface{}{
  1230  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1231  					"kind":       "Test4MultiParentResourceWithOnlyContainerSupport",
  1232  					"metadata": map[string]interface{}{
  1233  						"annotations": map[string]interface{}{
  1234  							k8s.FolderIDAnnotation: "folder-id-from-resource-annotation",
  1235  						},
  1236  						"name": "resource-name",
  1237  					},
  1238  				},
  1239  			},
  1240  			ns: &corev1.Namespace{
  1241  				ObjectMeta: metav1.ObjectMeta{
  1242  					Annotations: map[string]string{
  1243  						k8s.FolderIDAnnotation: "folder-id-from-namespace-annotation",
  1244  					},
  1245  					Name: "namespace-name",
  1246  				},
  1247  			},
  1248  		},
  1249  		{
  1250  			name: "default resource-level annotation from namespace annotation (multi-parent resource which only supports container annotations)",
  1251  			obj: &unstructured.Unstructured{
  1252  				Object: map[string]interface{}{
  1253  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1254  					"kind":       "Test4MultiParentResourceWithOnlyContainerSupport",
  1255  					"metadata": map[string]interface{}{
  1256  						"name": "resource-name",
  1257  					},
  1258  				},
  1259  			},
  1260  			newObj: &unstructured.Unstructured{
  1261  				Object: map[string]interface{}{
  1262  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1263  					"kind":       "Test4MultiParentResourceWithOnlyContainerSupport",
  1264  					"metadata": map[string]interface{}{
  1265  						"annotations": map[string]interface{}{
  1266  							k8s.FolderIDAnnotation: "folder-id-from-namespace-annotation",
  1267  						},
  1268  						"name": "resource-name",
  1269  					},
  1270  				},
  1271  			},
  1272  			ns: &corev1.Namespace{
  1273  				ObjectMeta: metav1.ObjectMeta{
  1274  					Annotations: map[string]string{
  1275  						k8s.FolderIDAnnotation: "folder-id-from-namespace-annotation",
  1276  					},
  1277  					Name: "namespace-name",
  1278  				},
  1279  			},
  1280  		},
  1281  		{
  1282  			name: "deny resource if more than one namespace annotation (multi-parent resource which only supports container annotations)",
  1283  			obj: &unstructured.Unstructured{
  1284  				Object: map[string]interface{}{
  1285  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1286  					"kind":       "Test4MultiParentResourceWithOnlyContainerSupport",
  1287  					"metadata": map[string]interface{}{
  1288  						"name": "resource-name",
  1289  					},
  1290  				},
  1291  			},
  1292  			ns: &corev1.Namespace{
  1293  				ObjectMeta: metav1.ObjectMeta{
  1294  					Annotations: map[string]string{
  1295  						k8s.FolderIDAnnotation: "folder-id-from-namespace-annotation",
  1296  						k8s.OrgIDAnnotation:    "org-id-from-namespace-annotation",
  1297  					},
  1298  					Name: "namespace-name",
  1299  				},
  1300  			},
  1301  			denied: true,
  1302  		},
  1303  		{
  1304  			name: "deny resource if no namespace annotation (non-project-scoped resource which only supports container annotations)",
  1305  			obj: &unstructured.Unstructured{
  1306  				Object: map[string]interface{}{
  1307  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1308  					"kind":       "Test4MultiParentResourceWithOnlyContainerSupport",
  1309  					"metadata": map[string]interface{}{
  1310  						"name": "resource-name",
  1311  					},
  1312  				},
  1313  			},
  1314  			ns: &corev1.Namespace{
  1315  				ObjectMeta: metav1.ObjectMeta{
  1316  					Name: "namespace-name",
  1317  				},
  1318  			},
  1319  			denied: true,
  1320  		},
  1321  
  1322  		// Test defaulting of hierarchical references for resources which
  1323  		// support both container annotations and hierarchical references.
  1324  		{
  1325  			name: "no defaulting if resource already has reference (project-scoped resource which supports both container annotations and hierarchical references)",
  1326  			obj: &unstructured.Unstructured{
  1327  				Object: map[string]interface{}{
  1328  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1329  					"kind":       "Test4ProjectScopedResource",
  1330  					"metadata": map[string]interface{}{
  1331  						"annotations": map[string]interface{}{
  1332  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
  1333  						},
  1334  						"name": "resource-name",
  1335  					},
  1336  					"spec": map[string]interface{}{
  1337  						"projectRef": map[string]interface{}{
  1338  							"name": "project-id-from-spec",
  1339  						},
  1340  					},
  1341  				},
  1342  			},
  1343  			newObj: &unstructured.Unstructured{
  1344  				Object: map[string]interface{}{
  1345  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1346  					"kind":       "Test4ProjectScopedResource",
  1347  					"metadata": map[string]interface{}{
  1348  						"annotations": map[string]interface{}{
  1349  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
  1350  						},
  1351  						"name": "resource-name",
  1352  					},
  1353  					"spec": map[string]interface{}{
  1354  						"projectRef": map[string]interface{}{
  1355  							"name": "project-id-from-spec",
  1356  						},
  1357  					},
  1358  				},
  1359  			},
  1360  			ns: &corev1.Namespace{
  1361  				ObjectMeta: metav1.ObjectMeta{
  1362  					Annotations: map[string]string{
  1363  						k8s.ProjectIDAnnotation: "project-id-from-namespace-annotation",
  1364  					},
  1365  					Name: "namespace-name",
  1366  				},
  1367  			},
  1368  		},
  1369  		{
  1370  			name: "default reference from resource annotation (project-scoped resource which supports both container annotations and hierarchical references)",
  1371  			obj: &unstructured.Unstructured{
  1372  				Object: map[string]interface{}{
  1373  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1374  					"kind":       "Test4ProjectScopedResource",
  1375  					"metadata": map[string]interface{}{
  1376  						"annotations": map[string]interface{}{
  1377  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
  1378  						},
  1379  						"name": "resource-name",
  1380  					},
  1381  				},
  1382  			},
  1383  			newObj: &unstructured.Unstructured{
  1384  				Object: map[string]interface{}{
  1385  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1386  					"kind":       "Test4ProjectScopedResource",
  1387  					"metadata": map[string]interface{}{
  1388  						"annotations": map[string]interface{}{
  1389  							k8s.ProjectIDAnnotation: "project-id-from-resource-annotation",
  1390  						},
  1391  						"name": "resource-name",
  1392  					},
  1393  					"spec": map[string]interface{}{
  1394  						"projectRef": map[string]interface{}{
  1395  							"external": "project-id-from-resource-annotation",
  1396  						},
  1397  					},
  1398  				},
  1399  			},
  1400  			ns: &corev1.Namespace{
  1401  				ObjectMeta: metav1.ObjectMeta{
  1402  					Annotations: map[string]string{
  1403  						k8s.ProjectIDAnnotation: "project-id-from-namespace-annotation",
  1404  					},
  1405  					Name: "namespace-name",
  1406  				},
  1407  			},
  1408  		},
  1409  		{
  1410  			name: "default reference from namespace annotation (project-scoped resource which supports both container annotations and hierarchical references)",
  1411  			obj: &unstructured.Unstructured{
  1412  				Object: map[string]interface{}{
  1413  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1414  					"kind":       "Test4ProjectScopedResource",
  1415  					"metadata": map[string]interface{}{
  1416  						"name": "resource-name",
  1417  					},
  1418  				},
  1419  			},
  1420  			newObj: &unstructured.Unstructured{
  1421  				Object: map[string]interface{}{
  1422  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1423  					"kind":       "Test4ProjectScopedResource",
  1424  					"metadata": map[string]interface{}{
  1425  						"name": "resource-name",
  1426  					},
  1427  					"spec": map[string]interface{}{
  1428  						"projectRef": map[string]interface{}{
  1429  							"external": "project-id-from-namespace-annotation",
  1430  						},
  1431  					},
  1432  				},
  1433  			},
  1434  			ns: &corev1.Namespace{
  1435  				ObjectMeta: metav1.ObjectMeta{
  1436  					Annotations: map[string]string{
  1437  						k8s.ProjectIDAnnotation: "project-id-from-namespace-annotation",
  1438  					},
  1439  					Name: "namespace-name",
  1440  				},
  1441  			},
  1442  		},
  1443  		{
  1444  			name: "default reference from namespace name (project-scoped resource which supports both container annotations and hierarchical references)",
  1445  			obj: &unstructured.Unstructured{
  1446  				Object: map[string]interface{}{
  1447  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1448  					"kind":       "Test4ProjectScopedResource",
  1449  					"metadata": map[string]interface{}{
  1450  						"name": "resource-name",
  1451  					},
  1452  				},
  1453  			},
  1454  			newObj: &unstructured.Unstructured{
  1455  				Object: map[string]interface{}{
  1456  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1457  					"kind":       "Test4ProjectScopedResource",
  1458  					"metadata": map[string]interface{}{
  1459  						"name": "resource-name",
  1460  					},
  1461  					"spec": map[string]interface{}{
  1462  						"projectRef": map[string]interface{}{
  1463  							"external": "namespace-name",
  1464  						},
  1465  					},
  1466  				},
  1467  			},
  1468  			ns: &corev1.Namespace{
  1469  				ObjectMeta: metav1.ObjectMeta{
  1470  					Name: "namespace-name",
  1471  				},
  1472  			},
  1473  		},
  1474  		{
  1475  			name: "default reference from resource annotation (multi-parent resource which supports both container annotations and hierarchical references)",
  1476  			obj: &unstructured.Unstructured{
  1477  				Object: map[string]interface{}{
  1478  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1479  					"kind":       "Test4MultiParentResource",
  1480  					"metadata": map[string]interface{}{
  1481  						"annotations": map[string]interface{}{
  1482  							k8s.FolderIDAnnotation: "folder-id-from-resource-annotation",
  1483  						},
  1484  						"name": "resource-name",
  1485  					},
  1486  				},
  1487  			},
  1488  			newObj: &unstructured.Unstructured{
  1489  				Object: map[string]interface{}{
  1490  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1491  					"kind":       "Test4MultiParentResource",
  1492  					"metadata": map[string]interface{}{
  1493  						"annotations": map[string]interface{}{
  1494  							k8s.FolderIDAnnotation: "folder-id-from-resource-annotation",
  1495  						},
  1496  						"name": "resource-name",
  1497  					},
  1498  					"spec": map[string]interface{}{
  1499  						"folderRef": map[string]interface{}{
  1500  							"external": "folder-id-from-resource-annotation",
  1501  						},
  1502  					},
  1503  				},
  1504  			},
  1505  			ns: &corev1.Namespace{
  1506  				ObjectMeta: metav1.ObjectMeta{
  1507  					Annotations: map[string]string{
  1508  						k8s.FolderIDAnnotation: "folder-id-from-namespace-annotation",
  1509  					},
  1510  					Name: "namespace-name",
  1511  				},
  1512  			},
  1513  		},
  1514  		{
  1515  			name: "deny resource if more than one resource annotation (multi-parent resource which supports both container annotations and hierarchical references)",
  1516  			obj: &unstructured.Unstructured{
  1517  				Object: map[string]interface{}{
  1518  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1519  					"kind":       "Test4MultiParentResource",
  1520  					"metadata": map[string]interface{}{
  1521  						"annotations": map[string]interface{}{
  1522  							k8s.FolderIDAnnotation: "folder-id-from-resource-annotation",
  1523  							k8s.OrgIDAnnotation:    "org-id-from-resource-annotation",
  1524  						},
  1525  						"name": "resource-name",
  1526  					},
  1527  				},
  1528  			},
  1529  			ns: &corev1.Namespace{
  1530  				ObjectMeta: metav1.ObjectMeta{
  1531  					Annotations: map[string]string{
  1532  						k8s.FolderIDAnnotation: "folder-id-from-namespace-annotation",
  1533  						k8s.OrgIDAnnotation:    "org-id-from-namespace-annotation",
  1534  					},
  1535  					Name: "namespace-name",
  1536  				},
  1537  			},
  1538  			denied: true,
  1539  		},
  1540  		{
  1541  			name: "default reference from namespace annotation (multi-parent resource which supports both container annotations and hierarchical references)",
  1542  			obj: &unstructured.Unstructured{
  1543  				Object: map[string]interface{}{
  1544  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1545  					"kind":       "Test4MultiParentResource",
  1546  					"metadata": map[string]interface{}{
  1547  						"name": "resource-name",
  1548  					},
  1549  				},
  1550  			},
  1551  			newObj: &unstructured.Unstructured{
  1552  				Object: map[string]interface{}{
  1553  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1554  					"kind":       "Test4MultiParentResource",
  1555  					"metadata": map[string]interface{}{
  1556  						"name": "resource-name",
  1557  					},
  1558  					"spec": map[string]interface{}{
  1559  						"folderRef": map[string]interface{}{
  1560  							"external": "folder-id-from-namespace-annotation",
  1561  						},
  1562  					},
  1563  				},
  1564  			},
  1565  			ns: &corev1.Namespace{
  1566  				ObjectMeta: metav1.ObjectMeta{
  1567  					Annotations: map[string]string{
  1568  						k8s.FolderIDAnnotation: "folder-id-from-namespace-annotation",
  1569  					},
  1570  					Name: "namespace-name",
  1571  				},
  1572  			},
  1573  		},
  1574  		{
  1575  			name: "deny resource if more than one namespace annotation (multi-parent resource which supports both container annotations and hierarchical references)",
  1576  			obj: &unstructured.Unstructured{
  1577  				Object: map[string]interface{}{
  1578  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1579  					"kind":       "Test4MultiParentResource",
  1580  					"metadata": map[string]interface{}{
  1581  						"name": "resource-name",
  1582  					},
  1583  				},
  1584  			},
  1585  			ns: &corev1.Namespace{
  1586  				ObjectMeta: metav1.ObjectMeta{
  1587  					Annotations: map[string]string{
  1588  						k8s.FolderIDAnnotation: "folder-id-from-namespace-annotation",
  1589  						k8s.OrgIDAnnotation:    "org-id-from-namespace-annotation",
  1590  					},
  1591  					Name: "namespace-name",
  1592  				},
  1593  			},
  1594  			denied: true,
  1595  		},
  1596  		{
  1597  			name: "deny resource if no namespace annotation (non-project-scoped resource which supports both container annotations and hierarchical references)",
  1598  			obj: &unstructured.Unstructured{
  1599  				Object: map[string]interface{}{
  1600  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1601  					"kind":       "Test4MultiParentResource",
  1602  					"metadata": map[string]interface{}{
  1603  						"name": "resource-name",
  1604  					},
  1605  				},
  1606  			},
  1607  			ns: &corev1.Namespace{
  1608  				ObjectMeta: metav1.ObjectMeta{
  1609  					Name: "namespace-name",
  1610  				},
  1611  			},
  1612  			denied: true,
  1613  		},
  1614  		{
  1615  			name: "allow resource even if no annotations found on resource/namespace as long as resource has reference (multi-parent resource which supports both container annotations and hierarchical references)",
  1616  			obj: &unstructured.Unstructured{
  1617  				Object: map[string]interface{}{
  1618  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1619  					"kind":       "Test4MultiParentResource",
  1620  					"metadata": map[string]interface{}{
  1621  						"name": "resource-name",
  1622  					},
  1623  					"spec": map[string]interface{}{
  1624  						"folderRef": map[string]interface{}{
  1625  							"name": "project-id-from-spec",
  1626  						},
  1627  					},
  1628  				},
  1629  			},
  1630  			newObj: &unstructured.Unstructured{
  1631  				Object: map[string]interface{}{
  1632  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1633  					"kind":       "Test4MultiParentResource",
  1634  					"metadata": map[string]interface{}{
  1635  						"name": "resource-name",
  1636  					},
  1637  					"spec": map[string]interface{}{
  1638  						"folderRef": map[string]interface{}{
  1639  							"name": "project-id-from-spec",
  1640  						},
  1641  					},
  1642  				},
  1643  			},
  1644  			ns: &corev1.Namespace{
  1645  				ObjectMeta: metav1.ObjectMeta{
  1646  					Name: "namespace-name",
  1647  				},
  1648  			},
  1649  		},
  1650  
  1651  		// Test defaulting of hierarchical references for resources which
  1652  		// only support hierarchical references.
  1653  		{
  1654  			name: "no defaulting if resource already has reference (project-scoped resource which only supports hierarchical references)",
  1655  			obj: &unstructured.Unstructured{
  1656  				Object: map[string]interface{}{
  1657  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1658  					"kind":       "Test4ProjectScopedResourceWithOnlyHierarchicalReferenceSupport",
  1659  					"metadata": map[string]interface{}{
  1660  						"name": "resource-name",
  1661  					},
  1662  					"spec": map[string]interface{}{
  1663  						"projectRef": map[string]interface{}{
  1664  							"name": "project-id-from-spec",
  1665  						},
  1666  					},
  1667  				},
  1668  			},
  1669  			newObj: &unstructured.Unstructured{
  1670  				Object: map[string]interface{}{
  1671  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1672  					"kind":       "Test4ProjectScopedResourceWithOnlyHierarchicalReferenceSupport",
  1673  					"metadata": map[string]interface{}{
  1674  						"name": "resource-name",
  1675  					},
  1676  					"spec": map[string]interface{}{
  1677  						"projectRef": map[string]interface{}{
  1678  							"name": "project-id-from-spec",
  1679  						},
  1680  					},
  1681  				},
  1682  			},
  1683  			ns: &corev1.Namespace{
  1684  				ObjectMeta: metav1.ObjectMeta{
  1685  					Annotations: map[string]string{
  1686  						k8s.ProjectIDAnnotation: "project-id-from-namespace-annotation",
  1687  					},
  1688  					Name: "namespace-name",
  1689  				},
  1690  			},
  1691  		},
  1692  		{
  1693  			name: "default reference from namespace annotation (project-scoped resource which only supports hierarchical references)",
  1694  			obj: &unstructured.Unstructured{
  1695  				Object: map[string]interface{}{
  1696  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1697  					"kind":       "Test4ProjectScopedResourceWithOnlyHierarchicalReferenceSupport",
  1698  					"metadata": map[string]interface{}{
  1699  						"name": "resource-name",
  1700  					},
  1701  				},
  1702  			},
  1703  			newObj: &unstructured.Unstructured{
  1704  				Object: map[string]interface{}{
  1705  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1706  					"kind":       "Test4ProjectScopedResourceWithOnlyHierarchicalReferenceSupport",
  1707  					"metadata": map[string]interface{}{
  1708  						"name": "resource-name",
  1709  					},
  1710  					"spec": map[string]interface{}{
  1711  						"projectRef": map[string]interface{}{
  1712  							"external": "project-id-from-namespace-annotation",
  1713  						},
  1714  					},
  1715  				},
  1716  			},
  1717  			ns: &corev1.Namespace{
  1718  				ObjectMeta: metav1.ObjectMeta{
  1719  					Annotations: map[string]string{
  1720  						k8s.ProjectIDAnnotation: "project-id-from-namespace-annotation",
  1721  					},
  1722  					Name: "namespace-name",
  1723  				},
  1724  			},
  1725  		},
  1726  		{
  1727  			name: "default reference from namespace name (project-scoped resource which only supports hierarchical references)",
  1728  			obj: &unstructured.Unstructured{
  1729  				Object: map[string]interface{}{
  1730  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1731  					"kind":       "Test4ProjectScopedResourceWithOnlyHierarchicalReferenceSupport",
  1732  					"metadata": map[string]interface{}{
  1733  						"name": "resource-name",
  1734  					},
  1735  				},
  1736  			},
  1737  			newObj: &unstructured.Unstructured{
  1738  				Object: map[string]interface{}{
  1739  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1740  					"kind":       "Test4ProjectScopedResourceWithOnlyHierarchicalReferenceSupport",
  1741  					"metadata": map[string]interface{}{
  1742  						"name": "resource-name",
  1743  					},
  1744  					"spec": map[string]interface{}{
  1745  						"projectRef": map[string]interface{}{
  1746  							"external": "namespace-name",
  1747  						},
  1748  					},
  1749  				},
  1750  			},
  1751  			ns: &corev1.Namespace{
  1752  				ObjectMeta: metav1.ObjectMeta{
  1753  					Name: "namespace-name",
  1754  				},
  1755  			},
  1756  		},
  1757  		{
  1758  			name: "default reference from namespace annotation (multi-parent resource which only supports hierarchical references)",
  1759  			obj: &unstructured.Unstructured{
  1760  				Object: map[string]interface{}{
  1761  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1762  					"kind":       "Test4MultiParentResourceWithOnlyHierarchicalReferenceSupport",
  1763  					"metadata": map[string]interface{}{
  1764  						"name": "resource-name",
  1765  					},
  1766  				},
  1767  			},
  1768  			newObj: &unstructured.Unstructured{
  1769  				Object: map[string]interface{}{
  1770  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1771  					"kind":       "Test4MultiParentResourceWithOnlyHierarchicalReferenceSupport",
  1772  					"metadata": map[string]interface{}{
  1773  						"name": "resource-name",
  1774  					},
  1775  					"spec": map[string]interface{}{
  1776  						"folderRef": map[string]interface{}{
  1777  							"external": "folder-id-from-namespace-annotation",
  1778  						},
  1779  					},
  1780  				},
  1781  			},
  1782  			ns: &corev1.Namespace{
  1783  				ObjectMeta: metav1.ObjectMeta{
  1784  					Annotations: map[string]string{
  1785  						k8s.FolderIDAnnotation: "folder-id-from-namespace-annotation",
  1786  					},
  1787  					Name: "namespace-name",
  1788  				},
  1789  			},
  1790  		},
  1791  		{
  1792  			name: "deny resource if more than one namespace annotation (multi-parent resource which only supports hierarchical references)",
  1793  			obj: &unstructured.Unstructured{
  1794  				Object: map[string]interface{}{
  1795  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1796  					"kind":       "Test4MultiParentResourceWithOnlyHierarchicalReferenceSupport",
  1797  					"metadata": map[string]interface{}{
  1798  						"name": "resource-name",
  1799  					},
  1800  				},
  1801  			},
  1802  			ns: &corev1.Namespace{
  1803  				ObjectMeta: metav1.ObjectMeta{
  1804  					Annotations: map[string]string{
  1805  						k8s.FolderIDAnnotation: "folder-id-from-namespace-annotation",
  1806  						k8s.OrgIDAnnotation:    "org-id-from-namespace-annotation",
  1807  					},
  1808  					Name: "namespace-name",
  1809  				},
  1810  			},
  1811  			denied: true,
  1812  		},
  1813  		{
  1814  			name: "deny resource if no namespace annotation (non-project-scoped resource which only supports hierarchical references)",
  1815  			obj: &unstructured.Unstructured{
  1816  				Object: map[string]interface{}{
  1817  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1818  					"kind":       "Test4MultiParentResourceWithOnlyHierarchicalReferenceSupport",
  1819  					"metadata": map[string]interface{}{
  1820  						"name": "resource-name",
  1821  					},
  1822  				},
  1823  			},
  1824  			ns: &corev1.Namespace{
  1825  				ObjectMeta: metav1.ObjectMeta{
  1826  					Name: "namespace-name",
  1827  				},
  1828  			},
  1829  			denied: true,
  1830  		},
  1831  		{
  1832  			name: "allow resource even if no annotations found on resource/namespace as long as resource has reference (multi-parent resource which only supports hierarchical references)",
  1833  			obj: &unstructured.Unstructured{
  1834  				Object: map[string]interface{}{
  1835  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1836  					"kind":       "Test4MultiParentResourceWithOnlyHierarchicalReferenceSupport",
  1837  					"metadata": map[string]interface{}{
  1838  						"name": "resource-name",
  1839  					},
  1840  					"spec": map[string]interface{}{
  1841  						"folderRef": map[string]interface{}{
  1842  							"name": "folder-id-from-spec",
  1843  						},
  1844  					},
  1845  				},
  1846  			},
  1847  			newObj: &unstructured.Unstructured{
  1848  				Object: map[string]interface{}{
  1849  					"apiVersion": "test4.cnrm.cloud.google.com/v1alpha1",
  1850  					"kind":       "Test4MultiParentResourceWithOnlyHierarchicalReferenceSupport",
  1851  					"metadata": map[string]interface{}{
  1852  						"name": "resource-name",
  1853  					},
  1854  					"spec": map[string]interface{}{
  1855  						"folderRef": map[string]interface{}{
  1856  							"name": "folder-id-from-spec",
  1857  						},
  1858  					},
  1859  				},
  1860  			},
  1861  			ns: &corev1.Namespace{
  1862  				ObjectMeta: metav1.ObjectMeta{
  1863  					Name: "namespace-name",
  1864  				},
  1865  			},
  1866  		},
  1867  	}
  1868  
  1869  	smLoader := testservicemappingloader.NewForUnitTest(t)
  1870  	for _, tc := range tests {
  1871  		tc := tc
  1872  		t.Run(tc.name, func(t *testing.T) {
  1873  			t.Parallel()
  1874  			response := handleContainerAnnotationsForTFBasedResources(tc.obj, tc.ns, smLoader)
  1875  			if tc.denied {
  1876  				if response.Allowed {
  1877  					t.Fatalf("expected request to be denied, but was allowed. Response:\n%v", response)
  1878  				}
  1879  				return
  1880  			}
  1881  			if !response.Allowed {
  1882  				t.Fatalf("request was unexpectedly denied. Response:\n%v", response)
  1883  			}
  1884  			expectedResponse := constructPatchResponse(tc.obj, tc.newObj)
  1885  			if !testutil.Equals(t, expectedResponse, response) {
  1886  				diff := cmp.Diff(expectedResponse, response)
  1887  				t.Fatalf("unexpected diff in the response (-want +got):\n%v", diff)
  1888  			}
  1889  		})
  1890  	}
  1891  }
  1892  

View as plain text