Skip to content

Commit 88409f8

Browse files
feat: only delete cluster if all other finalizers on cluster resource are gone (#85)
* only delete cluster if all other finalizers on cluster resource are gone * move foreign finalizer detection in helper method * add unit tests for helper function * refactor: identifyFinalizers to table driven test * chore: clean-up go.mod * fix: remove comments --------- Co-authored-by: Maximilian Techritz <maximilian.techritz@sap.com>
1 parent 9222ff3 commit 88409f8

File tree

2 files changed

+86
-1
lines changed

2 files changed

+86
-1
lines changed

internal/controller/cluster_controller.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,20 @@ func (r *ClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
9292
}
9393

9494
func (r *ClusterReconciler) handleDelete(ctx context.Context, cluster *clustersv1alpha1.Cluster) (ctrl.Result, error) {
95+
log := logf.FromContext(ctx)
9596
requeue := smartrequeue.FromContext(ctx)
9697
cluster.Status.Phase = commonapi.StatusPhaseTerminating
9798

98-
if !controllerutil.ContainsFinalizer(cluster, Finalizer) {
99+
// check if there are any foreign finalizers on the Cluster resource
100+
foreignFinalizers, found := identifyFinalizers(cluster)
101+
if !found {
99102
// Nothing to do
100103
return ctrl.Result{}, nil
101104
}
105+
if len(foreignFinalizers) > 0 {
106+
log.Info("Postponing cluster deletion until foreign finalizers are removed", "foreignFinalizers", foreignFinalizers)
107+
return requeue.Progressing()
108+
}
102109

103110
name := kindName(cluster)
104111

@@ -245,3 +252,19 @@ func isClusterProviderResponsible(cluster *clustersv1alpha1.Cluster) bool {
245252
func runsOnLocalHost() bool {
246253
return os.Getenv("KIND_ON_LOCAL_HOST") == "true"
247254
}
255+
256+
// identifyFinalizers checks two things for the given object:
257+
// 1. If the 'clusters.openmcp.cloud/finalizer' finalizer is present (second return value).
258+
// 2. Which other finalizers are present (first return value).
259+
func identifyFinalizers(obj client.Object) ([]string, bool) {
260+
foreignFinalizers := make([]string, 0, len(obj.GetFinalizers()))
261+
found := false
262+
for _, fin := range obj.GetFinalizers() {
263+
if fin != Finalizer {
264+
foreignFinalizers = append(foreignFinalizers, fin)
265+
} else {
266+
found = true
267+
}
268+
}
269+
return foreignFinalizers, found
270+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package controller
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
7+
corev1 "k8s.io/api/core/v1"
8+
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
9+
)
10+
11+
func TestIdentifyFinalizers(t *testing.T) {
12+
tests := []struct {
13+
name string
14+
inputFinalizers []string
15+
expectedForeignFinalizers []string
16+
expectedOwnFinalizer bool
17+
}{
18+
{
19+
name: "no finalizers on the object at all",
20+
inputFinalizers: []string{},
21+
expectedForeignFinalizers: []string{},
22+
expectedOwnFinalizer: false,
23+
},
24+
{
25+
name: "only the own finalizer on the object",
26+
inputFinalizers: []string{Finalizer},
27+
expectedForeignFinalizers: []string{},
28+
expectedOwnFinalizer: true,
29+
},
30+
{
31+
name: "only other finalizers on the object",
32+
inputFinalizers: []string{"other/finalizer1", "other/finalizer2"},
33+
expectedForeignFinalizers: []string{"other/finalizer1", "other/finalizer2"},
34+
expectedOwnFinalizer: false,
35+
},
36+
{
37+
name: "both own and other finalizers on the object",
38+
inputFinalizers: []string{"other/finalizer1", Finalizer, "other/finalizer2"},
39+
expectedForeignFinalizers: []string{"other/finalizer1", "other/finalizer2"},
40+
expectedOwnFinalizer: true,
41+
},
42+
}
43+
44+
for _, tt := range tests {
45+
t.Run(tt.name, func(t *testing.T) {
46+
obj := &corev1.Namespace{}
47+
48+
for _, finalizer := range tt.inputFinalizers {
49+
controllerutil.AddFinalizer(obj, finalizer)
50+
}
51+
52+
foreignFinalizers, ownFinalizer := identifyFinalizers(obj)
53+
54+
if !reflect.DeepEqual(foreignFinalizers, tt.expectedForeignFinalizers) {
55+
t.Errorf("identifyFinalizers() foreignFinalizers = %v, want %v", foreignFinalizers, tt.expectedForeignFinalizers)
56+
}
57+
if ownFinalizer != tt.expectedOwnFinalizer {
58+
t.Errorf("identifyFinalizers() ownFinalizer = %v, want %v", ownFinalizer, tt.expectedOwnFinalizer)
59+
}
60+
})
61+
}
62+
}

0 commit comments

Comments
 (0)