-
Notifications
You must be signed in to change notification settings - Fork 303
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add funcs to add/delete finalizer on ClusterSlice
- Added general functions to patch ClusterSlice ObjectMetadata - Added functions to add/delete neg cleanup finalizer on ClusterSlice. This will allow to properly clean neg controllers when cluster slice is deleted
- Loading branch information
Showing
4 changed files
with
336 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package finalizer | ||
|
||
import ( | ||
"fmt" | ||
|
||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
clusterslice "k8s.io/ingress-gce/pkg/apis/clusterslice/v1" | ||
clustersliceclient "k8s.io/ingress-gce/pkg/clusterslice/client/clientset/versioned/typed/clusterslice/v1" | ||
"k8s.io/ingress-gce/pkg/utils/patch" | ||
"k8s.io/ingress-gce/pkg/utils/slice" | ||
"k8s.io/klog/v2" | ||
) | ||
|
||
const ( | ||
ClusterSliceNEGCleanupFinalizer = "multiproject.networking.gke.io/neg-cleanup" | ||
) | ||
|
||
func EnsureClusterSliceNEGCleanupFinalizer(cs *clusterslice.ClusterSlice, csClient clustersliceclient.ClusterSliceInterface, logger klog.Logger) error { | ||
return ensureClusterSliceFinalizer(cs, ClusterSliceNEGCleanupFinalizer, csClient, logger) | ||
} | ||
|
||
func DeleteClusterSliceNEGCleanupFinalizer(cs *clusterslice.ClusterSlice, csClient clustersliceclient.ClusterSliceInterface, logger klog.Logger) error { | ||
return deleteClusterSliceFinalizer(cs, ClusterSliceNEGCleanupFinalizer, csClient, logger) | ||
} | ||
|
||
func ensureClusterSliceFinalizer(cs *clusterslice.ClusterSlice, key string, csClient clustersliceclient.ClusterSliceInterface, logger klog.Logger) error { | ||
if HasGivenFinalizer(cs.ObjectMeta, key) { | ||
return nil | ||
} | ||
|
||
// Make a deep copy of the ClusterSlice to avoid mutating the shared informer cache. | ||
updatedObjectMeta := cs.ObjectMeta.DeepCopy() | ||
updatedObjectMeta.Finalizers = append(updatedObjectMeta.Finalizers, key) | ||
|
||
logger.V(2).Info("Adding finalizer to ClusterSlice", "finalizerKey", key, "clusterSlice", fmt.Sprintf("%s/%s", cs.Namespace, cs.Name)) | ||
return patch.PatchClusterSliceObjectMetadata(csClient, cs, *updatedObjectMeta) | ||
} | ||
|
||
func deleteClusterSliceFinalizer(cs *clusterslice.ClusterSlice, key string, csClient clustersliceclient.ClusterSliceInterface, logger klog.Logger) error { | ||
if !HasGivenFinalizer(cs.ObjectMeta, key) { | ||
return nil | ||
} | ||
|
||
updatedObjectMeta := cs.ObjectMeta.DeepCopy() | ||
updatedObjectMeta.Finalizers = slice.RemoveString(updatedObjectMeta.Finalizers, key, nil) | ||
logger.V(2).Info("Deleting finalizer from ClusterSlice", "finalizerKey", key, "clusterSlice", fmt.Sprintf("%s/%s", cs.Namespace, cs.Name)) | ||
return patch.PatchClusterSliceObjectMetadata(csClient, cs, *updatedObjectMeta) | ||
} | ||
|
||
// HasGivenFinalizer is true if the passed in meta has the specified finalizer. | ||
func HasGivenFinalizer(m metav1.ObjectMeta, key string) bool { | ||
return slice.ContainsString(m.Finalizers, key, nil) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
package finalizer | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
clusterslicev1 "k8s.io/ingress-gce/pkg/apis/clusterslice/v1" | ||
clusterslicefake "k8s.io/ingress-gce/pkg/clusterslice/client/clientset/versioned/fake" | ||
"k8s.io/ingress-gce/pkg/utils/slice" | ||
"k8s.io/klog/v2/ktesting" | ||
) | ||
|
||
func TestEnsureClusterSliceNEGCleanupFinalizer(t *testing.T) { | ||
testCases := []struct { | ||
desc string | ||
cs *clusterslicev1.ClusterSlice | ||
expectedFinalizerPresent bool | ||
}{ | ||
{ | ||
desc: "Finalizer not present, should add it", | ||
cs: &clusterslicev1.ClusterSlice{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: "test-cs-add-finalizer", | ||
Namespace: "default", | ||
Finalizers: []string{}, | ||
}, | ||
}, | ||
expectedFinalizerPresent: true, | ||
}, | ||
{ | ||
desc: "Finalizer already present, should remain", | ||
cs: &clusterslicev1.ClusterSlice{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: "test-cs-finalizer-present", | ||
Namespace: "default", | ||
Finalizers: []string{ | ||
ClusterSliceNEGCleanupFinalizer, | ||
}, | ||
}, | ||
}, | ||
expectedFinalizerPresent: true, | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.desc, func(t *testing.T) { | ||
csClient := clusterslicefake.NewSimpleClientset(tc.cs) | ||
csInterface := csClient.FlagsV1().ClusterSlices(tc.cs.Namespace) | ||
|
||
// Create the initial ClusterSlice object | ||
_, err := csInterface.Create(context.TODO(), tc.cs, metav1.CreateOptions{}) | ||
if err != nil { | ||
t.Fatalf("Failed to create ClusterSlice: %v", err) | ||
} | ||
|
||
logger, _ := ktesting.NewTestContext(t) | ||
|
||
err = EnsureClusterSliceNEGCleanupFinalizer(tc.cs, csInterface, logger) | ||
if err != nil { | ||
t.Fatalf("EnsureClusterSliceNEGCleanupFinalizer returned error: %v", err) | ||
} | ||
|
||
// Retrieve the updated ClusterSlice | ||
updatedCS, err := csInterface.Get(context.TODO(), tc.cs.Name, metav1.GetOptions{}) | ||
if err != nil { | ||
t.Fatalf("Failed to get updated ClusterSlice: %v", err) | ||
} | ||
|
||
// Check if the finalizer is present as expected | ||
hasFinalizer := slice.ContainsString(updatedCS.Finalizers, ClusterSliceNEGCleanupFinalizer, nil) | ||
if hasFinalizer != tc.expectedFinalizerPresent { | ||
t.Errorf("Finalizer presence mismatch: expected %v, got %v", tc.expectedFinalizerPresent, hasFinalizer) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestEnsureDeleteClusterSliceNEGCleanupFinalizer(t *testing.T) { | ||
testCases := []struct { | ||
desc string | ||
cs *clusterslicev1.ClusterSlice | ||
expectedFinalizerPresent bool | ||
}{ | ||
{ | ||
desc: "Finalizer present, should be removed", | ||
cs: &clusterslicev1.ClusterSlice{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: "test-cs-remove-finalizer", | ||
Namespace: "default", | ||
Finalizers: []string{ | ||
ClusterSliceNEGCleanupFinalizer, | ||
}, | ||
}, | ||
}, | ||
expectedFinalizerPresent: false, | ||
}, | ||
{ | ||
desc: "Finalizer not present, remains absent", | ||
cs: &clusterslicev1.ClusterSlice{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: "test-cs-finalizer-not-present", | ||
Namespace: "default", | ||
Finalizers: []string{}, | ||
}, | ||
}, | ||
expectedFinalizerPresent: false, | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.desc, func(t *testing.T) { | ||
csClient := clusterslicefake.NewSimpleClientset(tc.cs) | ||
csInterface := csClient.FlagsV1().ClusterSlices(tc.cs.Namespace) | ||
|
||
// Create the initial ClusterSlice object | ||
_, err := csInterface.Create(context.TODO(), tc.cs, metav1.CreateOptions{}) | ||
if err != nil { | ||
t.Fatalf("Failed to create ClusterSlice: %v", err) | ||
} | ||
|
||
logger, _ := ktesting.NewTestContext(t) | ||
|
||
err = DeleteClusterSliceNEGCleanupFinalizer(tc.cs, csInterface, logger) | ||
if err != nil { | ||
t.Fatalf("DeleteClusterSliceNEGCleanupFinalizer returned error: %v", err) | ||
} | ||
|
||
// Retrieve the updated ClusterSlice | ||
updatedCS, err := csInterface.Get(context.TODO(), tc.cs.Name, metav1.GetOptions{}) | ||
if err != nil { | ||
t.Fatalf("Failed to get updated ClusterSlice: %v", err) | ||
} | ||
|
||
// Check if the finalizer is present as expected | ||
hasFinalizer := slice.ContainsString(updatedCS.Finalizers, ClusterSliceNEGCleanupFinalizer, nil) | ||
if hasFinalizer != tc.expectedFinalizerPresent { | ||
t.Errorf("Finalizer presence mismatch: expected %v, got %v", tc.expectedFinalizerPresent, hasFinalizer) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters