diff --git a/operators/README.md b/operators/README.md index 99629db0f..d62314629 100644 --- a/operators/README.md +++ b/operators/README.md @@ -249,7 +249,7 @@ make run-tenant For a deeper definition go to -- `Tenant` [GoLang code version](./api/v1alpha1/tenant_types.go) +- `Tenant` [GoLang code version](./api/v1alpha2/tenant_types.go) - `Tenant` [YAML version](./deploy/crds/crownlabs.polito.it_tenants.yaml) - `Workspace` [GoLang code version](./api/v1alpha1/workspace_types.go) - `Workspace` [YAML version](./deploy/crds/crownlabs.polito.it_workspaces.yaml) diff --git a/operators/api/v1alpha1/tenant_conversion.go b/operators/api/v1alpha1/tenant_conversion.go deleted file mode 100644 index 7a98fdba8..000000000 --- a/operators/api/v1alpha1/tenant_conversion.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2020-2022 Politecnico di Torino -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v1alpha1 - -import ( - "sigs.k8s.io/controller-runtime/pkg/conversion" - - "github.com/netgroup-polito/CrownLabs/operators/api/v1alpha2" -) - -// ConvertTo converts a v1alpha1.Tenant to a v1alpha2.Tenant. -func (src *Tenant) ConvertTo(dstRaw conversion.Hub) error { - dst := dstRaw.(*v1alpha2.Tenant) - - dst.ObjectMeta = src.ObjectMeta - - dst.Spec.CreateSandbox = src.Spec.CreateSandbox - dst.Spec.Email = src.Spec.Email - dst.Spec.FirstName = src.Spec.FirstName - dst.Spec.LastName = src.Spec.LastName - dst.Spec.PublicKeys = src.Spec.PublicKeys - dst.Spec.Workspaces = make([]v1alpha2.TenantWorkspaceEntry, len(src.Spec.Workspaces)) - dst.Spec.Quota = src.Spec.Quota - for i, w := range src.Spec.Workspaces { - dst.Spec.Workspaces[i].Name = w.WorkspaceRef.Name - dst.Spec.Workspaces[i].Role = w.Role - } - - dst.Status = src.Status - - return nil -} - -// ConvertFrom creates a v1alpha1.Tenant from a v1alpha2.Tenant. -//nolint:stylecheck,revive // allow different receiver name as it is clearer (as in kubebuilder example). -func (dst *Tenant) ConvertFrom(srcRaw conversion.Hub) error { - src := srcRaw.(*v1alpha2.Tenant) - - dst.ObjectMeta = src.ObjectMeta - - dst.Spec.CreateSandbox = src.Spec.CreateSandbox - dst.Spec.Email = src.Spec.Email - dst.Spec.FirstName = src.Spec.FirstName - dst.Spec.LastName = src.Spec.LastName - dst.Spec.PublicKeys = src.Spec.PublicKeys - dst.Spec.Workspaces = make([]TenantWorkspaceEntry, len(src.Spec.Workspaces)) - dst.Spec.Quota = src.Spec.Quota - for i, w := range src.Spec.Workspaces { - dst.Spec.Workspaces[i].WorkspaceRef.Name = w.Name - dst.Spec.Workspaces[i].Role = w.Role - } - - dst.Status = src.Status - - return nil -} diff --git a/operators/api/v1alpha1/tenant_types.go b/operators/api/v1alpha1/tenant_types.go deleted file mode 100644 index c880fd314..000000000 --- a/operators/api/v1alpha1/tenant_types.go +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2020-2022 Politecnico di Torino -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v1alpha1 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - ctrl "sigs.k8s.io/controller-runtime" - - "github.com/netgroup-polito/CrownLabs/operators/api/v1alpha2" -) - -// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! -// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. - -// TenantWorkspaceEntry contains the information regarding one of the Workspaces -// the Tenant is subscribed to, including his/her role. -type TenantWorkspaceEntry struct { - // The reference to the Workspace resource the Tenant is subscribed to. - WorkspaceRef v1alpha2.GenericRef `json:"workspaceRef"` - - // The role of the Tenant in the context of the Workspace. - Role v1alpha2.WorkspaceUserRole `json:"role"` - - // The number of the group the Tenant belongs to. Empty means no group. - GroupNumber uint `json:"groupNumber,omitempty"` -} - -// TenantSpec is the specification of the desired state of the Tenant. -type TenantSpec struct { - // The first name of the Tenant. - FirstName string `json:"firstName"` - - // The last name of the Tenant. - LastName string `json:"lastName"` - - // +kubebuilder:validation:Pattern="^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$" - - // The email associated with the Tenant, which will be used to log-in - // into the system. - Email string `json:"email"` - - // The list of the Workspaces the Tenant is subscribed to, along with his/her - // role in each of them. - Workspaces []TenantWorkspaceEntry `json:"workspaces,omitempty"` - - // The list of the SSH public keys associated with the Tenant. These will be - // used to enable to access the remote environments through the SSH protocol. - PublicKeys []string `json:"publicKeys,omitempty"` - - // +kubebuilder:default=false - - // Whether a sandbox namespace should be created to allow the Tenant play - // with Kubernetes. - CreateSandbox bool `json:"createSandbox,omitempty"` - - // The amount of resources associated with this Tenant, if defined it overrides the one computed from the workspaces the tenant is enrolled in. - Quota *v1alpha2.TenantResourceQuota `json:"quota,omitempty"` -} - -// +kubebuilder:object:root=true -// +kubebuilder:subresource:status -// +kubebuilder:resource:scope="Cluster" -// +kubebuilder:printcolumn:name="First Name",type=string,JSONPath=`.spec.firstName` -// +kubebuilder:printcolumn:name="Last Name",type=string,JSONPath=`.spec.lastName` -// +kubebuilder:printcolumn:name="Email",type=string,JSONPath=`.spec.email`,priority=10 -// +kubebuilder:printcolumn:name="Namespace",type=string,JSONPath=`.status.personalNamespace.name`,priority=10 -// +kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.ready` -// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` - -// Tenant describes a user of CrownLabs. -type Tenant struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec TenantSpec `json:"spec,omitempty"` - Status v1alpha2.TenantStatus `json:"status,omitempty"` -} - -// +kubebuilder:object:root=true - -// TenantList contains a list of Tenant objects. -type TenantList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []Tenant `json:"items"` -} - -func init() { - SchemeBuilder.Register(&Tenant{}, &TenantList{}) -} - -// SetupWebhookWithManager setups the webhook with the given manager. -func (r *Tenant) SetupWebhookWithManager(mgr ctrl.Manager) error { - return ctrl.NewWebhookManagedBy(mgr). - For(r). - Complete() -} diff --git a/operators/api/v1alpha1/zz_generated.deepcopy.go b/operators/api/v1alpha1/zz_generated.deepcopy.go index b3cc88d7c..3eb94235b 100644 --- a/operators/api/v1alpha1/zz_generated.deepcopy.go +++ b/operators/api/v1alpha1/zz_generated.deepcopy.go @@ -154,111 +154,6 @@ func (in *ImageListStatus) DeepCopy() *ImageListStatus { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Tenant) DeepCopyInto(out *Tenant) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Tenant. -func (in *Tenant) DeepCopy() *Tenant { - if in == nil { - return nil - } - out := new(Tenant) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *Tenant) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *TenantList) DeepCopyInto(out *TenantList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]Tenant, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TenantList. -func (in *TenantList) DeepCopy() *TenantList { - if in == nil { - return nil - } - out := new(TenantList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *TenantList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *TenantSpec) DeepCopyInto(out *TenantSpec) { - *out = *in - if in.Workspaces != nil { - in, out := &in.Workspaces, &out.Workspaces - *out = make([]TenantWorkspaceEntry, len(*in)) - copy(*out, *in) - } - if in.PublicKeys != nil { - in, out := &in.PublicKeys, &out.PublicKeys - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.Quota != nil { - in, out := &in.Quota, &out.Quota - *out = new(v1alpha2.TenantResourceQuota) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TenantSpec. -func (in *TenantSpec) DeepCopy() *TenantSpec { - if in == nil { - return nil - } - out := new(TenantSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *TenantWorkspaceEntry) DeepCopyInto(out *TenantWorkspaceEntry) { - *out = *in - out.WorkspaceRef = in.WorkspaceRef -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TenantWorkspaceEntry. -func (in *TenantWorkspaceEntry) DeepCopy() *TenantWorkspaceEntry { - if in == nil { - return nil - } - out := new(TenantWorkspaceEntry) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Workspace) DeepCopyInto(out *Workspace) { *out = *in diff --git a/operators/api/v1alpha2/tenant_types.go b/operators/api/v1alpha2/tenant_types.go index aead93abb..95c30d427 100644 --- a/operators/api/v1alpha2/tenant_types.go +++ b/operators/api/v1alpha2/tenant_types.go @@ -162,9 +162,6 @@ func init() { SchemeBuilder.Register(&Tenant{}, &TenantList{}) } -// Hub is to enable conversion webhook. -func (*Tenant) Hub() {} - // SetupWebhookWithManager setups the webhook with the given manager. func (r *Tenant) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). diff --git a/operators/cmd/tenant-operator/main.go b/operators/cmd/tenant-operator/main.go index 457fbfc90..71f6798b1 100644 --- a/operators/cmd/tenant-operator/main.go +++ b/operators/cmd/tenant-operator/main.go @@ -129,15 +129,6 @@ func main() { os.Exit(1) } if *enableWH { - if err = (&clv1alpha1.Tenant{}).SetupWebhookWithManager(mgr); err != nil { - log.Error(err, "Unable to create conversion webhook", "webhook", "Tenant") - os.Exit(1) - } - if err = (&clv1alpha2.Tenant{}).SetupWebhookWithManager(mgr); err != nil { - log.Error(err, "Unable to create conversion webhook", "webhook", "Tenant") - os.Exit(1) - } - hookServer := mgr.GetWebhookServer() webhookBypassGroupsList := strings.Split(webhookBypassGroups, ",") hookServer.Register(ValidatingWebhookPath, tenantwh.MakeTenantValidator(mgr.GetClient(), webhookBypassGroupsList)) diff --git a/operators/deploy/crds/crownlabs.polito.it_tenants.yaml b/operators/deploy/crds/crownlabs.polito.it_tenants.yaml index 42891e85b..cc68c86e4 100644 --- a/operators/deploy/crds/crownlabs.polito.it_tenants.yaml +++ b/operators/deploy/crds/crownlabs.polito.it_tenants.yaml @@ -16,248 +16,6 @@ spec: singular: tenant scope: Cluster versions: - - additionalPrinterColumns: - - jsonPath: .spec.firstName - name: First Name - type: string - - jsonPath: .spec.lastName - name: Last Name - type: string - - jsonPath: .spec.email - name: Email - priority: 10 - type: string - - jsonPath: .status.personalNamespace.name - name: Namespace - priority: 10 - type: string - - jsonPath: .status.ready - name: Ready - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: Tenant describes a user of CrownLabs. - 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: TenantSpec is the specification of the desired state of the - Tenant. - properties: - createSandbox: - default: false - description: Whether a sandbox namespace should be created to allow - the Tenant play with Kubernetes. - type: boolean - email: - description: The email associated with the Tenant, which will be used - to log-in into the system. - pattern: ^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$ - type: string - firstName: - description: The first name of the Tenant. - type: string - lastName: - description: The last name of the Tenant. - type: string - publicKeys: - description: The list of the SSH public keys associated with the Tenant. - These will be used to enable to access the remote environments through - the SSH protocol. - items: - type: string - type: array - quota: - description: The amount of resources associated with this Tenant, - if defined it overrides the one computed from the workspaces the - tenant is enrolled in. - properties: - cpu: - anyOf: - - type: integer - - type: string - description: The maximum amount of CPU which can be used by this - Tenant. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - instances: - description: The maximum number of concurrent instances which - can be created by this Tenant. - format: int32 - minimum: 0 - type: integer - memory: - anyOf: - - type: integer - - type: string - description: The maximum amount of RAM memory which can be used - by this Tenant. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - required: - - cpu - - instances - - memory - type: object - workspaces: - description: The list of the Workspaces the Tenant is subscribed to, - along with his/her role in each of them. - items: - description: TenantWorkspaceEntry contains the information regarding - one of the Workspaces the Tenant is subscribed to, including his/her - role. - properties: - groupNumber: - description: The number of the group the Tenant belongs to. - Empty means no group. - type: integer - role: - description: The role of the Tenant in the context of the Workspace. - enum: - - manager - - user - type: string - workspaceRef: - description: The reference to the Workspace resource the Tenant - is subscribed to. - properties: - name: - description: The name of the resource to be referenced. - type: string - namespace: - description: The namespace containing the resource to be - referenced. It should be left empty in case of cluster-wide - resources. - type: string - required: - - name - type: object - required: - - role - - workspaceRef - type: object - type: array - required: - - email - - firstName - - lastName - type: object - status: - description: TenantStatus reflects the most recently observed status of - the Tenant. - properties: - failingWorkspaces: - description: The list of Workspaces that are throwing errors during - subscription. This mainly happens if .spec.Workspaces contains references - to Workspaces which do not exist. - items: - type: string - type: array - personalNamespace: - description: The namespace containing all CrownLabs related objects - of the Tenant. This is the namespace that groups his/her own Instances, - together with all the accessory resources (e.g. RBACs, resource - quota, network policies, ...) created by the tenant-operator. - properties: - created: - description: Whether the creation succeeded or not. - type: boolean - name: - description: The name of the considered resource. - type: string - required: - - created - type: object - quota: - description: The amount of resources associated with this Tenant, - either inherited from the Workspaces in which he/she is enrolled, - or manually overridden. - properties: - cpu: - anyOf: - - type: integer - - type: string - description: The maximum amount of CPU which can be used by this - Tenant. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - instances: - description: The maximum number of concurrent instances which - can be created by this Tenant. - format: int32 - minimum: 0 - type: integer - memory: - anyOf: - - type: integer - - type: string - description: The maximum amount of RAM memory which can be used - by this Tenant. - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - required: - - cpu - - instances - - memory - type: object - ready: - description: Whether all subscriptions and resource creations succeeded - or an error occurred. In case of errors, the other status fields - provide additional information about which problem occurred. - type: boolean - sandboxNamespace: - description: The namespace that can be freely used by the Tenant to - play with Kubernetes. This namespace is created only if the .spec.CreateSandbox - flag is true. - properties: - created: - description: Whether the creation succeeded or not. - type: boolean - name: - description: The name of the considered resource. - type: string - required: - - created - type: object - subscriptions: - additionalProperties: - description: SubscriptionStatus is an enumeration of the different - states that can be assumed by the subscription to a service (e.g. - successful or failing). - enum: - - Ok - - Failed - type: string - description: The list of the subscriptions to external services (e.g. - Keycloak, Nextcloud, ...), indicating for each one whether it succeeded - or an error occurred. - type: object - required: - - failingWorkspaces - - personalNamespace - - ready - - sandboxNamespace - - subscriptions - type: object - type: object - served: true - storage: false - subresources: - status: {} - additionalPrinterColumns: - jsonPath: .spec.firstName name: First Name