Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Use Patch instead of Update to add/remove finalizers #1801

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions controllers/controller_shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ import (
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/predicate"
)
Expand Down Expand Up @@ -366,3 +368,35 @@ func getReferencedValue(ctx context.Context, cl client.Client, cr metav1.ObjectM
}
}
}

// Add finalizer through a MergePatch
// Avoids updating the entire object and only changes the finalizers
func addFinalizer(ctx context.Context, cl client.Client, cr client.Object) error {
// Only update when changed
if controllerutil.AddFinalizer(cr, grafanaFinalizer) {
return patchFinalizers(ctx, cl, cr)
}
return nil
}

// Remove finalizer through a MergePatch
// Avoids updating the entire object and only changes the finalizers
func removeFinalizer(ctx context.Context, cl client.Client, cr client.Object) error {
// Only update when changed
if controllerutil.RemoveFinalizer(cr, grafanaFinalizer) {
return patchFinalizers(ctx, cl, cr)
}
return nil
}

// Helper func for add/remove, avoid using directly
func patchFinalizers(ctx context.Context, cl client.Client, cr client.Object) error {
crFinalizers := cr.GetFinalizers()

// Create patch using slice
patch, err := json.Marshal(map[string]interface{}{"metadata": map[string]interface{}{"finalizers": crFinalizers}})
if err != nil {
return err
}
return cl.Patch(ctx, cr, client.RawPatch(types.MergePatchType, patch))
}
24 changes: 11 additions & 13 deletions controllers/grafanaalertrulegroup_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,13 @@ func (r *GrafanaAlertRuleGroupReconciler) Reconcile(ctx context.Context, req ctr
}

