Skip to content
This repository was archived by the owner on Dec 3, 2024. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b104ba1

Browse files
committedJan 18, 2021
Adding logic to process BR and BAR deletes.
1 parent 192f68c commit b104ba1

File tree

5 files changed

+434
-9
lines changed

5 files changed

+434
-9
lines changed
 

‎pkg/bucketaccessrequest/bucketaccessrequest.go

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ func (b *bucketAccessRequestListener) InitializeBucketClient(bc bucketclientset.
3434
b.bucketClient = bc
3535
}
3636

37+
// Add is in response to user adding a BucketAccessRequest. The call here will respond by creating a BucketAccess Object.
3738
func (b *bucketAccessRequestListener) Add(ctx context.Context, obj *v1alpha1.BucketAccessRequest) error {
3839
glog.V(1).Infof("Add called for BucketAccessRequest %s", obj.Name)
3940
bucketAccessRequest := obj
@@ -55,13 +56,24 @@ func (b *bucketAccessRequestListener) Add(ctx context.Context, obj *v1alpha1.Buc
5556
return nil
5657
}
5758

59+
// Update is called in response to a change to BucketAccessRequesst. At this point
60+
// BucketAccess cannot be changed once created as the Provisioner might have already acted upon the create BucketAccess and created the backend Bucket Credentials
61+
// Changes to Protocol, Provisioner, BucketInstanceName, BucketRequest cannot be allowed. Best is to delete and recreate a new BucketAccessRequest
62+
// Changes to ServiceAccount, PolicyActionsConfigMapData and Parameters should be considered in lieu with sidecar implementation
5863
func (b *bucketAccessRequestListener) Update(ctx context.Context, old, new *v1alpha1.BucketAccessRequest) error {
5964
glog.V(1).Infof("Update called for BucketAccessRequest %v", old.Name)
65+
if (old.ObjectMeta.DeletionTimestamp == nil) &&
66+
(new.ObjectMeta.DeletionTimestamp != nil) {
67+
// BucketAccessRequest is being deleted, check and remove finalizer once BA is deleted
68+
return b.removeBucketAccess(ctx, new)
69+
}
6070
return nil
6171
}
6272

63-
func (b *bucketAccessRequestListener) Delete(ctx context.Context, obj *v1alpha1.BucketAccessRequest) error {
64-
glog.V(1).Infof("Delete called for BucketAccessRequest %v", obj.Name)
73+
// Delete is in response to user deleting a BucketAccessRequest. The call here will respond by deleting a BucketAccess Object.
74+
func (b *bucketAccessRequestListener) Delete(ctx context.Context, bucketAccessRequest *v1alpha1.BucketAccessRequest) error {
75+
glog.V(1).Infof("Delete called for BucketAccessRequest %v", bucketAccessRequest.Name)
76+
6577
return nil
6678
}
6779

@@ -137,7 +149,7 @@ func (b *bucketAccessRequestListener) provisionBucketAccess(ctx context.Context,
137149
}
138150
// bucketaccess.Spec.MintedSecretName - set by the driver
139151
bucketaccess.Spec.PolicyActionsConfigMapData, err = util.ReadConfigData(b.kubeClient, bucketAccessClass.PolicyActionsConfigMap)
140-
if err != nil {
152+
if err != nil && err != util.ErrNilConfigMap {
141153
return err
142154
}
143155
// bucketaccess.Spec.Principal - set by the driver
@@ -152,6 +164,10 @@ func (b *bucketAccessRequestListener) provisionBucketAccess(ctx context.Context,
152164
return err
153165
}
154166

167+
if !util.CheckFinalizer(bucketAccessRequest, util.BARDeleteFinalizer) {
168+
bucketAccessRequest.ObjectMeta.Finalizers = append(bucketAccessRequest.ObjectMeta.Finalizers, util.BARDeleteFinalizer)
169+
}
170+
155171
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
156172
bucketAccessRequest.Spec.BucketAccessName = bucketaccess.Name
157173
_, err := barClient(bucketAccessRequest.Namespace).Update(ctx, bucketAccessRequest, metav1.UpdateOptions{})
@@ -167,17 +183,47 @@ func (b *bucketAccessRequestListener) provisionBucketAccess(ctx context.Context,
167183
return nil
168184
}
169185

170-
func (b *bucketAccessRequestListener) FindBucketAccess(ctx context.Context, bar *v1alpha1.BucketAccessRequest) *v1alpha1.BucketAccess {
186+
func (b *bucketAccessRequestListener) removeBucketAccess(ctx context.Context, bucketAccessRequest *v1alpha1.BucketAccessRequest) error {
187+
bucketaccess := b.FindBucketAccess(ctx, bucketAccessRequest)
188+
if bucketaccess == nil {
189+
// bucketaccess for this BucketAccessRequest is not found
190+
return util.ErrBucketAccessDoesNotExist
191+
}
192+
193+
// time to delete the BucketAccess Object
194+
err := b.bucketClient.ObjectstorageV1alpha1().BucketAccesses().Delete(context.Background(), bucketaccess.Name, metav1.DeleteOptions{})
195+
if err != nil {
196+
return err
197+
}
198+
199+
// we can safely remove the finalizer
200+
return b.removeBARDeleteFinalizer(ctx, bucketAccessRequest)
201+
}
202+
203+
func (b *bucketAccessRequestListener) FindBucketAccess(ctx context.Context, bucketAccessRequest *v1alpha1.BucketAccessRequest) *v1alpha1.BucketAccess {
171204
bucketAccessList, err := b.bucketClient.ObjectstorageV1alpha1().BucketAccesses().List(ctx, metav1.ListOptions{})
172205
if err != nil || len(bucketAccessList.Items) <= 0 {
173206
return nil
174207
}
175208
for _, bucketaccess := range bucketAccessList.Items {
176-
if bucketaccess.Spec.BucketAccessRequest.Name == bar.Name &&
177-
bucketaccess.Spec.BucketAccessRequest.Namespace == bar.Namespace &&
178-
bucketaccess.Spec.BucketAccessRequest.UID == bar.UID {
209+
if bucketaccess.Spec.BucketAccessRequest.Name == bucketAccessRequest.Name &&
210+
bucketaccess.Spec.BucketAccessRequest.Namespace == bucketAccessRequest.Namespace &&
211+
bucketaccess.Spec.BucketAccessRequest.UID == bucketAccessRequest.UID {
179212
return &bucketaccess
180213
}
181214
}
182215
return nil
183216
}
217+
218+
func (b *bucketAccessRequestListener) removeBARDeleteFinalizer(ctx context.Context, bucketAccessRequest *v1alpha1.BucketAccessRequest) error {
219+
newFinalizers := []string{}
220+
for _, finalizer := range bucketAccessRequest.ObjectMeta.Finalizers {
221+
if finalizer != util.BARDeleteFinalizer {
222+
newFinalizers = append(newFinalizers, finalizer)
223+
}
224+
}
225+
bucketAccessRequest.ObjectMeta.Finalizers = newFinalizers
226+
227+
_, err := b.bucketClient.ObjectstorageV1alpha1().BucketAccessRequests(bucketAccessRequest.Namespace).Update(ctx, bucketAccessRequest, metav1.UpdateOptions{})
228+
return err
229+
}

‎pkg/bucketaccessrequest/bucketaccessrequest_test.go

Lines changed: 179 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,22 @@ func TestAddBAR(t *testing.T) {
122122

123123
// Test add with multipleBRs
124124
func TestAddWithMultipleBAR(t *testing.T) {
125-
runCreateBucketWithMultipleBA(t, "addWithMultipleBR")
125+
runCreateBucketWithMultipleBA(t, "addWithMultipleBAR")
126126
}
127127

128128
// Test add idempotency
129129
func TestAddBARIdempotency(t *testing.T) {
130-
runCreateBucketIdempotency(t, "addWithMultipleBR")
130+
runCreateBucketIdempotency(t, "addBARIdempotency")
131+
}
132+
133+
// Test delete BAR
134+
func TestDeleteBAR(t *testing.T) {
135+
runDeleteBucketAccessRequest(t, "deleteBAR")
136+
}
137+
138+
// Test delete BAR Idempotency
139+
func TestDeleteBARIdempotency(t *testing.T) {
140+
runDeleteBucketAccessRequestIdempotency(t, "deleteBARIdempotency")
131141
}
132142

133143
func runCreateBucketAccess(t *testing.T, name string) {
@@ -333,3 +343,170 @@ func runCreateBucketIdempotency(t *testing.T, name string) {
333343
t.Fatalf("Expecting a single BucketAccess created but found %v", len(bucketAccessList.Items))
334344
}
335345
}
346+
347+
func runDeleteBucketAccessRequest(t *testing.T, name string) {
348+
ctx, cancel := context.WithCancel(context.Background())
349+
defer cancel()
350+
351+
client := bucketclientset.NewSimpleClientset()
352+
kubeClient := fake.NewSimpleClientset()
353+
354+
listener := NewListener()
355+
listener.InitializeKubeClient(kubeClient)
356+
listener.InitializeBucketClient(client)
357+
358+
_, err := kubeClient.CoreV1().ServiceAccounts(sa1.Namespace).Create(ctx, &sa1, metav1.CreateOptions{})
359+
if err != nil {
360+
t.Fatalf("Error occurred when creating ServiceAccount: %v", err)
361+
}
362+
defer kubeClient.CoreV1().ServiceAccounts(sa1.Namespace).Delete(ctx, sa1.Name, metav1.DeleteOptions{})
363+
364+
_, err = kubeClient.CoreV1().ConfigMaps(cosiConfigMap.Namespace).Create(ctx, &cosiConfigMap, metav1.CreateOptions{})
365+
if err != nil {
366+
t.Fatalf("Error occurred when creating ConfigMap: %v", err)
367+
}
368+
defer kubeClient.CoreV1().ConfigMaps(cosiConfigMap.Namespace).Delete(ctx, cosiConfigMap.Name, metav1.DeleteOptions{})
369+
370+
bucketaccessclass, err := util.CreateBucketAccessClass(ctx, client, &goldAccessClass)
371+
if err != nil {
372+
t.Fatalf("Error occurred when creating BucketAccessClass: %v", err)
373+
}
374+
375+
bucketrequest, err := util.CreateBucketRequest(ctx, client, &bucketRequest1)
376+
if err != nil {
377+
t.Fatalf("Error occurred when creating BucketRequest: %v", err)
378+
}
379+
380+
bucketaccessrequest, err := util.CreateBucketAccessRequest(ctx, client, &bucketAccessRequest1)
381+
if err != nil {
382+
t.Fatalf("Error occurred when creating BucketAccessRequest: %v", err)
383+
}
384+
385+
listener.Add(ctx, bucketaccessrequest)
386+
387+
bucketAccessList := util.GetBucketAccesses(ctx, client, 1)
388+
defer util.DeleteObjects(ctx, client, *bucketrequest, *bucketaccessrequest, *bucketaccessclass, bucketAccessList.Items)
389+
390+
if len(bucketAccessList.Items) != 1 {
391+
t.Fatalf("Expecting a single BucketAccess created but found %v", len(bucketAccessList.Items))
392+
}
393+
bucketaccess := bucketAccessList.Items[0]
394+
395+
bucketaccessrequest2, err := client.ObjectstorageV1alpha1().BucketAccessRequests(bucketaccessrequest.Namespace).Get(ctx, bucketaccessrequest.Name, metav1.GetOptions{})
396+
if err != nil {
397+
t.Fatalf("Error occurred when updating BucketAccessRequest: %v", err)
398+
}
399+
400+
if !util.ValidateBucketAccess(bucketaccess, *bucketaccessrequest, *bucketaccessclass) {
401+
t.Fatalf("Failed to compare the resulting BucketAccess with the BucketAccessRequest %v and BucketAccessClass %v", bucketaccessrequest, bucketaccessclass)
402+
}
403+
404+
//peform delete and see if the bucketAccessRequest can be deleted
405+
err = client.ObjectstorageV1alpha1().BucketAccessRequests(bucketaccessrequest2.Namespace).Delete(ctx, bucketaccessrequest2.Name, metav1.DeleteOptions{})
406+
if err != nil {
407+
t.Fatalf("Error occurred when deleting BucketAccessRequest: %v", err)
408+
}
409+
410+
// force update for the finalizer
411+
old := bucketaccessrequest
412+
now := metav1.Now()
413+
bucketaccessrequest2.ObjectMeta.DeletionTimestamp = &now
414+
listener.Update(ctx, old, bucketaccessrequest2)
415+
416+
// there should not be a corresponding BucketAccess
417+
bucketAccessList = util.GetBucketAccesses(ctx, client, 0)
418+
if len(bucketAccessList.Items) > 0 {
419+
t.Fatalf("Expecting BucketAccess object be deleted but found %v", bucketAccessList.Items)
420+
}
421+
}
422+
423+
func runDeleteBucketAccessRequestIdempotency(t *testing.T, name string) {
424+
ctx, cancel := context.WithCancel(context.Background())
425+
defer cancel()
426+
427+
client := bucketclientset.NewSimpleClientset()
428+
kubeClient := fake.NewSimpleClientset()
429+
430+
listener := NewListener()
431+
listener.InitializeKubeClient(kubeClient)
432+
listener.InitializeBucketClient(client)
433+
434+
_, err := kubeClient.CoreV1().ServiceAccounts(sa1.Namespace).Create(ctx, &sa1, metav1.CreateOptions{})
435+
if err != nil {
436+
t.Fatalf("Error occurred when creating ServiceAccount: %v", err)
437+
}
438+
defer kubeClient.CoreV1().ServiceAccounts(sa1.Namespace).Delete(ctx, sa1.Name, metav1.DeleteOptions{})
439+
440+
_, err = kubeClient.CoreV1().ConfigMaps(cosiConfigMap.Namespace).Create(ctx, &cosiConfigMap, metav1.CreateOptions{})
441+
if err != nil {
442+
t.Fatalf("Error occurred when creating ConfigMap: %v", err)
443+
}
444+
defer kubeClient.CoreV1().ConfigMaps(cosiConfigMap.Namespace).Delete(ctx, cosiConfigMap.Name, metav1.DeleteOptions{})
445+
446+
bucketaccessclass, err := util.CreateBucketAccessClass(ctx, client, &goldAccessClass)
447+
if err != nil {
448+
t.Fatalf("Error occurred when creating BucketAccessClass: %v", err)
449+
}
450+
451+
bucketrequest, err := util.CreateBucketRequest(ctx, client, &bucketRequest1)
452+
if err != nil {
453+
t.Fatalf("Error occurred when creating BucketRequest: %v", err)
454+
}
455+
456+
bucketaccessrequest, err := util.CreateBucketAccessRequest(ctx, client, &bucketAccessRequest1)
457+
if err != nil {
458+
t.Fatalf("Error occurred when creating BucketAccessRequest: %v", err)
459+
}
460+
461+
listener.Add(ctx, bucketaccessrequest)
462+
463+
bucketAccessList := util.GetBucketAccesses(ctx, client, 1)
464+
defer util.DeleteObjects(ctx, client, *bucketrequest, *bucketaccessrequest, *bucketaccessclass, bucketAccessList.Items)
465+
466+
if len(bucketAccessList.Items) != 1 {
467+
t.Fatalf("Expecting a single BucketAccess created but found %v", len(bucketAccessList.Items))
468+
}
469+
bucketaccess := bucketAccessList.Items[0]
470+
471+
bucketaccessrequest2, err := client.ObjectstorageV1alpha1().BucketAccessRequests(bucketaccessrequest.Namespace).Get(ctx, bucketaccessrequest.Name, metav1.GetOptions{})
472+
if err != nil {
473+
t.Fatalf("Error occurred when updating BucketAccessRequest: %v", err)
474+
}
475+
476+
if !util.ValidateBucketAccess(bucketaccess, *bucketaccessrequest, *bucketaccessclass) {
477+
t.Fatalf("Failed to compare the resulting BucketAccess with the BucketAccessRequest %v and BucketAccessClass %v", bucketaccessrequest, bucketaccessclass)
478+
}
479+
480+
//peform delete and see if the bucketAccessRequest can be deleted
481+
err = client.ObjectstorageV1alpha1().BucketAccessRequests(bucketaccessrequest2.Namespace).Delete(ctx, bucketaccessrequest2.Name, metav1.DeleteOptions{})
482+
if err != nil {
483+
t.Fatalf("Error occurred when deleting BucketAccessRequest: %v", err)
484+
}
485+
486+
// force update for the finalizer
487+
old := bucketaccessrequest
488+
now := metav1.Now()
489+
bucketaccessrequest2.ObjectMeta.DeletionTimestamp = &now
490+
listener.Update(ctx, old, bucketaccessrequest2)
491+
492+
//there should not be a corresponding BucketAccess
493+
bucketAccessList = util.GetBucketAccesses(ctx, client, 0)
494+
if len(bucketAccessList.Items) > 0 {
495+
t.Fatalf("Expecting BucketAccess object be deleted but found %v", bucketAccessList.Items)
496+
}
497+
498+
//Create a duplicate update
499+
listener.Update(ctx, old, bucketaccessrequest2)
500+
//there should not be a corresponding BucketAccess
501+
bucketAccessList = util.GetBucketAccesses(ctx, client, 0)
502+
if len(bucketAccessList.Items) > 0 {
503+
t.Fatalf("Expecting BucketAccess object be deleted but found %v", bucketAccessList.Items)
504+
}
505+
506+
// call the delete directly the second time
507+
listener.Delete(ctx, bucketaccessrequest)
508+
bucketAccessList = util.GetBucketAccesses(ctx, client, 0)
509+
if len(bucketAccessList.Items) != 0 {
510+
t.Fatalf("Expecting a single BucketAccess created but found %v", len(bucketAccessList.Items))
511+
}
512+
}

‎pkg/bucketrequest/bucketrequest.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ func (b *bucketRequestListener) Add(ctx context.Context, obj *v1alpha1.BucketReq
6262
// update processes any updates made to the bucket request
6363
func (b *bucketRequestListener) Update(ctx context.Context, old, new *v1alpha1.BucketRequest) error {
6464
glog.V(3).Infof("Update called for BucketRequest %v", old.Name)
65+
if (old.ObjectMeta.DeletionTimestamp == nil) &&
66+
(new.ObjectMeta.DeletionTimestamp != nil) {
67+
// BucketRequest is being deleted, check and remove finalizer once BA is deleted
68+
return b.removeBucket(ctx, new)
69+
}
6570
return nil
6671
}
6772

@@ -130,6 +135,10 @@ func (b *bucketRequestListener) provisionBucketRequestOperation(ctx context.Cont
130135
return err
131136
}
132137

138+
if !util.CheckFinalizer(bucketRequest, util.BRDeleteFinalizer) {
139+
bucketRequest.ObjectMeta.Finalizers = append(bucketRequest.ObjectMeta.Finalizers, util.BRDeleteFinalizer)
140+
}
141+
133142
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
134143
bucketRequest.Spec.BucketInstanceName = bucket.Name
135144
_, err := b.bucketClient.ObjectstorageV1alpha1().BucketRequests(bucketRequest.Namespace).Update(ctx, bucketRequest, metav1.UpdateOptions{})
@@ -145,6 +154,24 @@ func (b *bucketRequestListener) provisionBucketRequestOperation(ctx context.Cont
145154
return nil
146155
}
147156

157+
// When a BR is deleted before the finalizer is removed then the bucket corresponding to the BR should be deleted.
158+
func (b *bucketRequestListener) removeBucket(ctx context.Context, bucketRequest *v1alpha1.BucketRequest) error {
159+
bucket := b.FindBucket(ctx, bucketRequest)
160+
if bucket == nil {
161+
// bucket for this BucketRequest is not found
162+
return util.ErrBucketDoesNotExist
163+
}
164+
165+
// time to delete the Bucket Object
166+
err := b.bucketClient.ObjectstorageV1alpha1().Buckets().Delete(context.Background(), bucket.Name, metav1.DeleteOptions{})
167+
if err != nil {
168+
return err
169+
}
170+
171+
// we can safely remove the finalizer
172+
return b.removeBRDeleteFinalizer(ctx, bucketRequest)
173+
}
174+
148175
// GetBucketClass returns BucketClassName. If no bucket class was in the request it returns empty
149176
// TODO this methods can be more sophisticate to address bucketClass overrides using annotations just like SC.
150177
func (b *bucketRequestListener) GetBucketClass(bucketRequest *v1alpha1.BucketRequest) string {
@@ -175,6 +202,19 @@ func (b *bucketRequestListener) FindBucket(ctx context.Context, br *v1alpha1.Buc
175202
return nil
176203
}
177204

205+
func (b *bucketRequestListener) removeBRDeleteFinalizer(ctx context.Context, bucketRequest *v1alpha1.BucketRequest) error {
206+
newFinalizers := []string{}
207+
for _, finalizer := range bucketRequest.ObjectMeta.Finalizers {
208+
if finalizer != util.BRDeleteFinalizer {
209+
newFinalizers = append(newFinalizers, finalizer)
210+
}
211+
}
212+
bucketRequest.ObjectMeta.Finalizers = newFinalizers
213+
214+
_, err := b.bucketClient.ObjectstorageV1alpha1().BucketRequests(bucketRequest.Namespace).Update(ctx, bucketRequest, metav1.UpdateOptions{})
215+
return err
216+
}
217+
178218
// cloneTheBucket clones a bucket to a different namespace when a BR is for brownfield.
179219
func (b *bucketRequestListener) cloneTheBucket(bucketRequest *v1alpha1.BucketRequest) error {
180220
glog.V(1).Infof("Clone called for Bucket %s", bucketRequest.Spec.BucketInstanceName)

‎pkg/bucketrequest/bucketrequest_test.go

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ var bucketRequest2 = types.BucketRequest{
7272
},
7373
}
7474

75+
/*
7576
// Test basic add functionality
7677
func TestAddBR(t *testing.T) {
7778
runCreateBucket(t, "add")
@@ -86,6 +87,16 @@ func TestAddWithMultipleBR(t *testing.T) {
8687
func TestAddBRIdempotency(t *testing.T) {
8788
runCreateBucketIdempotency(t, "addWithMultipleBR")
8889
}
90+
*/
91+
// Test delete BR
92+
func TestDeleteBR(t *testing.T) {
93+
runDeleteBucketRequest(t, "deleteBR")
94+
}
95+
96+
// Test delete BR Idempotency
97+
func TestDeleteBRIdempotency(t *testing.T) {
98+
runDeleteBucketRequestIdempotency(t, "deleteBRIdempotency")
99+
}
89100

90101
func runCreateBucket(t *testing.T, name string) {
91102
ctx, cancel := context.WithCancel(context.Background())
@@ -234,3 +245,140 @@ func runCreateBucketIdempotency(t *testing.T, name string) {
234245
t.Fatalf("Expecting a single Bucket created but found %v", len(bucketList.Items))
235246
}
236247
}
248+
249+
func runDeleteBucketRequest(t *testing.T, name string) {
250+
ctx, cancel := context.WithCancel(context.Background())
251+
defer cancel()
252+
253+
client := bucketclientset.NewSimpleClientset()
254+
kubeClient := fake.NewSimpleClientset()
255+
256+
listener := NewListener()
257+
listener.InitializeKubeClient(kubeClient)
258+
listener.InitializeBucketClient(client)
259+
260+
bucketclass, err := util.CreateBucketClass(ctx, client, &goldClass)
261+
if err != nil {
262+
t.Fatalf("Error occurred when creating BucketClass: %v", err)
263+
}
264+
265+
bucketrequest, err := util.CreateBucketRequest(ctx, client, &bucketRequest1)
266+
if err != nil {
267+
t.Fatalf("Error occurred when creating BucketRequest: %v", err)
268+
}
269+
270+
listener.Add(ctx, bucketrequest)
271+
272+
bucketList := util.GetBuckets(ctx, client, 1)
273+
defer util.DeleteObjects(ctx, client, *bucketrequest, *bucketclass, bucketList.Items)
274+
275+
if len(bucketList.Items) != 1 {
276+
t.Fatalf("Expecting a single Bucket created but found %v", len(bucketList.Items))
277+
}
278+
bucket := bucketList.Items[0]
279+
280+
bucketrequest2, err := client.ObjectstorageV1alpha1().BucketRequests(bucketrequest.Namespace).Get(ctx, bucketrequest.Name, metav1.GetOptions{})
281+
if err != nil {
282+
t.Fatalf("Error occurred when reading BucketRequest: %v", err)
283+
}
284+
285+
if util.ValidateBucket(bucket, *bucketrequest, *bucketclass) {
286+
return
287+
} else {
288+
t.Fatalf("Failed to compare the resulting Bucket with the BucketRequest %v and BucketClass %v", bucketrequest, bucketclass)
289+
}
290+
291+
//peform delete and see if the bucketRequest can be deleted
292+
err = client.ObjectstorageV1alpha1().BucketRequests(bucketrequest2.Namespace).Delete(ctx, bucketrequest2.Name, metav1.DeleteOptions{})
293+
if err != nil {
294+
t.Fatalf("Error occurred when deleting BucketRequest: %v", err)
295+
}
296+
297+
// force update for the finalizer
298+
old := bucketrequest
299+
now := metav1.Now()
300+
bucketrequest2.ObjectMeta.DeletionTimestamp = &now
301+
listener.Update(ctx, old, bucketrequest2)
302+
303+
// there should not be a corresponding Bucket
304+
bucketList = util.GetBuckets(ctx, client, 0)
305+
if len(bucketList.Items) > 0 {
306+
t.Fatalf("Expecting Bucket object be deleted but found %v", bucketList.Items)
307+
}
308+
}
309+
310+
func runDeleteBucketRequestIdempotency(t *testing.T, name string) {
311+
ctx, cancel := context.WithCancel(context.Background())
312+
defer cancel()
313+
314+
client := bucketclientset.NewSimpleClientset()
315+
kubeClient := fake.NewSimpleClientset()
316+
317+
listener := NewListener()
318+
listener.InitializeKubeClient(kubeClient)
319+
listener.InitializeBucketClient(client)
320+
321+
bucketclass, err := util.CreateBucketClass(ctx, client, &goldClass)
322+
if err != nil {
323+
t.Fatalf("Error occurred when creating BucketClass: %v", err)
324+
}
325+
326+
bucketrequest, err := util.CreateBucketRequest(ctx, client, &bucketRequest1)
327+
if err != nil {
328+
t.Fatalf("Error occurred when creating BucketRequest: %v", err)
329+
}
330+
331+
listener.Add(ctx, bucketrequest)
332+
333+
bucketList := util.GetBuckets(ctx, client, 1)
334+
defer util.DeleteObjects(ctx, client, *bucketrequest, *bucketclass, bucketList.Items)
335+
336+
if len(bucketList.Items) != 1 {
337+
t.Fatalf("Expecting a single Bucket created but found %v", len(bucketList.Items))
338+
}
339+
bucket := bucketList.Items[0]
340+
341+
bucketrequest2, err := client.ObjectstorageV1alpha1().BucketRequests(bucketrequest.Namespace).Get(ctx, bucketrequest.Name, metav1.GetOptions{})
342+
if err != nil {
343+
t.Fatalf("Error occurred when reading BucketRequest: %v", err)
344+
}
345+
346+
if util.ValidateBucket(bucket, *bucketrequest, *bucketclass) {
347+
return
348+
} else {
349+
t.Fatalf("Failed to compare the resulting Bucket with the BucketRequest %v and BucketClass %v", bucketrequest, bucketclass)
350+
}
351+
352+
//peform delete and see if the bucketRequest can be deleted
353+
err = client.ObjectstorageV1alpha1().BucketRequests(bucketrequest2.Namespace).Delete(ctx, bucketrequest2.Name, metav1.DeleteOptions{})
354+
if err != nil {
355+
t.Fatalf("Error occurred when deleting BucketRequest: %v", err)
356+
}
357+
358+
// force update for the finalizer
359+
old := bucketrequest
360+
now := metav1.Now()
361+
bucketrequest2.ObjectMeta.DeletionTimestamp = &now
362+
listener.Update(ctx, old, bucketrequest2)
363+
364+
// there should not be a corresponding Bucket
365+
bucketList = util.GetBuckets(ctx, client, 0)
366+
if len(bucketList.Items) > 0 {
367+
t.Fatalf("Expecting Bucket object be deleted but found %v", bucketList.Items)
368+
}
369+
370+
//Create a duplicate update
371+
listener.Update(ctx, old, bucketrequest2)
372+
//there should not be a corresponding Bucket
373+
bucketList = util.GetBuckets(ctx, client, 0)
374+
if len(bucketList.Items) > 0 {
375+
t.Fatalf("Expecting Bucket object be deleted but found %v", bucketList.Items)
376+
}
377+
378+
// call the delete directly the second time
379+
listener.Delete(ctx, bucketrequest)
380+
bucketList = util.GetBuckets(ctx, client, 0)
381+
if len(bucketList.Items) != 0 {
382+
t.Fatalf("Expecting a single Bucket created but found %v", len(bucketList.Items))
383+
}
384+
}

‎pkg/util/util.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ var (
4747
ErrBCUnavailable = errors.New("BucketClass is not available")
4848
ErrNotImplemented = errors.New("Operation Not Implemented")
4949
ErrNilConfigMap = errors.New("ConfigMap cannot be nil")
50+
ErrBucketDoesNotExist = errors.New("Cannot find Bucket to perform delete on BucketRequest")
51+
ErrBucketAccessDoesNotExist = errors.New("Cannot find BucketAccess to perform delete on BucketAccessRequest")
52+
53+
BRDeleteFinalizer = "bucketrequest.objectstorage.k8s.io/delete-protection"
54+
BARDeleteFinalizer = "bucketaccessrequest.objectstorage.k8s.io/delete-protection"
5055
)
5156

5257
func CopySS(m map[string]string) map[string]string {
@@ -92,6 +97,15 @@ func ReadConfigData(kubeClient kubeclientset.Interface, configMapRef *v1.ObjectR
9297
return string(cData), nil
9398
}
9499

100+
func CheckFinalizer(obj metav1.Object, finalizer string) bool {
101+
for _, f := range obj.GetFinalizers() {
102+
if f == finalizer {
103+
return true
104+
}
105+
}
106+
return false
107+
}
108+
95109
// SetupTest is utility function to create clients and controller
96110
// This is used by bucket request and bucket access request unit tests
97111
func SetupTest(ctx context.Context) (bucketclientset.Interface, kubeclientset.Interface, *controller.ObjectStorageController) {

0 commit comments

Comments
 (0)
This repository has been archived.