Skip to content
This repository was archived by the owner on Apr 17, 2025. It is now read-only.

Commit bb33c3d

Browse files
committed
Better organize adding/removing finalizers
To be able to distinguish between updating just the status and updating the full resource. Tested: Ran both unit-tests ('make test') and integration test ('make test-e2e') successfully.
1 parent 34837c2 commit bb33c3d

File tree

2 files changed

+31
-24
lines changed

2 files changed

+31
-24
lines changed

internal/anchor/reconciler.go

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"k8s.io/apimachinery/pkg/types"
2727
ctrl "sigs.k8s.io/controller-runtime"
2828
"sigs.k8s.io/controller-runtime/pkg/client"
29+
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
2930
"sigs.k8s.io/controller-runtime/pkg/event"
3031
"sigs.k8s.io/controller-runtime/pkg/handler"
3132
"sigs.k8s.io/controller-runtime/pkg/reconcile"
@@ -81,9 +82,9 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
8182
// Anchors in unmanaged namespace should be ignored. Make sure it
8283
// doesn't have any finalizers, otherwise, leave it alone.
8384
if why := config.WhyUnmanaged(pnm); why != "" {
84-
if len(inst.ObjectMeta.Finalizers) > 0 {
85+
if controllerutil.ContainsFinalizer(inst, api.MetaGroup) {
8586
log.Info("Removing finalizers from anchor in unmanaged namespace", "reason", why)
86-
inst.ObjectMeta.Finalizers = nil
87+
controllerutil.RemoveFinalizer(inst, api.MetaGroup)
8788
return ctrl.Result{}, r.writeInstance(ctx, log, inst)
8889
}
8990
return ctrl.Result{}, nil
@@ -94,10 +95,10 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
9495
// been bypassed and the anchor has been successfully created. Forbidden
9596
// anchors won't have finalizers.
9697
if why := config.WhyUnmanaged(nm); why != "" {
97-
if inst.Status.State != api.Forbidden || len(inst.ObjectMeta.Finalizers) > 0 {
98+
if inst.Status.State != api.Forbidden || controllerutil.ContainsFinalizer(inst, api.MetaGroup) {
9899
log.Info("Setting forbidden state on anchor with unmanaged name", "reason", why)
99100
inst.Status.State = api.Forbidden
100-
inst.ObjectMeta.Finalizers = nil
101+
controllerutil.RemoveFinalizer(inst, api.MetaGroup)
101102
return ctrl.Result{}, r.writeInstance(ctx, log, inst)
102103
}
103104
return ctrl.Result{}, nil
@@ -130,9 +131,6 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
130131
}
131132
}
132133

133-
// Add finalizers on all non-forbidden anchors to ensure it's not deleted until
134-
// after the subnamespace is deleted.
135-
inst.ObjectMeta.Finalizers = []string{api.MetaGroup}
136134
return ctrl.Result{}, r.writeInstance(ctx, log, inst)
137135
}
138136

@@ -146,8 +144,13 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
146144
// if allowCascadingDeletion is disabled but the subnamespace has descendants (see
147145
// shouldDeleteSubns for details). In such cases, we move straight to step 2.
148146
func (r *Reconciler) onDeleting(ctx context.Context, log logr.Logger, inst *api.SubnamespaceAnchor, snsInst *corev1.Namespace) (bool, error) {
149-
// Early exit and continue reconciliation if the instance is not being deleted.
147+
// Early exit, ensure finalizer is present and continue reconciliation if the instance is not being deleted.
150148
if inst.DeletionTimestamp.IsZero() {
149+
// Add finalizers on all non-forbidden anchors to ensure it's not deleted until
150+
// after the subnamespace is deleted.
151+
if !controllerutil.ContainsFinalizer(inst, api.MetaGroup) {
152+
controllerutil.AddFinalizer(inst, api.MetaGroup)
153+
}
151154
return false, nil
152155
}
153156

@@ -168,13 +171,16 @@ func (r *Reconciler) onDeleting(ctx context.Context, log logr.Logger, inst *api.
168171
log.Info("Deleting subnamespace due to anchor being deleted")
169172
return true, r.deleteNamespace(ctx, log, snsInst)
170173
case r.shouldFinalizeAnchor(log, inst, snsInst):
171-
log.V(1).Info("Unblocking deletion") // V(1) since we'll very shortly show an "anchor deleted" message
172-
inst.ObjectMeta.Finalizers = nil
173-
return true, r.writeInstance(ctx, log, inst)
174+
if controllerutil.ContainsFinalizer(inst, api.MetaGroup) {
175+
log.V(1).Info("Unblocking deletion") // V(1) since we'll very shortly show an "anchor deleted" message
176+
controllerutil.RemoveFinalizer(inst, api.MetaGroup)
177+
return true, r.writeInstance(ctx, log, inst)
178+
}
179+
return true, nil
174180
default:
175181
// There's nothing to do; we're just waiting for something to happen. Print out a log message
176182
// indicating what we're waiting for.
177-
if len(inst.ObjectMeta.Finalizers) > 0 {
183+
if controllerutil.ContainsFinalizer(inst, api.MetaGroup) {
178184
log.Info("Waiting for subnamespace to be fully purged before letting the anchor be deleted")
179185
} else {
180186
// I doubt we'll ever get here but I suppose it's possible
@@ -213,7 +219,7 @@ func (r *Reconciler) shouldDeleteSubns(log logr.Logger, inst *api.SubnamespaceAn
213219
log.V(1).Info("The subnamespace is already being deleted; no need to delete again")
214220
return false
215221
}
216-
if len(inst.ObjectMeta.Finalizers) == 0 {
222+
if !controllerutil.ContainsFinalizer(inst, api.MetaGroup) {
217223
log.V(1).Info("The anchor has already been finalized; do not reconsider deleting the namespace")
218224
return false
219225
}
@@ -257,7 +263,7 @@ func (r *Reconciler) shouldDeleteSubns(log logr.Logger, inst *api.SubnamespaceAn
257263
// deleted, it's in the process of being deleted, etc).
258264
func (r *Reconciler) shouldFinalizeAnchor(log logr.Logger, inst *api.SubnamespaceAnchor, snsInst *corev1.Namespace) bool {
259265
// If the anchor is already finalized, there's no need to do it again.
260-
if len(inst.ObjectMeta.Finalizers) == 0 {
266+
if !controllerutil.ContainsFinalizer(inst, api.MetaGroup) {
261267
return false
262268
}
263269

internal/hierarchyconfig/reconciler.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
ctrl "sigs.k8s.io/controller-runtime"
3131
"sigs.k8s.io/controller-runtime/pkg/client"
3232
"sigs.k8s.io/controller-runtime/pkg/controller"
33+
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
3334
"sigs.k8s.io/controller-runtime/pkg/event"
3435
"sigs.k8s.io/controller-runtime/pkg/handler"
3536
"sigs.k8s.io/controller-runtime/pkg/reconcile"
@@ -133,9 +134,9 @@ func (r *Reconciler) handleUnmanaged(ctx context.Context, log logr.Logger, nm st
133134
// Remove the finalizers if there are any. Note that while getSingleton can return an invalid
134135
// object (i.e. one without a name or namespace, if there's no singleton on the server), it can
135136
// never do that if there are finalizers or children so this is safe to write back.
136-
if len(inst.ObjectMeta.Finalizers) > 0 || len(inst.Status.Children) > 0 {
137+
if controllerutil.ContainsFinalizer(inst, api.FinalizerHasSubnamespace) || len(inst.Status.Children) > 0 {
137138
log.Info("Removing finalizers and children on unmanaged singleton")
138-
inst.ObjectMeta.Finalizers = nil
139+
controllerutil.RemoveFinalizer(inst, api.FinalizerHasSubnamespace)
139140
inst.Status.Children = nil
140141
stats.WriteHierConfig()
141142
if err := r.Update(ctx, inst); err != nil {
@@ -241,27 +242,27 @@ func (r *Reconciler) addIncludedNamespaceLabel(log logr.Logger, nsInst *corev1.N
241242
// .spec.allowCascadingDeletion field, so if we allowed this object to be deleted before all
242243
// descendants have been deleted, we would lose the knowledge that cascading deletion is enabled.
243244
func (r *Reconciler) updateFinalizers(log logr.Logger, inst *api.HierarchyConfiguration, nsInst *corev1.Namespace, anms []string) {
244-
// No-one should put a finalizer on a hierarchy config except us. See
245-
// https://github.com/kubernetes-sigs/hierarchical-namespaces/issues/623 as we try to enforce that.
246245
switch {
247246
case len(anms) == 0:
248247
// There are no subnamespaces in this namespace. The HC instance can be safely deleted anytime.
249-
if len(inst.ObjectMeta.Finalizers) > 0 {
248+
if controllerutil.ContainsFinalizer(inst, api.FinalizerHasSubnamespace) {
250249
log.V(1).Info("Removing finalizers since there are no longer any anchors in the namespace.")
250+
controllerutil.RemoveFinalizer(inst, api.FinalizerHasSubnamespace)
251251
}
252-
inst.ObjectMeta.Finalizers = nil
253252
case !inst.DeletionTimestamp.IsZero() && nsInst.DeletionTimestamp.IsZero():
254253
// If the HC instance is being deleted but not the namespace (which means
255254
// it's not a cascading delete), remove the finalizers to let it go through.
256255
// This is the only case the finalizers can be removed even when the
257256
// namespace has subnamespaces. (A default HC will be recreated later.)
258-
log.Info("Removing finalizers to allow a single deletion of the singleton (not involved in a cascading deletion).")
259-
inst.ObjectMeta.Finalizers = nil
257+
if controllerutil.ContainsFinalizer(inst, api.FinalizerHasSubnamespace) {
258+
log.Info("Removing finalizers to allow a single deletion of the singleton (not involved in a cascading deletion).")
259+
controllerutil.RemoveFinalizer(inst, api.FinalizerHasSubnamespace)
260+
}
260261
default:
261-
if len(inst.ObjectMeta.Finalizers) == 0 {
262+
if !controllerutil.ContainsFinalizer(inst, api.FinalizerHasSubnamespace) {
262263
log.Info("Adding finalizers since there's at least one anchor in the namespace.")
264+
controllerutil.AddFinalizer(inst, api.FinalizerHasSubnamespace)
263265
}
264-
inst.ObjectMeta.Finalizers = []string{api.FinalizerHasSubnamespace}
265266
}
266267
}
267268

0 commit comments

Comments
 (0)