Skip to content

Commit

Permalink
fix and test stale tenant identification
Browse files Browse the repository at this point in the history
  • Loading branch information
johannes94 committed Oct 24, 2024
1 parent c2dcfc2 commit c74023b
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 7 deletions.
20 changes: 13 additions & 7 deletions fleetshard/pkg/central/reconciler/tenant_cleanup.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import (
"github.com/stackrox/acs-fleet-manager/fleetshard/pkg/k8s"
"github.com/stackrox/acs-fleet-manager/internal/dinosaur/pkg/api/private"
"helm.sh/helm/v3/pkg/chart"
"k8s.io/kubernetes/pkg/apis/core"
corev1 "k8s.io/api/core/v1"

ctrlClient "sigs.k8s.io/controller-runtime/pkg/client"
)

Expand All @@ -30,9 +31,10 @@ func NewTenantCleanup(k8sClient ctrlClient.Client, secureTenantNetwork bool) *Te
// DeleteStaleTenantK8sResources deletes all namespaces on the cluster that are labeled
// as tenant namespaces but are not in the given list of ManagedCentrals
func (t *TenantCleanup) DeleteStaleTenantK8sResources(ctx context.Context, centralListFromFmAPI *private.ManagedCentralList) error {
namespaceList := core.NamespaceList{}
labels := map[string]string{k8s.ManagedByLabelKey: k8s.ManagedByFleetshardValue}
if err := t.k8sClient.List(ctx, &namespaceList, ctrlClient.MatchingLabels(labels)); err != nil {
namespaceList := corev1.NamespaceList{}
matchLabels := ctrlClient.MatchingLabels{k8s.ManagedByLabelKey: k8s.ManagedByFleetshardValue}
hasLabels := ctrlClient.HasLabels{TenantIDLabelKey, crNameLabelKey}
if err := t.k8sClient.List(ctx, &namespaceList, matchLabels, hasLabels); err != nil {
return fmt.Errorf("Failed to list all tenant namespaces: %w", err)
}

Expand All @@ -46,13 +48,17 @@ func (t *TenantCleanup) DeleteStaleTenantK8sResources(ctx context.Context, centr
}

for _, central := range centralListFromFmAPI.Items {
// the namespaceName is equal to the ID of a central
delete(namespaceNameToCrName, central.Id)
delete(namespaceNameToCrName, central.Metadata.Namespace)
}

for namespace, crName := range namespaceNameToCrName {
glog.Infof("delete resources for stale tenant in namespace: %s", namespace)
if crName == "" {
glog.Infof("namespace %q was not propperly labeled with a tenant name, skipping deletion", namespace)
continue
}
if _, err := t.DeleteK8sResources(ctx, namespace, crName); err != nil {
glog.Errorf("Failed to delete k8s resources for central: %s: %s", namespace, err.Error())
glog.Errorf("failed to delete k8s resources for central: %s: %s", namespace, err.Error())
}
}

Expand Down
138 changes: 138 additions & 0 deletions fleetshard/pkg/central/reconciler/tenant_cleanup_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package reconciler

import (
"context"
"testing"

"github.com/stackrox/acs-fleet-manager/fleetshard/pkg/testutils"
"github.com/stackrox/acs-fleet-manager/internal/dinosaur/pkg/api/private"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
ctrlClient "sigs.k8s.io/controller-runtime/pkg/client"
)

func TestDeleteStaleTenant(t *testing.T) {
keepNamespaces := []string{
"keep-because-in-fm-list-1",
"keep-because-in-fm-list-2",
"keep-because-empty-tenant-name",
"keep-because-not-managed-by-fleetshard",
"keep-because-missing-tenant-label",
}
deleteNamespaces := []string{
"delete-1",
"delete-2",
}

existingObjs := []ctrlClient.Object{
&corev1.Namespace{
ObjectMeta: v1.ObjectMeta{
Name: keepNamespaces[0],
Labels: map[string]string{
"app.kubernetes.io/managed-by": "rhacs-fleetshard",
"rhacs.redhat.com/tenant": keepNamespaces[0],
"app.kubernetes.io/instance": keepNamespaces[0],
}},
},
&corev1.Namespace{
ObjectMeta: v1.ObjectMeta{
Name: deleteNamespaces[0],
Labels: map[string]string{
"app.kubernetes.io/managed-by": "rhacs-fleetshard",
"rhacs.redhat.com/tenant": deleteNamespaces[0],
"app.kubernetes.io/instance": deleteNamespaces[0],
}},
},
&corev1.Namespace{
ObjectMeta: v1.ObjectMeta{
Name: keepNamespaces[1],
Labels: map[string]string{
"app.kubernetes.io/managed-by": "rhacs-fleetshard",
"rhacs.redhat.com/tenant": keepNamespaces[1],
"app.kubernetes.io/instance": keepNamespaces[1],
}},
},
&corev1.Namespace{
ObjectMeta: v1.ObjectMeta{
Name: keepNamespaces[2],
Labels: map[string]string{
"app.kubernetes.io/managed-by": "rhacs-fleetshard",
"rhacs.redhat.com/tenant": keepNamespaces[2],
"app.kubernetes.io/instance": "",
},
},
},
&corev1.Namespace{
ObjectMeta: v1.ObjectMeta{
Name: deleteNamespaces[1],
Labels: map[string]string{
"app.kubernetes.io/managed-by": "rhacs-fleetshard",
"rhacs.redhat.com/tenant": deleteNamespaces[1],
"app.kubernetes.io/instance": deleteNamespaces[1],
},
},
},
&corev1.Namespace{
ObjectMeta: v1.ObjectMeta{
Name: keepNamespaces[3],
Labels: map[string]string{
"app.kubernetes.io/managed-by": "something-else",
"rhacs.redhat.com/tenant": keepNamespaces[3],
"app.kubernetes.io/instance": keepNamespaces[3],
},
},
},
&corev1.Namespace{
ObjectMeta: v1.ObjectMeta{
Name: keepNamespaces[4],
Labels: map[string]string{
"app.kubernetes.io/managed-by": "rhacs-fleetshard",
"app.kubernetes.io/instance": keepNamespaces[4],
},
},
},
}

listFromFM := &private.ManagedCentralList{
Items: []private.ManagedCentral{
{
Metadata: private.ManagedCentralAllOfMetadata{
Namespace: keepNamespaces[0],
},
},
{
Metadata: private.ManagedCentralAllOfMetadata{
Namespace: keepNamespaces[1],
},
},
},
}

fakeClient, _ := testutils.NewFakeClientWithTracker(t, existingObjs...)
tenantCleanup := NewTenantCleanup(fakeClient, true)
err := tenantCleanup.DeleteStaleTenantK8sResources(context.TODO(), listFromFM)
require.NoError(t, err, "unexpected error deleting stale tenants")

namespaceList := corev1.NamespaceList{}
err = fakeClient.List(context.TODO(), &namespaceList)
require.NoError(t, err, "unexpected error listing remaining namespaces")

remainingNames := make(map[string]bool, len(namespaceList.Items))
for _, ns := range namespaceList.Items {
remainingNames[ns.Name] = true
}

for _, keepNS := range keepNamespaces {
if !remainingNames[keepNS] {
t.Fatalf("expected namespace %q to still exist, but it was deleted", keepNS)
}
}

for _, deleteNS := range deleteNamespaces {
if remainingNames[deleteNS] {
t.Fatalf("expected namespace %q to be deleted, but was not", deleteNS)
}
}

}

0 comments on commit c74023b

Please sign in to comment.