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 Feb 4, 2024
1 parent 9788e83 commit 85ffd87
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 14 deletions.
1 change: 1 addition & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ linters-settings:
- sigs.k8s.io/controller-runtime
funlen:
lines: 110
statements: 50
gci:
sections:
- standard # Captures all standard packages if they do not match another section.
Expand Down
16 changes: 14 additions & 2 deletions e2e/serviceaccount_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,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 @@ -109,7 +109,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 @@ -258,6 +258,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
4 changes: 2 additions & 2 deletions e2e/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ const (
EnvChartVersionCapsule = "CAPSULE_HELM_VERSION"
EnvChartVersionCapsuleProxy = "CAPSULE_PROXY_HELM_VERSION"

TimeoutKindSeconds = 120
TimeoutHelmInstallSeconds = 120
TimeoutKindSeconds = 600
TimeoutHelmInstallSeconds = 600

KubeConfigPath = "/tmp/kubeconfig"

Expand Down
32 changes: 32 additions & 0 deletions pkg/controller/serviceaccount/namespaces.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2020-2024 Project Capsule Authors.
// SPDX-License-Identifier: Apache-2.0

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: 28 additions & 10 deletions pkg/controller/serviceaccount/serviceaccount.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
clientcmdlatest "k8s.io/client-go/tools/clientcmd/api/latest"
Expand Down Expand Up @@ -142,20 +143,37 @@ 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())
// 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")
}
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")
}

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{Namespace: "", Name: 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 Down

0 comments on commit 85ffd87

Please sign in to comment.