Skip to content

Commit

Permalink
Add subnamespace controller functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
ubombar committed Mar 21, 2024
1 parent cb53f2e commit f648553
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 9 deletions.
7 changes: 4 additions & 3 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ limitations under the License.
package main

import (
"context"
"crypto/tls"
"flag"
"fmt"
"os"

// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
// to ensure that exec-entrypoint and run can make use of them.
"google.golang.org/appengine/log"

_ "k8s.io/client-go/plugin/pkg/client/auth"

"k8s.io/apimachinery/pkg/runtime"
Expand Down Expand Up @@ -147,7 +147,8 @@ func main() {
disableNodeLabeller := err != nil

if err != nil {
log.Warningf(context.TODO(), "Cannot retrieve the MaxMind Account Token, running without the NodeLabeller")
fmt.Println("Skipping node labeller")
// log.Warningf(context.TODO(), "Cannot retrieve the MaxMind Account Token, running without the NodeLabeller")
}

// Setup reconcilers, we might want to add the list of reconcilers. This part is auto generated.
Expand Down
54 changes: 54 additions & 0 deletions config/crd/bases/multitenancy.edge-net.io_subnamespaces.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.14.0
name: subnamespaces.multitenancy.edge-net.io
spec:
group: multitenancy.edge-net.io
names:
kind: SubNamespace
listKind: SubNamespaceList
plural: subnamespaces
singular: subnamespace
scope: Namespaced
versions:
- name: v1
schema:
openAPIV3Schema:
description: SubNamespace is the Schema for the subnamespaces API
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: SubNamespaceSpec defines the desired state of SubNamespace
properties:
foo:
description: Foo is an example field of SubNamespace. Edit subnamespace_types.go
to remove/update
type: string
type: object
status:
description: SubNamespaceStatus defines the observed state of SubNamespace
type: object
type: object
served: true
storage: true
subresources:
status: {}
26 changes: 26 additions & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,32 @@ rules:
- patch
- update
- watch
- apiGroups:
- multitenancy.edge-net.io
resources:
- subnamespaces
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- multitenancy.edge-net.io
resources:
- subnamespaces/finalizers
verbs:
- update
- apiGroups:
- multitenancy.edge-net.io
resources:
- subnamespaces/status
verbs:
- get
- patch
- update
- apiGroups:
- multitenancy.edge-net.io
resources:
Expand Down
41 changes: 38 additions & 3 deletions internal/controller/multitenancy/subnamespace_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,21 @@ import (
"context"

"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/tools/record"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"

multitenancyv1 "github.com/edgenet-project/edgenet/api/multitenancy/v1"
"github.com/edgenet-project/edgenet/internal/multitenancy/v1"
"github.com/edgenet-project/edgenet/internal/utils"
)

// SubNamespaceReconciler reconciles a SubNamespace object
type SubNamespaceReconciler struct {
client.Client
Scheme *runtime.Scheme
Scheme *runtime.Scheme
recorder record.EventRecorder
}

//+kubebuilder:rbac:groups=multitenancy.edge-net.io,resources=subnamespaces,verbs=get;list;watch;create;update;patch;delete
Expand All @@ -47,15 +51,46 @@ type SubNamespaceReconciler struct {
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/[email protected]/pkg/reconcile
func (r *SubNamespaceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
_ = log.FromContext(ctx)
logger := log.FromContext(ctx)
sns := multitenancyv1.SubNamespace{}
isMarkedForDeletion, reconcileResult, err := utils.GetResourceWithFinalizer(ctx, r.Client, &sns, req.NamespacedName)

// TODO(user): your logic here
if !utils.IsObjectInitialized(&sns) {
return reconcileResult, err
}

multiTenancyManager, err := multitenancy.NewMultiTenancyManager(ctx, r.Client)

if err != nil {
logger.Error(err, "cannot create multitenancy manager")
return ctrl.Result{}, err
}

if isMarkedForDeletion {
// Do a cleanup and allow tenant object for deletion
if err := multiTenancyManager.SubNamespaceCleanup(ctx, &sns); err != nil {
utils.RecordEventError(r.recorder, &sns, "SubNamespace cleanup failed")
return ctrl.Result{Requeue: true}, err
}

return utils.AllowObjectDeletion(ctx, r.Client, &sns)
} else {
// TODO: What to do now?
if err := multiTenancyManager.SetupSubNamespace(ctx, &sns); err != nil {
utils.RecordEventError(r.recorder, &sns, "SubNamespace setup failed")
return ctrl.Result{Requeue: true}, err
}
}

utils.RecordEventInfo(r.recorder, &sns, "SubNamespace reconciliation successfull")
return ctrl.Result{}, nil
}

// SetupWithManager sets up the controller with the Manager.
func (r *SubNamespaceReconciler) SetupWithManager(mgr ctrl.Manager) error {
// Setup the event recorder
r.recorder = utils.GetEventRecorder(mgr)

return ctrl.NewControllerManagedBy(mgr).
For(&multitenancyv1.SubNamespace{}).
Complete(r)
Expand Down
58 changes: 55 additions & 3 deletions internal/multitenancy/v1/multitenancy.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package multitenancy

import (
"context"
"fmt"

antreav1alpha1 "antrea.io/antrea/pkg/apis/crd/v1alpha1"
multitenancyv1 "github.com/edgenet-project/edgenet/api/multitenancy/v1"
Expand Down Expand Up @@ -45,14 +46,20 @@ type MultiTenancyManager interface {
CreateCoreNamespace(context.Context, *multitenancyv1.Tenant, types.UID) error

// Same as the CreateCoreNamespace except gets the UID from local cluster.
CreateCoreNamespaceLocal(ctx context.Context, t *multitenancyv1.Tenant) error
CreateCoreNamespaceLocal(context.Context, *multitenancyv1.Tenant) error

// Creates a new tenant role binding with admin priviliages. Requires "edgenet:tenant-admin" role
// to work.
CreateTenantAdminRoleBinding(ctx context.Context, t *multitenancyv1.Tenant) error
CreateTenantAdminRoleBinding(context.Context, *multitenancyv1.Tenant) error

// Create the network policy. If specified creates the cluster network policy as well.
CreateTenantNetworkPolicy(ctx context.Context, t *multitenancyv1.Tenant) error
CreateTenantNetworkPolicy(context.Context, *multitenancyv1.Tenant) error

// Cleanups the SubNamespace
SubNamespaceCleanup(context.Context, *multitenancyv1.SubNamespace) error

// Creates and setups studd for the SubNamespace
SetupSubNamespace(context.Context, *multitenancyv1.SubNamespace) error
}

type multiTenancyManager struct {
Expand Down Expand Up @@ -372,3 +379,48 @@ func (m *multiTenancyManager) CreateTenantNetworkPolicy(ctx context.Context, t *

return nil
}

// Deletes the created child namespace.
func (m *multiTenancyManager) SubNamespaceCleanup(ctx context.Context, s *multitenancyv1.SubNamespace) error {
subNamespaceName := utils.ResolveSubNamespaceName(s)

ns := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: subNamespaceName,
},
}

// Try to delete the namespace, ignore if not found
if err := m.client.Delete(ctx, ns); err != nil && !errors.IsNotFound(err) {
return err
}

fmt.Println("Deleted successfully")

return nil
}

// This creates a new namespace using the generated name. Then populates the namespace with the initial allocation.
// Then gives the current tenant admin the permissions.
func (m *multiTenancyManager) SetupSubNamespace(ctx context.Context, s *multitenancyv1.SubNamespace) error {
subNamespaceName := utils.ResolveSubNamespaceName(s)

ns := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: subNamespaceName,
Labels: map[string]string{
"edge-net.io/generated": "true",
"edge-net.io/kind": "sub",
},
},
}

// Try to create the namespace, continue even if it already exist
if err := m.client.Create(ctx, ns); err != nil && !errors.IsAlreadyExists(err) {
return err
}

// TODO: Create the role bingind etc.

return nil
}
6 changes: 6 additions & 0 deletions internal/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import (
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/reconcile"

multitenancyv1 "github.com/edgenet-project/edgenet/api/multitenancy/v1"
)

// Define a custom type that implements the flag.Value interface
Expand Down Expand Up @@ -60,6 +62,10 @@ func ResolveCoreNamespaceName(tenantName string) string {
return tenantName
}

func ResolveSubNamespaceName(s *multitenancyv1.SubNamespace) string {
return fmt.Sprintf("%s-%s", s.GetName(), s.GetUID())
}

// Check a string exists in a list of strings
func containsFinalizer(finalizers []string, finalizer string) bool {
for _, item := range finalizers {
Expand Down

0 comments on commit f648553

Please sign in to comment.