Skip to content

Commit

Permalink
feat: move the tenant system namespace inside the tenant
Browse files Browse the repository at this point in the history
Signed-off-by: Massimiliano Giovagnoli <[email protected]>
  • Loading branch information
maxgio92 committed Jan 24, 2024
1 parent 0ae46d5 commit 7206185
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 13 deletions.
16 changes: 14 additions & 2 deletions e2e/serviceaccount_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ var _ = Describe("Creating a new ServiceAccount", func() {
})
})
Context("set as owner of the Tenant", func() {
BeforeEach(func() {
BeforeAll(func() {
Expect(adminClient.Create(context.TODO(), &capsulev1beta2.Tenant{
ObjectMeta: metav1.ObjectMeta{
Name: TenantName,
Expand All @@ -106,7 +106,7 @@ var _ = Describe("Creating a new ServiceAccount", func() {
},
})).Should(Succeed())
})
AfterEach(func() {
AfterAll(func() {
Expect(adminClient.Delete(context.TODO(), &capsulev1beta2.Tenant{
ObjectMeta: metav1.ObjectMeta{
Name: TenantName,
Expand Down Expand Up @@ -255,6 +255,18 @@ var _ = Describe("Creating a new ServiceAccount", func() {
g.Expect(gtr.Spec.Resources).To(BeNil())
}, 20*time.Second, 1*time.Second).Should(Succeed())
})

It("should set the correct owner reference to the Tenant system Namespace", func() {
Eventually(func(g Gomega) {
ns := new(corev1.Namespace)
Expect(adminClient.Get(context.TODO(), types.NamespacedName{
Name: sa.Namespace,
}, ns)).Should(Succeed())
Expect(len(ns.OwnerReferences)).To(Equal(1))
Expect(ns.OwnerReferences[0].Kind).To(Equal("Tenant"))
Expect(ns.OwnerReferences[0].Name).To(Equal(TenantName))
}, 20*time.Second, 1*time.Second).Should(Succeed())
})
})

When("has the annotation to enable the addon and the annotation to make the kubeconfig global", func() {
Expand Down
28 changes: 28 additions & 0 deletions pkg/controller/serviceaccount/namespaces.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package serviceaccount

import (
"context"

capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)

// Set the Tenant owner reference on the Namespace specified.
func (r *ServiceAccountReconciler) setNamespaceOwnerRef(ctx context.Context, ns *corev1.Namespace, tnt *capsulev1beta2.Tenant) error {
scheme := runtime.NewScheme()
_ = capsulev1beta2.AddToScheme(scheme)
_ = corev1.AddToScheme(scheme)

if _, err := controllerutil.CreateOrUpdate(ctx, r.Client, ns, func() error {
if err := controllerutil.SetControllerReference(tnt, ns, scheme); err != nil {
return err
}
return nil
}); err != nil {
return err
}

return nil
}
38 changes: 27 additions & 11 deletions pkg/controller/serviceaccount/serviceaccount.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package serviceaccount
import (
"context"
"fmt"
"k8s.io/apimachinery/pkg/types"

"github.com/go-logr/logr"
"github.com/pkg/errors"
Expand Down Expand Up @@ -138,18 +139,34 @@ func (r *ServiceAccountReconciler) Reconcile(ctx context.Context, request ctrl.R
return reconcile.Result{}, errors.Wrap(err, "error ensuring the kubeConfig secret")
}

// If the option for distributing the kubeConfig to Tenant globally.
if sa.GetAnnotations()[ServiceAccountGlobalAnnotationKey] == ServiceAccountGlobalAnnotationValue {
// Get the Tenant owned by the ServiceAccount.
ownerName := fmt.Sprintf("system:serviceaccount:%s:%s", sa.GetNamespace(), sa.GetName())
tenantList, err := r.listTenantsOwned(ctx, string(capsulev1beta2.ServiceAccountOwner), ownerName)
if err != nil {
return reconcile.Result{}, errors.Wrap(err, "error listing Tenants for owner")
}
if tenantList.Items == nil {
return reconcile.Result{}, errors.New("Tenant list for owner is empty")
// Get the Tenant owned by the ServiceAccount.
ownerName := fmt.Sprintf("system:serviceaccount:%s:%s", sa.GetNamespace(), sa.GetName())
tenantList, err := r.listTenantsOwned(ctx, string(capsulev1beta2.ServiceAccountOwner), ownerName)
if err != nil {
return reconcile.Result{}, errors.Wrap(err, "error listing Tenants for owner")
}
if tenantList.Items == nil {
return reconcile.Result{}, errors.New("Tenant list for owner is empty")
}

// Get the ServiceAccount's Namespace.
ns := new(corev1.Namespace)
if err = r.Client.Get(ctx, types.NamespacedName{"", sa.Namespace}, ns); err != nil {
if apierrors.IsNotFound(err) {
r.Log.Info("ServiceAccount Namespace is missing. Requeueing.")

return reconcile.Result{Requeue: true}, nil
}
r.Log.Error(err, "Error reading the object")

return reconcile.Result{}, err
}
// And set the first Tenant owned by the SA as Namespace owner.
if err = r.setNamespaceOwnerRef(ctx, ns, tenantList.Items[0].DeepCopy()); err != nil {
return reconcile.Result{}, errors.Wrap(err, "error setting the owner reference on the namespace")
}
// If the option for distributing the kubeConfig to Tenant globally.
if sa.GetAnnotations()[ServiceAccountGlobalAnnotationKey] == ServiceAccountGlobalAnnotationValue {
for _, tenant := range tenantList.Items {
// Ensure the GlobalTenantResource to distribute the kubeConfig Secret.
name := fmt.Sprintf("%s-%s%s", tenant.Name, sa.Name, GlobalTenantResourceSuffix)
Expand All @@ -158,7 +175,6 @@ func (r *ServiceAccountReconciler) Reconcile(ctx context.Context, request ctrl.R
}
}
}

r.Log.Info("ServiceAccount reconciliation completed")

return reconcile.Result{}, nil
Expand Down

0 comments on commit 7206185

Please sign in to comment.