The kubebuilder documentation on finalizers has the following example code for removing a finalizer from an object.
// remove our finalizer from the list and update it.
controllerutil.RemoveFinalizer(cronJob, myFinalizerName)
if err := r.Update(ctx, cronJob); err != nil {
return ctrl.Result{}, err
}
I found when doing this, if the operation running above this in the Reconcile()
function (typically to remove a remote resource from an API) this r.Update()
call would return an error like this:
the object has been modified; please apply your changes to the latest version and try again
This can leave your object stuck in a Terminating
state which can cause issues like Namespaces and other objects not be cleaned up correctly.
There are a few ways you could go about mitigating this issue, but using Patch()
appears to be the fastest and most consistent approach.
// remove our finalizer from the list and update it.
f := ns.GetFinalizers()
for i, e := range f {
if e == utils.BayFinalizerAwsAccount {
p := []byte(fmt.Sprintf(`[{"op": "remove", "path": "/metadata/finalizers/%d"}]`, i))
patch := client.RawPatch(types.JSONPatchType, p)
r.Log.Info("removing finalizer from namespace")
if err := r.Patch(ctx, ns, patch); err != nil {
return ctrl.Result{}, err
}
}
}