Skip to content

Commit d9a2ba0

Browse files
authored
Added KAM resource cleanup logic along with tests (#1106)
Signed-off-by: Tejas Soham <tejassoham05@gmail.com>
1 parent c4bdd09 commit d9a2ba0

2 files changed

Lines changed: 167 additions & 0 deletions

File tree

controllers/gitopsservice_controller.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ var (
7373

7474
const (
7575
gitopsServicePrefix = "gitops-service-"
76+
kamResourceName = "kam"
7677
)
7778

7879
// SetupWithManager sets up the controller with the Manager.
@@ -259,6 +260,8 @@ func (r *ReconcileGitopsService) Reconcile(ctx context.Context, request reconcil
259260
Namespace: namespace,
260261
}
261262

263+
r.cleanKAMResources(ctx, reqLogger)
264+
262265
if !r.DisableDefaultInstall {
263266
// Create/reconcile the default Argo CD instance, unless default install is disabled
264267
if result, err := r.reconcileDefaultArgoCDInstance(instance, reqLogger); err != nil {
@@ -312,6 +315,44 @@ func (r *ReconcileGitopsService) Reconcile(ctx context.Context, request reconcil
312315
}
313316
}
314317

318+
// Detect the unsupported KAM components across Deployments , Routes , Services and deletes them to perform cleanup as KAM is no longer supported since 1.15
319+
func (r *ReconcileGitopsService) cleanKAMResources(ctx context.Context, reqLogger logr.Logger) {
320+
321+
// KAM Deployment
322+
cleanupKAMDeployment := &appsv1.Deployment{}
323+
if err := r.Client.Get(ctx, types.NamespacedName{Name: kamResourceName, Namespace: serviceNamespace}, cleanupKAMDeployment); err == nil {
324+
reqLogger.Info("Detected unsupported KAM Deployment, deleting", "Name", kamResourceName, "Namespace", serviceNamespace)
325+
if err := r.Client.Delete(ctx, cleanupKAMDeployment); err != nil && !errors.IsNotFound(err) {
326+
reqLogger.Error(err, "Failed to delete KAM Deployment", "Name", kamResourceName, "Namespace", serviceNamespace)
327+
}
328+
} else if !errors.IsNotFound(err) {
329+
reqLogger.Error(err, "Failed to retrieve KAM Deployment", "Name", kamResourceName, "Namespace", serviceNamespace)
330+
}
331+
332+
// KAM Service
333+
cleanupKAMService := &corev1.Service{}
334+
if err := r.Client.Get(ctx, types.NamespacedName{Name: kamResourceName, Namespace: serviceNamespace}, cleanupKAMService); err == nil {
335+
reqLogger.Info("Detected unsupported KAM Service, deleting", "Name", kamResourceName, "Namespace", serviceNamespace)
336+
if err := r.Client.Delete(ctx, cleanupKAMService); err != nil && !errors.IsNotFound(err) {
337+
reqLogger.Error(err, "Failed to delete KAM Service", "Name", kamResourceName, "Namespace", serviceNamespace)
338+
}
339+
} else if !errors.IsNotFound(err) {
340+
reqLogger.Error(err, "Failed to retrieve KAM Service", "Name", kamResourceName, "Namespace", serviceNamespace)
341+
}
342+
343+
// KAM Route
344+
cleanupKAMRoute := &routev1.Route{}
345+
if err := r.Client.Get(ctx, types.NamespacedName{Name: kamResourceName, Namespace: serviceNamespace}, cleanupKAMRoute); err == nil {
346+
reqLogger.Info("Detected unsupported KAM Route, deleting", "Name", kamResourceName, "Namespace", serviceNamespace)
347+
if err := r.Client.Delete(ctx, cleanupKAMRoute); err != nil && !errors.IsNotFound(err) {
348+
reqLogger.Error(err, "Failed to delete KAM Route", "Name", kamResourceName, "Namespace", serviceNamespace)
349+
}
350+
} else if !errors.IsNotFound(err) {
351+
reqLogger.Error(err, "Failed to retrieve KAM Route", "Name", kamResourceName, "Namespace", serviceNamespace)
352+
}
353+
354+
}
355+
315356
func (r *ReconcileGitopsService) ensureDefaultArgoCDInstanceDoesntExist() error {
316357

317358
defaultArgoCDInstance, err := argocd.NewCR(common.ArgoCDInstanceName, serviceNamespace, r.Client)

controllers/gitopsservice_controller_test.go

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,132 @@ func TestReconcileBackend_DefaultRequestsAndLimits(t *testing.T) {
889889
assert.Equal(t, deployment.Spec.Template.Spec.Containers[0].Resources.Limits["cpu"], resourcev1.MustParse("500m"))
890890
}
891891

892+
// Tests for KAM component cleanup
893+
// No resources exist
894+
func TestCleanKAMResources_NoResourcesExist(t *testing.T) {
895+
logf.SetLogger(zap.New(zap.UseDevMode(true)))
896+
s := scheme.Scheme
897+
addKnownTypesToScheme(s)
898+
fakeClient := fake.NewClientBuilder().WithScheme(s).Build()
899+
reconciler := newReconcileGitOpsService(fakeClient, s)
900+
reqLogger := logs.WithValues("Request.Namespace", "test", "Request.Name", "test")
901+
902+
// No KAM resources exist - function should be a silent no-op
903+
reconciler.cleanKAMResources(context.TODO(), reqLogger)
904+
}
905+
906+
// Deployment exist
907+
func TestCleanKAMResources_DeploymentExist(t *testing.T) {
908+
logf.SetLogger(zap.New(zap.UseDevMode(true)))
909+
s := scheme.Scheme
910+
addKnownTypesToScheme(s)
911+
912+
kamDeploy := &appsv1.Deployment{
913+
ObjectMeta: v1.ObjectMeta{Name: kamResourceName, Namespace: serviceNamespace},
914+
}
915+
fakeClient := fake.NewClientBuilder().WithScheme(s).WithObjects(kamDeploy).Build()
916+
reconciler := newReconcileGitOpsService(fakeClient, s)
917+
reqLogger := logs.WithValues("Request.Namespace", "test", "Request.Name", "test")
918+
919+
reconciler.cleanKAMResources(context.TODO(), reqLogger)
920+
921+
err := fakeClient.Get(context.TODO(), types.NamespacedName{Name: kamResourceName, Namespace: serviceNamespace}, &appsv1.Deployment{})
922+
if !errors.IsNotFound(err) {
923+
t.Fatalf("expected KAM Deployment to be deleted , got err: %v", err)
924+
}
925+
}
926+
927+
// Service exist
928+
func TestCleanKAMResources_ServiceExist(t *testing.T) {
929+
logf.SetLogger(zap.New(zap.UseDevMode(true)))
930+
s := scheme.Scheme
931+
addKnownTypesToScheme(s)
932+
kamService := &corev1.Service{
933+
ObjectMeta: v1.ObjectMeta{Name: kamResourceName, Namespace: serviceNamespace},
934+
}
935+
fakeClient := fake.NewClientBuilder().WithScheme(s).WithObjects(kamService).Build()
936+
reconciler := newReconcileGitOpsService(fakeClient, s)
937+
reqLogger := logs.WithValues("Request.Namespace", "test", "Request.Name", "test")
938+
939+
reconciler.cleanKAMResources(context.TODO(), reqLogger)
940+
941+
err := fakeClient.Get(context.TODO(), types.NamespacedName{Name: kamResourceName, Namespace: serviceNamespace}, &corev1.Service{})
942+
if !errors.IsNotFound(err) {
943+
t.Fatalf("expected KAM Service to be deleted , got err: %v", err)
944+
}
945+
}
946+
947+
// Route exist
948+
func TestCleanKAMResources_RouteExist(t *testing.T) {
949+
logf.SetLogger(zap.New(zap.UseDevMode(true)))
950+
s := scheme.Scheme
951+
addKnownTypesToScheme(s)
952+
kamRoute := &routev1.Route{
953+
ObjectMeta: v1.ObjectMeta{Name: kamResourceName, Namespace: serviceNamespace},
954+
}
955+
fakeClient := fake.NewClientBuilder().WithScheme(s).WithObjects(kamRoute).Build()
956+
reconciler := newReconcileGitOpsService(fakeClient, s)
957+
reqLogger := logs.WithValues("Request.Namespace", "test", "Request.Name", "test")
958+
959+
reconciler.cleanKAMResources(context.TODO(), reqLogger)
960+
961+
err := fakeClient.Get(context.TODO(), types.NamespacedName{Name: kamResourceName, Namespace: serviceNamespace}, &routev1.Route{})
962+
if !errors.IsNotFound(err) {
963+
t.Fatalf("expected KAM Route to be deleted , got err: %v", err)
964+
}
965+
}
966+
967+
// All Resources exist
968+
func TestCleanKAMResources_AllResourcesExist(t *testing.T) {
969+
logf.SetLogger(zap.New(zap.UseDevMode(true)))
970+
s := scheme.Scheme
971+
addKnownTypesToScheme(s)
972+
kamDeploy := &appsv1.Deployment{
973+
ObjectMeta: v1.ObjectMeta{Name: kamResourceName, Namespace: serviceNamespace},
974+
}
975+
kamService := &corev1.Service{
976+
ObjectMeta: v1.ObjectMeta{Name: kamResourceName, Namespace: serviceNamespace},
977+
}
978+
kamRoute := &routev1.Route{
979+
ObjectMeta: v1.ObjectMeta{Name: kamResourceName, Namespace: serviceNamespace},
980+
}
981+
fakeClient := fake.NewClientBuilder().WithScheme(s).WithObjects(kamDeploy, kamService, kamRoute).Build()
982+
reconciler := newReconcileGitOpsService(fakeClient, s)
983+
reqLogger := logs.WithValues("Request.Namespace", "test", "Request.Name", "test")
984+
985+
reconciler.cleanKAMResources(context.TODO(), reqLogger)
986+
987+
if err := fakeClient.Get(context.TODO(), types.NamespacedName{Name: kamResourceName, Namespace: serviceNamespace}, &appsv1.Deployment{}); !errors.IsNotFound(err) {
988+
t.Fatalf("expected KAM Deployment to be deleted , got err: %v", err)
989+
}
990+
if err := fakeClient.Get(context.TODO(), types.NamespacedName{Name: kamResourceName, Namespace: serviceNamespace}, &corev1.Service{}); !errors.IsNotFound(err) {
991+
t.Fatalf("expected KAM Service to be deleted , got err: %v", err)
992+
}
993+
if err := fakeClient.Get(context.TODO(), types.NamespacedName{Name: kamResourceName, Namespace: serviceNamespace}, &routev1.Route{}); !errors.IsNotFound(err) {
994+
t.Fatalf("expected KAM Route to be deleted , got err: %v", err)
995+
}
996+
}
997+
998+
// Idempotency
999+
func TestCleanKAMResources_Idempotent(t *testing.T) {
1000+
logf.SetLogger(zap.New(zap.UseDevMode(true)))
1001+
s := scheme.Scheme
1002+
addKnownTypesToScheme(s)
1003+
kamDeploy := &appsv1.Deployment{
1004+
ObjectMeta: v1.ObjectMeta{Name: kamResourceName, Namespace: serviceNamespace},
1005+
}
1006+
fakeClient := fake.NewClientBuilder().WithScheme(s).WithObjects(kamDeploy).Build()
1007+
reconciler := newReconcileGitOpsService(fakeClient, s)
1008+
reqLogger := logs.WithValues("Request.Namespace", "test", "Request.Name", "test")
1009+
1010+
// First call - deletes the KAM resource
1011+
reconciler.cleanKAMResources(context.TODO(), reqLogger)
1012+
1013+
// Second call - must not panic even if the resources are already deleted
1014+
reconciler.cleanKAMResources(context.TODO(), reqLogger)
1015+
1016+
}
1017+
8921018
func addKnownTypesToScheme(scheme *runtime.Scheme) {
8931019
scheme.AddKnownTypes(configv1.GroupVersion, &configv1.ClusterVersion{})
8941020
scheme.AddKnownTypes(pipelinesv1alpha1.GroupVersion, &pipelinesv1alpha1.GitopsService{})

0 commit comments

Comments
 (0)