1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package policymember_test
19
20 import (
21 "context"
22 "errors"
23 "log"
24 "strings"
25 "testing"
26 "time"
27
28 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/apis/iam/v1beta1"
29 kcciamclient "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/iam/iamclient"
30 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/iam/policymember"
31 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/dcl/clientconfig"
32 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/dcl/conversion"
33 dclmetadata "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/dcl/metadata"
34 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/dcl/schema/dclschemaloader"
35 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/k8s"
36 testcontroller "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/controller"
37 testreconciler "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/controller/reconciler"
38 testgcp "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/gcp"
39 testiam "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/iam"
40 testk8s "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/k8s"
41 testmain "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/main"
42 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/resourcefixture"
43 testservicemappingloader "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/servicemappingloader"
44 tfprovider "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/tf/provider"
45
46 apierrors "k8s.io/apimachinery/pkg/api/errors"
47 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
48 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
49 "sigs.k8s.io/controller-runtime/pkg/manager"
50 "sigs.k8s.io/controller-runtime/pkg/reconcile"
51 )
52
53 var (
54 mgr manager.Manager
55 expectedReconcileResult = reconcile.Result{RequeueAfter: k8s.MeanReconcileReenqueuePeriod}
56 )
57
58 func TestReconcileIAMPolicyMemberResourceLevelCreateDelete(t *testing.T) {
59 testFunc := func(t *testing.T, testId string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
60 k8sPolicyMember := newIAMPolicyMemberFixture(t, refResource, resourceRef, rc.CreateBindingRole, testgcp.GetIAMPolicyBindingMember(t))
61 testPolicyMemberCreateDelete(t, mgr, k8sPolicyMember)
62 }
63 testiam.RunResourceLevelTest(t, mgr, testFunc, testiam.ShouldRunWithTFResourcesOnly)
64 }
65
66 func TestReconcileIAMPolicyMemberResourceLevelCreateDeleteWithReconcileInterval(t *testing.T) {
67 shouldRun := func(fixture resourcefixture.ResourceFixture) bool {
68 return fixture.GVK.Kind == "PubSubTopic"
69 }
70 testFunc := func(t *testing.T, testId string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
71 k8sPolicyMember := newIAMPolicyMemberFixture(t, refResource, resourceRef, rc.CreateBindingRole, testgcp.GetIAMPolicyBindingMember(t))
72 k8sPolicyMember.SetAnnotations(map[string]string{k8s.ReconcileIntervalInSecondsAnnotation: "5"})
73 testPolicyMemberCreateDelete(t, mgr, k8sPolicyMember)
74 }
75 testiam.RunResourceLevelTest(t, mgr, testFunc, shouldRun)
76 }
77
78 func TestReconcileIAMPolicyMemberResourceLevelCreateDeleteWithExternalRef(t *testing.T) {
79 testFunc := func(t *testing.T, testId string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
80 k8sPolicyMember := newIAMPolicyMemberFixture(t, refResource, resourceRef, rc.CreateBindingRole, testgcp.GetIAMPolicyBindingMember(t))
81 testPolicyMemberCreateDelete(t, mgr, k8sPolicyMember)
82 }
83 testiam.RunResourceLevelTestWithExternalRef(t, mgr, testFunc, testiam.ShouldRunWithExternalRef)
84 }
85
86 func TestReconcileIAMPolicyMemberResourceLevelDeleteParentFirst(t *testing.T) {
87 shouldRun := func(fixture resourcefixture.ResourceFixture) bool {
88 return fixture.GVK.Kind == "PubSubTopic"
89 }
90 testFunc := func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
91 k8sPolicyMember := newIAMPolicyMemberFixture(t, refResource, resourceRef, rc.CreateBindingRole, testgcp.GetIAMPolicyBindingMember(t))
92 testReconcileResourceLevelDeleteParentFirst(t, mgr, k8sPolicyMember, refResource)
93 }
94 testiam.RunResourceLevelTest(t, mgr, testFunc, shouldRun)
95 }
96
97 func TestReconcileIAMPolicyMemberResourceLevelDeleteParentFirstWithExternalRef(t *testing.T) {
98 shouldRun := func(fixture resourcefixture.ResourceFixture) bool {
99 return fixture.GVK.Kind == "PubSubTopic"
100 }
101 testFunc := func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
102 k8sPolicyMember := newIAMPolicyMemberFixture(t, refResource, resourceRef, rc.CreateBindingRole, testgcp.GetIAMPolicyBindingMember(t))
103 testReconcileResourceLevelDeleteParentFirst(t, mgr, k8sPolicyMember, refResource)
104 }
105 testiam.RunResourceLevelTestWithExternalRef(t, mgr, testFunc, shouldRun)
106 }
107
108 func TestReconcileIAMPolicyMemberResourceLevelAcquire(t *testing.T) {
109 shouldRun := func(fixture resourcefixture.ResourceFixture) bool {
110 return fixture.GVK.Kind == "PubSubTopic"
111 }
112 testFunc := func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
113 k8sPolicyMember := newIAMPolicyMemberFixture(t, refResource, resourceRef, rc.CreateBindingRole, testgcp.GetIAMPolicyBindingMember(t))
114 testReconcileResourceLevelAcquire(t, mgr, k8sPolicyMember)
115 }
116 testiam.RunResourceLevelTest(t, mgr, testFunc, shouldRun)
117 }
118
119 func TestReconcileIAMPolicyMemberResourceLevelAcquireWithExternalRef(t *testing.T) {
120 shouldRun := func(fixture resourcefixture.ResourceFixture) bool {
121 return fixture.GVK.Kind == "PubSubTopic"
122 }
123 testFunc := func(t *testing.T, _ string, mgr manager.Manager, rc testiam.IAMResourceContext, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference) {
124 k8sPolicyMember := newIAMPolicyMemberFixture(t, refResource, resourceRef, rc.CreateBindingRole, testgcp.GetIAMPolicyBindingMember(t))
125 testReconcileResourceLevelAcquire(t, mgr, k8sPolicyMember)
126 }
127 testiam.RunResourceLevelTestWithExternalRef(t, mgr, testFunc, shouldRun)
128 }
129
130 func testPolicyMemberCreateDelete(t *testing.T, mgr manager.Manager, k8sPolicyMember *v1beta1.IAMPolicyMember) {
131 kubeClient := mgr.GetClient()
132 provider := tfprovider.NewOrLogFatal(tfprovider.DefaultConfig)
133 smLoader := testservicemappingloader.New(t)
134 dclSchemaLoader, err := dclschemaloader.New()
135 dclConfig := clientconfig.NewForIntegrationTest()
136 if err != nil {
137 t.Fatalf("error creating a new DCL schema loader: %v", err)
138 }
139 serviceMetaLoader := dclmetadata.New()
140 converter := conversion.New(dclSchemaLoader, serviceMetaLoader)
141 iamClient := kcciamclient.New(provider, smLoader, kubeClient, converter, dclConfig)
142 _, err = iamClient.GetPolicyMember(context.TODO(), k8sPolicyMember)
143 if !errors.Is(err, kcciamclient.NotFoundError) {
144 t.Fatalf("unexpected error value: got '%v', want '%v'", err, kcciamclient.NotFoundError)
145 }
146 if err := kubeClient.Create(context.TODO(), k8sPolicyMember); err != nil {
147 t.Fatalf("error creating policy member: %v", err)
148 }
149 preReconcileGeneration := k8sPolicyMember.GetGeneration()
150 reconciler := testreconciler.New(t, mgr, tfprovider.NewOrLogFatal(tfprovider.DefaultConfig))
151 resource, err := policymember.ToK8sResource(k8sPolicyMember)
152 if err != nil {
153 t.Fatalf("error converting object %v to k8sResource: %v", k8sPolicyMember, err)
154 }
155 u, err := resource.MarshalAsUnstructured()
156 if err != nil {
157 t.Fatalf("error marshalling object %v as unstructured: %v", k8sPolicyMember, err)
158 }
159 reconciler.ReconcileObjectMeta(k8sPolicyMember.ObjectMeta, v1beta1.IAMPolicyMemberGVK.Kind, testreconciler.ExpectedSuccessfulReconcileResultFor(reconciler, u), nil)
160 gcpPolicyMember, err := iamClient.GetPolicyMember(context.TODO(), k8sPolicyMember)
161 if err != nil {
162 t.Fatalf("unexpected error getting policy member: %v", err)
163 }
164 if gcpPolicyMember.Spec.Role != k8sPolicyMember.Spec.Role {
165 t.Errorf("unexpected value for role: got '%v', want '%v'", gcpPolicyMember.Spec.Role, k8sPolicyMember.Spec.Role)
166 }
167 if gcpPolicyMember.Spec.Member != k8sPolicyMember.Spec.Member {
168 t.Errorf("unexpected value for role: got '%v', want '%v'", gcpPolicyMember.Spec.Member, k8sPolicyMember.Spec.Member)
169 }
170 if err := kubeClient.Get(context.TODO(), k8s.GetNamespacedName(k8sPolicyMember), k8sPolicyMember); err != nil {
171 t.Fatalf("unexpected error getting resource: %v", err)
172 }
173 testcontroller.AssertReadyCondition(t, k8sPolicyMember.Status.Conditions)
174 testcontroller.AssertEventRecordedForObjectMetaAndKind(t, kubeClient, v1beta1.IAMPolicyMemberGVK.Kind, &k8sPolicyMember.ObjectMeta, k8s.UpToDate)
175 if err := kubeClient.Delete(context.TODO(), k8sPolicyMember); err != nil {
176 t.Fatalf("error deleting policy member: %v", err)
177 }
178 assertObservedGenerationEquals(t, k8sPolicyMember, preReconcileGeneration)
179 reconciler.ReconcileObjectMeta(k8sPolicyMember.ObjectMeta, v1beta1.IAMPolicyMemberGVK.Kind, testreconciler.ExpectedRequeueReconcileStruct, nil)
180 if _, err := iamClient.GetPolicyMember(context.TODO(), k8sPolicyMember); err != nil {
181 t.Fatalf("expected policy member to exist in GCP, but got error: %v", err)
182 }
183 testk8s.RemoveDeletionDefenderFinalizer(t, k8sPolicyMember, v1beta1.IAMPolicyMemberGVK, kubeClient)
184 reconciler.ReconcileObjectMeta(k8sPolicyMember.ObjectMeta, v1beta1.IAMPolicyMemberGVK.Kind, testreconciler.ExpectedSuccessfulReconcileResultFor(reconciler, u), nil)
185 gcpPolicyMember, err = iamClient.GetPolicyMember(context.TODO(), k8sPolicyMember)
186 if !errors.Is(err, kcciamclient.NotFoundError) {
187 t.Fatalf("unexpected error value: got '%v', want '%v'", err, kcciamclient.NotFoundError)
188 }
189 if gcpPolicyMember != nil {
190 t.Fatalf("unexpected value for policy member: got '%v', want '%v'", gcpPolicyMember, nil)
191 }
192 if err := kubeClient.Get(context.TODO(), k8s.GetNamespacedName(k8sPolicyMember), k8sPolicyMember); err == nil || !apierrors.IsNotFound(err) {
193 t.Fatalf("unexpected error value: %v", err)
194 }
195 testcontroller.AssertEventRecordedForObjectMetaAndKind(t, kubeClient, v1beta1.IAMPolicyMemberGVK.Kind, &k8sPolicyMember.ObjectMeta, k8s.Deleted)
196 }
197
198 func testReconcileResourceLevelDeleteParentFirst(t *testing.T, mgr manager.Manager, k8sPolicyMember *v1beta1.IAMPolicyMember, refResource *unstructured.Unstructured) {
199 kubeClient := mgr.GetClient()
200 if err := kubeClient.Create(context.TODO(), k8sPolicyMember); err != nil {
201 t.Fatalf("error creating k8sPolicy: %v", err)
202 }
203 reconciler := testreconciler.New(t, mgr, tfprovider.NewOrLogFatal(tfprovider.DefaultConfig))
204 reconciler.ReconcileObjectMeta(k8sPolicyMember.ObjectMeta, v1beta1.IAMPolicyMemberGVK.Kind, expectedReconcileResult, nil)
205
206
207 log.Printf("Deleting the parent of the IAM Policy Member first %v: %v/%v\n", refResource.GetKind(), refResource.GetNamespace(), refResource.GetName())
208 testk8s.RemoveDeletionDefenderFinalizerForUnstructured(t, refResource, kubeClient)
209 err := kubeClient.Delete(context.TODO(), refResource)
210 if err != nil {
211 t.Errorf("error deleting %v: %v", refResource, err)
212 }
213 reconciler.Reconcile(refResource, expectedReconcileResult, nil)
214
215
216 testk8s.RemoveDeletionDefenderFinalizer(t, k8sPolicyMember, v1beta1.IAMPolicyMemberGVK, kubeClient)
217 if err := kubeClient.Delete(context.TODO(), k8sPolicyMember); err != nil {
218 t.Fatalf("error deleting k8sPolicyMember: %v", err)
219 }
220 reconciler.ReconcileObjectMeta(k8sPolicyMember.ObjectMeta, v1beta1.IAMPolicyMemberGVK.Kind, expectedReconcileResult, nil)
221 if err := kubeClient.Get(context.TODO(), k8s.GetNamespacedName(k8sPolicyMember), k8sPolicyMember); err == nil || !apierrors.IsNotFound(err) {
222 t.Fatalf("unexpected error value: %v", err)
223 }
224
225 testcontroller.CollectEvents(t, mgr.GetConfig(), k8sPolicyMember.Namespace, 6, 5*time.Second)
226 testcontroller.AssertEventRecordedForObjectMetaAndKind(t, kubeClient, v1beta1.IAMPolicyMemberGVK.Kind, &k8sPolicyMember.ObjectMeta, k8s.Deleted)
227 }
228
229 func testReconcileResourceLevelAcquire(t *testing.T, mgr manager.Manager, k8sPolicyMember *v1beta1.IAMPolicyMember) {
230 kubeClient := mgr.GetClient()
231 provider := tfprovider.NewOrLogFatal(tfprovider.DefaultConfig)
232 smLoader := testservicemappingloader.New(t)
233 dclSchemaLoader, err := dclschemaloader.New()
234 dclConfig := clientconfig.NewForIntegrationTest()
235 if err != nil {
236 t.Fatalf("error creating a new DCL schema loader: %v", err)
237 }
238 serviceMetaLoader := dclmetadata.New()
239 converter := conversion.New(dclSchemaLoader, serviceMetaLoader)
240 iamClient := kcciamclient.New(provider, smLoader, kubeClient, converter, dclConfig)
241 reconciler := testreconciler.New(t, mgr, provider)
242
243
244 if _, err := iamClient.SetPolicyMember(context.TODO(), k8sPolicyMember); err != nil {
245 t.Fatalf("error creating GCP policy member: %v", err)
246 }
247
248
249 if err := kubeClient.Create(context.TODO(), k8sPolicyMember); err != nil {
250 t.Fatalf("error creating k8sPolicy: %v", err)
251 }
252 preReconcileGeneration := k8sPolicyMember.GetGeneration()
253 reconciler.ReconcileObjectMeta(k8sPolicyMember.ObjectMeta, v1beta1.IAMPolicyMemberGVK.Kind, expectedReconcileResult, nil)
254 if _, err := iamClient.GetPolicyMember(context.TODO(), k8sPolicyMember); err != nil {
255 t.Fatalf("unexpected error getting policy member: %v", err)
256 }
257 if err := kubeClient.Get(context.TODO(), k8s.GetNamespacedName(k8sPolicyMember), k8sPolicyMember); err != nil {
258 t.Fatalf("unexpected error getting k8s resource: %v", err)
259 }
260 testcontroller.AssertReadyCondition(t, k8sPolicyMember.Status.Conditions)
261 testcontroller.AssertEventRecordedForObjectMetaAndKind(t, kubeClient, v1beta1.IAMPolicyMemberGVK.Kind, &k8sPolicyMember.ObjectMeta, k8s.UpToDate)
262 assertObservedGenerationEquals(t, k8sPolicyMember, preReconcileGeneration)
263 }
264
265 func assertObservedGenerationEquals(t *testing.T, k8sPolicyMember *v1beta1.IAMPolicyMember, preReconcileGeneration int64) {
266 if k8sPolicyMember.Status.ObservedGeneration != preReconcileGeneration {
267 t.Errorf("observedGeneration %v doesn't match with the pre-reconcile generation %v", k8sPolicyMember.Status.ObservedGeneration, preReconcileGeneration)
268 }
269 }
270
271 func newIAMPolicyMemberFixture(t *testing.T, refResource *unstructured.Unstructured, resourceRef v1beta1.ResourceReference, role, member string) *v1beta1.IAMPolicyMember {
272 return &v1beta1.IAMPolicyMember{
273 TypeMeta: metav1.TypeMeta{
274 APIVersion: v1beta1.IAMPolicyMemberGVK.GroupVersion().String(),
275 Kind: v1beta1.IAMPolicyMemberGVK.Kind,
276 },
277 ObjectMeta: metav1.ObjectMeta{
278 Name: testcontroller.UniqueName(t, name(t)),
279 Namespace: refResource.GetNamespace(),
280 },
281 Spec: v1beta1.IAMPolicyMemberSpec{
282 Role: role,
283 Member: v1beta1.Member(member),
284 ResourceReference: resourceRef,
285 },
286 }
287 }
288
289 func name(t *testing.T) string {
290
291 name := strings.ToLower(testcontroller.Name(t))
292 return strings.Split(name, "/")[0]
293 }
294
295 func TestMain(m *testing.M) {
296 testmain.TestMainForIntegrationTests(m, &mgr)
297 }
298
View as plain text