if group.GetDeletionTimestamp() != nil {
// Check if resource needs clean up
if controllerutil.ContainsFinalizer(group, grafanaFinalizer) {
// still need to clean up
err := r.finalize(ctx, group)
if err != nil {
return ctrl.Result{}, fmt.Errorf("cleaning up alert rule group: %w", err)
if err := r.finalize(ctx, group); err != nil {
return ctrl.Result{}, fmt.Errorf("failed to finalize GrafanaAlertRuleGroup: %w", err)
}
controllerutil.RemoveFinalizer(group, grafanaFinalizer)
if err := r.Update(ctx, group); err != nil {
r.Log.Error(err, "failed to remove finalizer")
return ctrl.Result{}, err
if err := removeFinalizer(ctx, r.Client, group); err != nil {
return ctrl.Result{}, fmt.Errorf("failed to remove finalizer: %w", err)
}
}
return ctrl.Result{}, nil
Expand All @@ -96,12 +93,13 @@ func (r *GrafanaAlertRuleGroupReconciler) Reconcile(ctx context.Context, req ctr
r.Log.Error(err, "updating status")
}
if meta.IsStatusConditionTrue(group.Status.Conditions, conditionNoMatchingInstance) {
controllerutil.RemoveFinalizer(group, grafanaFinalizer)
if err := removeFinalizer(ctx, r.Client, group); err != nil {
r.Log.Error(err, "failed to remove finalizer")
}
} else {
controllerutil.AddFinalizer(group, grafanaFinalizer)
}
if err := r.Update(ctx, group); err != nil {
r.Log.Error(err, "failed to set finalizer")
if err := addFinalizer(ctx, r.Client, group); err != nil {
r.Log.Error(err, "failed to set finalizer")
}
}
}()

Expand Down
23 changes: 11 additions & 12 deletions controllers/grafanacontactpoint_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,13 @@ func (r *GrafanaContactPointReconciler) Reconcile(ctx context.Context, req ctrl.
}

if contactPoint.GetDeletionTimestamp() != nil {
// Check if resource needs clean up
if controllerutil.ContainsFinalizer(contactPoint, grafanaFinalizer) {
err := r.finalize(ctx, contactPoint)
if err != nil {
return ctrl.Result{RequeueAfter: RequeueDelay}, fmt.Errorf("failed to finalize GrafanaContactPoint: %w", err)
if err := r.finalize(ctx, contactPoint); err != nil {
return ctrl.Result{}, fmt.Errorf("failed to finalize GrafanaContactPoint: %w", err)
}
controllerutil.RemoveFinalizer(contactPoint, grafanaFinalizer)
if err := r.Update(ctx, contactPoint); err != nil {
r.Log.Error(err, "failed to remove finalizer")
return ctrl.Result{RequeueAfter: RequeueDelay}, fmt.Errorf("failed to update GrafanaContactPoint: %w", err)
if err := removeFinalizer(ctx, r.Client, contactPoint); err != nil {
return ctrl.Result{}, fmt.Errorf("failed to remove finalizer: %w", err)
}
}
return ctrl.Result{}, nil
Expand All @@ -101,12 +99,13 @@ func (r *GrafanaContactPointReconciler) Reconcile(ctx context.Context, req ctrl.
r.Log.Error(err, "updating status")
}
if meta.IsStatusConditionTrue(contactPoint.Status.Conditions, conditionNoMatchingInstance) {
controllerutil.RemoveFinalizer(contactPoint, grafanaFinalizer)
if err := removeFinalizer(ctx, r.Client, contactPoint); err != nil {
r.Log.Error(err, "failed to remove finalizer")
}
} else {
controllerutil.AddFinalizer(contactPoint, grafanaFinalizer)
}
if err := r.Update(ctx, contactPoint); err != nil {
r.Log.Error(err, "failed to set finalizer")
if err := addFinalizer(ctx, r.Client, contactPoint); err != nil {
r.Log.Error(err, "failed to set finalizer")
}
}
}()

Expand Down
23 changes: 11 additions & 12 deletions controllers/notificationpolicy_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,13 @@ func (r *GrafanaNotificationPolicyReconciler) Reconcile(ctx context.Context, req
}

if notificationPolicy.GetDeletionTimestamp() != nil {
// Check if resource needs clean up
if controllerutil.ContainsFinalizer(notificationPolicy, grafanaFinalizer) {
err := r.finalize(ctx, notificationPolicy)
if err != nil {
return ctrl.Result{RequeueAfter: RequeueDelay}, fmt.Errorf("failed to finalize GrafanaNotificationPolicy: %w", err)
if err := r.finalize(ctx, notificationPolicy); err != nil {
return ctrl.Result{}, fmt.Errorf("failed to finalize GrafanaNotificationPolicy: %w", err)
}
controllerutil.RemoveFinalizer(notificationPolicy, grafanaFinalizer)
if err := r.Update(ctx, notificationPolicy); err != nil {
r.Log.Error(err, "failed to remove finalizer")
return ctrl.Result{RequeueAfter: RequeueDelay}, fmt.Errorf("failed to update GrafanaNotificationPolicy: %w", err)
if err := removeFinalizer(ctx, r.Client, notificationPolicy); err != nil {
return ctrl.Result{}, fmt.Errorf("failed to remove finalizer: %w", err)
}
}
return ctrl.Result{}, nil
Expand All @@ -99,12 +97,13 @@ func (r *GrafanaNotificationPolicyReconciler) Reconcile(ctx context.Context, req
r.Log.Error(err, "updating status")
}
if meta.IsStatusConditionTrue(notificationPolicy.Status.Conditions, conditionNoMatchingInstance) {
controllerutil.RemoveFinalizer(notificationPolicy, grafanaFinalizer)
if err := removeFinalizer(ctx, r.Client, notificationPolicy); err != nil {
r.Log.Error(err, "failed to remove finalizer")
}
} else {
controllerutil.AddFinalizer(notificationPolicy, grafanaFinalizer)
}
if err := r.Update(ctx, notificationPolicy); err != nil {
r.Log.Error(err, "failed to set finalizer")
if err := addFinalizer(ctx, r.Client, notificationPolicy); err != nil {
r.Log.Error(err, "failed to set finalizer")
}
}
}()

Expand Down
Loading