@@ -18,27 +18,26 @@ package finalizer
1818
1919import (
2020 "context"
21+ "encoding/json"
2122 "fmt"
2223 "slices"
2324 "sort"
2425 "strings"
2526
26- "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured "
27+ "k8s.io/apimachinery/pkg/types "
2728 "sigs.k8s.io/controller-runtime/pkg/client"
28- "sigs.k8s.io/controller-runtime/pkg/client/apiutil"
2929)
3030
3131const (
3232 FinalizerPrefix = "olm.operatorframework.io/"
3333)
3434
35- // EnsureFinalizers sets the finalizers on an object to exactly the provided list using server-side apply.
36- // If no finalizers are supplied, all finalizers will be removed from the object.
37- // If one finalizer is supplied, all other finalizers will be removed and only the supplied one will remain.
35+ // EnsureFinalizers sets the FinalizerPrefix finalizers an object using Patch (vs. Update)
36+ // If no finalizers are supplied, all FinalizerPrefix finalizers will be removed from the object.
37+ // If any finalizers are supplied, all other FinalizerPrefix finalizers will be removed and only the supplied ones will remain.
3838// Returns (true, nil) if the finalizers were changed, (false, nil) if they were already set to the desired value.
3939// Note: This function will update the passed object with the server response.
4040func EnsureFinalizers (ctx context.Context , owner string , c client.Client , obj client.Object , finalizers ... string ) (bool , error ) {
41- // Sort the desired finalizers for consistent ordering
4241 newFinalizers := slices .Clone (finalizers )
4342 if newFinalizers == nil {
4443 newFinalizers = []string {}
@@ -49,47 +48,45 @@ func EnsureFinalizers(ctx context.Context, owner string, c client.Client, obj cl
4948 panic (fmt .Sprintf ("finalizer does not have %q prefix: %q" , FinalizerPrefix , s ))
5049 }
5150 }
52- sort .Strings (newFinalizers )
5351
54- // Check if the current finalizers already match the desired state
55- // Remove any non-"olm.operatorframework.io" finalizers (ones we don't manage) from the list
52+ // Add any other, non-FinalizerPrefix, finalizers to the newFinalizer list
5653 currentFinalizers := obj .GetFinalizers ()
54+ for _ , f := range currentFinalizers {
55+ if ! strings .HasPrefix (f , FinalizerPrefix ) {
56+ newFinalizers = append (newFinalizers , f )
57+ }
58+ }
59+ // Sort the desired finalizers for consistent ordering
60+ sort .Strings (newFinalizers )
61+
62+ // Check if the current finalizers already match the desired state (newFinalizers)
5763 currentSorted := slices .Clone (currentFinalizers )
58- currentSorted = slices .DeleteFunc (currentSorted , func (f string ) bool {
59- return ! strings .HasPrefix (f , FinalizerPrefix )
60- })
6164 if currentSorted == nil {
6265 currentSorted = []string {}
6366 }
6467 sort .Strings (currentSorted )
6568
66- // With only "olm.operatorframework.io" finalizers, other controller's finalizers
67- // won't interfere in this check
69+ // Compare the current list with the desired newFinalizers
6870 if slices .Equal (currentSorted , newFinalizers ) {
6971 return false , nil
7072 }
7173
72- // Get the GVK for this object type
73- gvk , err := apiutil .GVKForObject (obj , c .Scheme ())
74- if err != nil {
75- return false , fmt .Errorf ("getting object kind: %w" , err )
74+ patch := map [string ]any {
75+ "metadata" : map [string ]any {
76+ "resourceVersion" : obj .GetResourceVersion (),
77+ "finalizers" : newFinalizers ,
78+ },
7679 }
7780
78- // Create an unstructured object for server-side apply
79- u := & unstructured.Unstructured {}
80- u .SetGroupVersionKind (gvk )
81- u .SetName (obj .GetName ())
82- u .SetNamespace (obj .GetNamespace ())
83- u .SetFinalizers (newFinalizers )
81+ patchJSON , err := json .Marshal (patch )
82+ if err != nil {
83+ return false , fmt .Errorf ("marshalling patch to ensure finalizers: %w" , err )
84+ }
8485
85- // Use server-side apply to update finalizers
86- if err := c .Patch (ctx , u , client .Apply , client . ForceOwnership , client . FieldOwner ( owner )); err != nil {
86+ // Use patch to update finalizers
87+ if err := c .Patch (ctx , obj , client .RawPatch ( types . MergePatchType , patchJSON )); err != nil {
8788 return false , fmt .Errorf ("updating finalizers: %w" , err )
8889 }
8990
90- // Update the passed object with the new finalizers
91- obj .SetFinalizers (u .GetFinalizers ())
92- obj .SetResourceVersion (u .GetResourceVersion ())
93-
9491 return true , nil
9592}
0 commit comments