Skip to content

Commit bb6ad2f

Browse files
committed
update to workapplier to use foreground deletion, add and fix tests
Signed-off-by: Britania Rodriguez Reyes <britaniar@microsoft.com>
1 parent d9e0d1b commit bb6ad2f

File tree

5 files changed

+531
-189
lines changed

5 files changed

+531
-189
lines changed

pkg/controllers/workapplier/controller.go

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
417417
Kind: fleetv1beta1.AppliedWorkKind,
418418
Name: appliedWork.GetName(),
419419
UID: appliedWork.GetUID(),
420-
BlockOwnerDeletion: ptr.To(false),
420+
BlockOwnerDeletion: ptr.To(true),
421421
}
422422

423423
// Set the default values for the Work object to avoid additional validation logic in the
@@ -487,7 +487,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
487487

488488
// garbageCollectAppliedWork deletes the appliedWork and all the manifests associated with it from the cluster.
489489
func (r *Reconciler) garbageCollectAppliedWork(ctx context.Context, work *fleetv1beta1.Work) (ctrl.Result, error) {
490-
deletePolicy := metav1.DeletePropagationBackground
490+
deletePolicy := metav1.DeletePropagationForeground
491491
if !controllerutil.ContainsFinalizer(work, fleetv1beta1.WorkFinalizer) {
492492
return ctrl.Result{}, nil
493493
}
@@ -496,18 +496,22 @@ func (r *Reconciler) garbageCollectAppliedWork(ctx context.Context, work *fleetv
496496
appliedWork := fleetv1beta1.AppliedWork{
497497
ObjectMeta: metav1.ObjectMeta{Name: work.Name},
498498
}
499-
err := r.spokeClient.Delete(ctx, &appliedWork, &client.DeleteOptions{PropagationPolicy: &deletePolicy})
500-
switch {
501-
case apierrors.IsNotFound(err):
502-
klog.V(2).InfoS("The appliedWork is already deleted", "appliedWork", work.Name)
503-
case err != nil:
504-
klog.ErrorS(err, "Failed to delete the appliedWork", "appliedWork", work.Name)
499+
if err := r.spokeClient.Delete(ctx, &appliedWork, &client.DeleteOptions{PropagationPolicy: &deletePolicy}); err != nil {
500+
if apierrors.IsNotFound(err) {
501+
klog.V(2).InfoS("The appliedWork is already deleted", "appliedWork", work.Name)
502+
return r.removeWorkFinalizer(ctx, work)
503+
}
504+
klog.V(2).ErrorS(err, "Failed to delete the appliedWork", "appliedWork", work.Name)
505505
return ctrl.Result{}, controller.NewAPIServerError(false, err)
506-
default:
507-
klog.InfoS("Successfully deleted the appliedWork", "appliedWork", work.Name)
508506
}
509-
controllerutil.RemoveFinalizer(work, fleetv1beta1.WorkFinalizer)
510507

508+
klog.V(2).InfoS("Deletion for appliedWork is in progress", "appliedWork", work.Name)
509+
return ctrl.Result{Requeue: true}, nil
510+
}
511+
512+
// removeWorkFinalizer removes the finalizer from the work and updates it in the hub.
513+
func (r *Reconciler) removeWorkFinalizer(ctx context.Context, work *fleetv1beta1.Work) (ctrl.Result, error) {
514+
controllerutil.RemoveFinalizer(work, fleetv1beta1.WorkFinalizer)
511515
if err := r.hubClient.Update(ctx, work, &client.UpdateOptions{}); err != nil {
512516
klog.ErrorS(err, "Failed to remove the finalizer from the work", "work", klog.KObj(work))
513517
return ctrl.Result{}, controller.NewAPIServerError(false, err)
@@ -557,6 +561,11 @@ func (r *Reconciler) ensureAppliedWork(ctx context.Context, work *fleetv1beta1.W
557561
return nil, controller.NewAPIServerError(false, err)
558562
}
559563
}
564+
565+
if err := r.spokeClient.Get(ctx, types.NamespacedName{Name: workRef.Name}, appliedWork); err != nil {
566+
klog.ErrorS(err, "Failed to get the appliedWork", "appliedWork", appliedWork.Name)
567+
return nil, controller.NewAPIServerError(false, err)
568+
}
560569
klog.InfoS("Recreated the appliedWork resource", "appliedWork", workRef.Name)
561570
return appliedWork, nil
562571
}

pkg/controllers/workapplier/controller_integration_migrated_helper_test.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
. "github.com/onsi/ginkgo/v2"
2525
. "github.com/onsi/gomega"
2626
corev1 "k8s.io/api/core/v1"
27+
apierrors "k8s.io/apimachinery/pkg/api/errors"
2728
"k8s.io/apimachinery/pkg/api/meta"
2829
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2930
"k8s.io/apimachinery/pkg/runtime"
@@ -137,3 +138,92 @@ func waitForWorkToBeHandled(workName, workNS string) *fleetv1beta1.Work {
137138
}, eventuallyDuration, eventuallyInterval).Should(BeTrue())
138139
return &resultWork
139140
}
141+
142+
// verifyConfigMapExists verifies that the configmap exists in member cluster
143+
func verifyConfigMapExists(cm *corev1.ConfigMap, resourceNamespace string) {
144+
Consistently(func() bool {
145+
var configMap corev1.ConfigMap
146+
err := memberClient.Get(context.Background(), types.NamespacedName{Name: cm.Name, Namespace: resourceNamespace}, &configMap)
147+
return !apierrors.IsNotFound(err)
148+
}, consistentlyDuration, consistentlyInterval).Should(BeTrue(), fmt.Sprintf("ConfigMap %s should not be deleted", cm.Name))
149+
}
150+
151+
// verifyConfigmapIsRemoved verifies that the configmap is removed from member cluster
152+
func verifyConfigmapIsRemoved(cm *corev1.ConfigMap, ns string) {
153+
Eventually(func() bool {
154+
var configMap corev1.ConfigMap
155+
err := memberClient.Get(context.Background(), types.NamespacedName{Name: cm.Name, Namespace: ns}, &configMap)
156+
return apierrors.IsNotFound(err)
157+
}, eventuallyDuration*5, eventuallyInterval).Should(BeTrue(), fmt.Sprintf("ConfigMap %s should be deleted", cm.Name))
158+
}
159+
160+
// verifyWorkIsDeleted verifies that the work is deleted from the hub cluster
161+
func verifyWorkIsDeleted(work *fleetv1beta1.Work) {
162+
Eventually(func() bool {
163+
var currentWork fleetv1beta1.Work
164+
return apierrors.IsNotFound(hubClient.Get(context.Background(), types.NamespacedName{Name: work.Name, Namespace: memberReservedNSName}, &currentWork))
165+
}, eventuallyDuration, eventuallyInterval).Should(BeTrue(), "Work should be deleted")
166+
}
167+
168+
// verifyAppliedWorkIsDeleted verifies that the applied work is deleted from the hub cluster
169+
func verifyAppliedWorkIsDeleted(name string) {
170+
Eventually(func() bool {
171+
var currentAppliedWork fleetv1beta1.AppliedWork
172+
return apierrors.IsNotFound(hubClient.Get(context.Background(), types.NamespacedName{Name: name}, &currentAppliedWork))
173+
}, eventuallyDuration, eventuallyInterval).Should(BeTrue(), "AppliedWork should be deleted")
174+
}
175+
176+
// verifyNamespaceIsDeleted verifies that the namespace is deleted from the hub cluster
177+
func verifyNamespaceIsDeleted(nsName string) {
178+
Eventually(func() bool {
179+
var ns corev1.Namespace
180+
return apierrors.IsNotFound(hubClient.Get(context.Background(), types.NamespacedName{Name: nsName}, &ns))
181+
}, eventuallyDuration, eventuallyInterval).Should(BeTrue(), "Namespace should be deleted")
182+
}
183+
184+
// removeFinalizersFromResource removes the finalizers from the configmap to delete
185+
func removeFinalizersFromResource(cm *corev1.ConfigMap) {
186+
var configMap corev1.ConfigMap
187+
Expect(memberClient.Get(context.Background(), types.NamespacedName{Name: cm.Name, Namespace: cm.Namespace}, &configMap)).Should(Succeed(), "Failed to get configmap")
188+
controllerutil.RemoveFinalizer(&configMap, "example.com/finalizer")
189+
Expect(memberClient.Update(context.Background(), &configMap)).Should(Succeed(), "Failed to remove finalizers from configmap")
190+
}
191+
192+
func addFinalizerToConfigMap(cm *corev1.ConfigMap) {
193+
// Add finalizer to the configmap
194+
var configMap corev1.ConfigMap
195+
Expect(memberClient.Get(context.Background(), types.NamespacedName{Name: cm.Name, Namespace: cm.Namespace}, &configMap)).Should(Succeed())
196+
controllerutil.AddFinalizer(&configMap, "example.com/finalizer")
197+
Expect(memberClient.Update(context.Background(), &configMap)).Should(Succeed())
198+
By("Added finalizer to configmap")
199+
}
200+
201+
func cleanupResources(cm, cm2 *corev1.ConfigMap, ns *corev1.Namespace, work *fleetv1beta1.Work) {
202+
// Remove finalizers from the configmap
203+
removeFinalizersFromResource(cm)
204+
removeFinalizersFromResource(cm2)
205+
206+
// Delete the configmap
207+
Expect(memberClient.Delete(context.Background(), cm)).Should(Succeed())
208+
Expect(memberClient.Delete(context.Background(), cm2)).Should(Succeed())
209+
210+
// Verify the configmap is deleted
211+
verifyConfigmapIsRemoved(cm, cm.Namespace)
212+
verifyConfigmapIsRemoved(cm2, cm2.Namespace)
213+
214+
// Delete the namespace
215+
Expect(memberClient.Delete(context.Background(), ns)).Should(Succeed())
216+
verifyNamespaceIsDeleted(ns.Name)
217+
218+
// Remove finalizers from the applied work. Needed as there
219+
var currentAppliedWork fleetv1beta1.AppliedWork
220+
Expect(memberClient.Get(context.Background(), types.NamespacedName{Name: work.Name}, &currentAppliedWork)).Should(Succeed(), "Failed to get applied work")
221+
controllerutil.RemoveFinalizer(&currentAppliedWork, metav1.FinalizerDeleteDependents)
222+
Expect(memberClient.Update(context.Background(), &currentAppliedWork)).Should(Succeed(), "Failed to remove finalizers from applied work")
223+
224+
// verify the applied work is deleted
225+
verifyAppliedWorkIsDeleted(work.Name)
226+
227+
// verify the work is deleted
228+
verifyWorkIsDeleted(work)
229+
}

0 commit comments

Comments
 (0)