Skip to content

Commit

Permalink
Merge pull request #552 from fluxcd/impersonation-finalize
Browse files Browse the repository at this point in the history
Ensure object are finalized under impersonation
  • Loading branch information
stefanprodan authored Jan 31, 2022
2 parents cd6fff0 + 65aaa1d commit ceefe5a
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 7 deletions.
18 changes: 11 additions & 7 deletions controllers/kustomization_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -922,13 +922,12 @@ func (r *KustomizationReconciler) finalize(ctx context.Context, kustomization ku
objects, _ := ListObjectsInInventory(kustomization.Status.Inventory)

impersonation := NewKustomizeImpersonation(kustomization, r.Client, r.StatusPoller, r.DefaultServiceAccount)
kubeClient, _, err := impersonation.GetClient(ctx)
if err != nil {
// when impersonation fails, log the stale objects and continue with the finalization
msg := fmt.Sprintf("unable to prune objects: \n%s", ssa.FmtUnstructuredList(objects))
log.Error(fmt.Errorf("failed to build kube client: %w", err), msg)
r.event(ctx, kustomization, kustomization.Status.LastAppliedRevision, events.EventSeverityError, msg, nil)
} else {
if impersonation.CanFinalize(ctx) {
kubeClient, _, err := impersonation.GetClient(ctx)
if err != nil {
return ctrl.Result{}, err
}

resourceManager := ssa.NewResourceManager(kubeClient, nil, ssa.Owner{
Field: r.ControllerName,
Group: kustomizev1.GroupVersion.Group,
Expand All @@ -953,6 +952,11 @@ func (r *KustomizationReconciler) finalize(ctx context.Context, kustomization ku
if changeSet != nil && len(changeSet.Entries) > 0 {
r.event(ctx, kustomization, kustomization.Status.LastAppliedRevision, events.EventSeverityInfo, changeSet.String(), nil)
}
} else {
// when the account to impersonate is gone, log the stale objects and continue with the finalization
msg := fmt.Sprintf("unable to prune objects: \n%s", ssa.FmtUnstructuredList(objects))
log.Error(fmt.Errorf("skiping pruning, failed to find account to impersonate"), msg)
r.event(ctx, kustomization, kustomization.Status.LastAppliedRevision, events.EventSeverityError, msg, nil)
}
}

Expand Down
29 changes: 29 additions & 0 deletions controllers/kustomization_impersonation.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ package controllers
import (
"context"
"fmt"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
Expand Down Expand Up @@ -69,6 +71,33 @@ func (ki *KustomizeImpersonation) GetClient(ctx context.Context) (client.Client,
}
}

// CanFinalize asserts if the given Kustomization can be finalized using impersonation.
func (ki *KustomizeImpersonation) CanFinalize(ctx context.Context) bool {
name := ki.defaultServiceAccount
if sa := ki.kustomization.Spec.ServiceAccountName; sa != "" {
name = sa
}
if name == "" {
return true
}

sa := &corev1.ServiceAccount{
TypeMeta: metav1.TypeMeta{
Kind: "ServiceAccount",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: ki.kustomization.Namespace,
},
}
if err := ki.Client.Get(ctx, client.ObjectKeyFromObject(sa), sa); err != nil {
return false
}

return true
}

func (ki *KustomizeImpersonation) setImpersonationConfig(restConfig *rest.Config) {
name := ki.defaultServiceAccount
if sa := ki.kustomization.Spec.ServiceAccountName; sa != "" {
Expand Down
20 changes: 20 additions & 0 deletions controllers/kustomization_impersonation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
Expand Down Expand Up @@ -101,6 +102,7 @@ data:
Kind: sourcev1.GitRepositoryKind,
},
TargetNamespace: id,
Prune: true,
},
}

Expand Down Expand Up @@ -187,4 +189,22 @@ data:

g.Expect(readyCondition.Reason).To(Equal(meta.ReconciliationSucceededReason))
})

t.Run("can finalize impersonating service account", func(t *testing.T) {
saK := &kustomizev1.Kustomization{}
err = k8sClient.Get(context.Background(), client.ObjectKeyFromObject(kustomization), saK)
g.Expect(err).NotTo(HaveOccurred())

err = k8sClient.Delete(context.Background(), saK)
g.Expect(err).NotTo(HaveOccurred())

g.Eventually(func() bool {
err := k8sClient.Get(context.Background(), client.ObjectKeyFromObject(kustomization), resultK)
return apierrors.IsNotFound(err)
}, timeout, time.Second).Should(BeTrue())

resultConfig := &corev1.ConfigMap{}
err := k8sClient.Get(context.Background(), types.NamespacedName{Name: id, Namespace: id}, resultConfig)
g.Expect(apierrors.IsNotFound(err)).To(BeTrue())
})
}

0 comments on commit ceefe5a

Please sign in to comment.