Skip to content

Commit 9f61089

Browse files
Address review comments
Signed-off-by: Rashmi Gottipati <[email protected]>
1 parent c6fecbb commit 9f61089

File tree

3 files changed

+69
-20
lines changed

3 files changed

+69
-20
lines changed

pkg/finalizer/finalizer.go

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,16 @@ import (
1717
"context"
1818
"fmt"
1919

20+
utilerrors "k8s.io/apimachinery/pkg/util/errors"
2021
"sigs.k8s.io/controller-runtime/pkg/client"
2122
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
2223
)
2324

25+
type finalizers map[string]Finalizer
26+
2427
// NewFinalizers returns the Finalizers interface
2528
func NewFinalizers() Finalizers {
26-
return finalizers(map[string]Finalizer{})
29+
return finalizers{}
2730
}
2831

2932
func (f finalizers) Register(key string, finalizer Finalizer) error {
@@ -35,19 +38,26 @@ func (f finalizers) Register(key string, finalizer Finalizer) error {
3538
}
3639

3740
func (f finalizers) Finalize(ctx context.Context, obj client.Object) (bool, error) {
41+
var errList []error
3842
needsUpdate := false
3943
for key, finalizer := range f {
40-
if obj.GetDeletionTimestamp().IsZero() && !controllerutil.ContainsFinalizer(obj, key) {
44+
if dt := obj.GetDeletionTimestamp(); dt.IsZero() && !controllerutil.ContainsFinalizer(obj, key) {
4145
controllerutil.AddFinalizer(obj, key)
4246
needsUpdate = true
43-
} else if obj.GetDeletionTimestamp() != nil && controllerutil.ContainsFinalizer(obj, key) {
44-
ret, err := finalizer.Finalize(ctx, obj)
47+
} else if !dt.IsZero() && controllerutil.ContainsFinalizer(obj, key) {
48+
finalizerNeedsUpdate, err := finalizer.Finalize(ctx, obj)
4549
if err != nil {
46-
return ret, fmt.Errorf("finalize failed for key %q: %v", key, err)
50+
// Even when the finalizer fails, it may need to signal to update the primary
51+
// object (e.g. it may set a condition and need a status update).
52+
needsUpdate = needsUpdate || finalizerNeedsUpdate
53+
errList = append(errList, fmt.Errorf("finalizer %q failed: %v", key, err))
54+
} else {
55+
// If the finalizer succeeds, we remove the finalizer from the primary
56+
// object's metadata, so we know it will need an update.
57+
needsUpdate = true
58+
controllerutil.RemoveFinalizer(obj, key)
4759
}
48-
controllerutil.RemoveFinalizer(obj, key)
49-
needsUpdate = true
5060
}
5161
}
52-
return needsUpdate, nil
62+
return needsUpdate, utilerrors.NewAggregate(errList)
5363
}

pkg/finalizer/finalizer_test.go

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,13 @@ var _ = Describe("TestFinalizer", func() {
4343
Expect(f).NotTo(BeNil())
4444

4545
})
46-
Describe("Finalizer helper library", func() {
47-
It("Register should successfully register a finalizer", func() {
46+
Describe("Register", func() {
47+
It("successfully registers a finalizer", func() {
4848
err = finalizers.Register("finalizers.sigs.k8s.io/testfinalizer", f)
4949
Expect(err).To(BeNil())
5050
})
5151

52-
It("Register should return an error when it is called twice with the same key", func() {
52+
It("should fail when trying to register a finalizer that was already registered", func() {
5353
err = finalizers.Register("finalizers.sigs.k8s.io/testfinalizer", f)
5454
Expect(err).To(BeNil())
5555

@@ -59,31 +59,72 @@ var _ = Describe("TestFinalizer", func() {
5959
Expect(err.Error()).To(ContainSubstring("already registered"))
6060

6161
})
62-
63-
It("Finalize should return no error and indicate false for needsUpdate if a finalizer is not registered", func() {
62+
})
63+
Describe("Finalize", func() {
64+
It("should return no error and return false for needsUpdate if a finalizer is not registered", func() {
6465
ret, err := finalizers.Finalize(context.TODO(), pod)
6566
Expect(err).To(BeNil())
6667
Expect(ret).To(BeFalse())
6768
})
6869

69-
It("Finalize should return no error when deletion timestamp is not nil and the finalizer exists", func() {
70+
It("successfully finalizes and returns true for needsUpdate when deletion timestamp is nil and finalizer does not exist", func() {
71+
err = finalizers.Register("finalizers.sigs.k8s.io/testfinalizer", f)
72+
Expect(err).To(BeNil())
73+
74+
pod.DeletionTimestamp = nil
75+
pod.Finalizers = []string{}
76+
77+
needsUpdate, err := finalizers.Finalize(context.TODO(), pod)
78+
Expect(err).To(BeNil())
79+
Expect(needsUpdate).To(BeTrue())
80+
})
81+
82+
It("successfully finalizes and returns true for needsUpdate when deletion timestamp is not nil and the finalizer exists", func() {
7083
now := metav1.Now()
7184
pod.DeletionTimestamp = &now
7285

7386
err = finalizers.Register("finalizers.sigs.k8s.io/testfinalizer", f)
7487
Expect(err).To(BeNil())
7588

76-
_, err := finalizers.Finalize(context.TODO(), pod)
89+
pod.Finalizers = []string{"finalizers.sigs.k8s.io/testfinalizer"}
90+
91+
needsUpdate, err := finalizers.Finalize(context.TODO(), pod)
7792
Expect(err).To(BeNil())
93+
Expect(needsUpdate).To(BeTrue())
7894
})
7995

80-
It("Finalize should return no error when deletion timestamp is nil and finalizer does not exist", func() {
81-
err = finalizers.Register("finalizers.sigs.k8s.io/testfinalizer", f)
96+
It("should return no error and return false for needsUpdate when deletion timestamp is nil and finalizer doesn't exist", func() {
97+
pod.DeletionTimestamp = nil
98+
pod.Finalizers = []string{}
99+
100+
needsUpdate, err := finalizers.Finalize(context.TODO(), pod)
82101
Expect(err).To(BeNil())
102+
Expect(needsUpdate).To(BeFalse())
103+
})
83104

84-
pod.DeletionTimestamp = nil
105+
It("should return no error and return false for needsUpdate when deletion timestamp is not nil and the finalizer doesn't exist", func() {
106+
now := metav1.Now()
107+
pod.DeletionTimestamp = &now
85108
pod.Finalizers = []string{}
86109

110+
needsUpdate, err := finalizers.Finalize(context.TODO(), pod)
111+
Expect(err).To(BeNil())
112+
Expect(needsUpdate).To(BeFalse())
113+
114+
})
115+
116+
It("successfully finalizes multiple finalizers and returns true for needsUpdate when deletion timestamp is not nil and the finalizer exists", func() {
117+
now := metav1.Now()
118+
pod.DeletionTimestamp = &now
119+
120+
err = finalizers.Register("finalizers.sigs.k8s.io/testfinalizer", f)
121+
Expect(err).To(BeNil())
122+
123+
err = finalizers.Register("finalizers.sigs.k8s.io/newtestfinalizer", f)
124+
Expect(err).To(BeNil())
125+
126+
pod.Finalizers = []string{"finalizers.sigs.k8s.io/testfinalizer", "finalizers.sigs.k8s.io/newtestfinalizer"}
127+
87128
needsUpdate, err := finalizers.Finalize(context.TODO(), pod)
88129
Expect(err).To(BeNil())
89130
Expect(needsUpdate).To(BeTrue())

pkg/finalizer/types.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ type Finalizer interface {
3333
Finalize(context.Context, client.Object) (needsUpdate bool, err error)
3434
}
3535

36-
type finalizers map[string]Finalizer
37-
3836
// Finalizers implements Registerer and Finalizer to finalize all registered
3937
// finalizers if the provided object has a deletion timestamp or set all
4038
// registered finalizers if it does not

0 commit comments

Comments
 (0)