Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Groups as Subject Kind for Tenant Namespace RoleBindings created by Capsule #71

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions api/v1alpha1/tenant_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ type AdditionalMetadata struct {

// TenantSpec defines the desired state of Tenant
type TenantSpec struct {
Owner string `json:"owner"`
Owner OwnerSpec `json:"owner"`
// +kubebuilder:validation:Optional
NamespacesMetadata AdditionalMetadata `json:"namespacesMetadata"`
// +kubebuilder:validation:Optional
Expand All @@ -51,6 +51,19 @@ type TenantSpec struct {
ResourceQuota []corev1.ResourceQuotaSpec `json:"resourceQuotas"`
}

// OwnerSpec defines tenant owner name and kind
type OwnerSpec struct {
Name string `json:"name"`
Kind Kind `json:"kind"`
}

// +kubebuilder:validation:Enum=User;Group
type Kind string

func (k Kind) String() string {
return string(k)
}

// TenantStatus defines the observed state of Tenant
type TenantStatus struct {
Size uint `json:"size"`
Expand All @@ -64,7 +77,8 @@ type TenantStatus struct {
// +kubebuilder:resource:scope=Cluster,shortName=tnt
// +kubebuilder:printcolumn:name="Namespace quota",type="integer",JSONPath=".spec.namespaceQuota",description="The max amount of Namespaces can be created"
// +kubebuilder:printcolumn:name="Namespace count",type="integer",JSONPath=".status.size",description="The total amount of Namespaces in use"
// +kubebuilder:printcolumn:name="Owner",type="string",JSONPath=".spec.owner",description="The assigned Tenant owner"
// +kubebuilder:printcolumn:name="Owner name",type="string",JSONPath=".spec.owner.name",description="The assigned Tenant owner"
// +kubebuilder:printcolumn:name="Owner kind",type="string",JSONPath=".spec.owner.kind",description="The assigned Tenant owner kind"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Age"

// Tenant is the Schema for the tenants API
Expand Down
16 changes: 16 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 19 additions & 3 deletions config/crd/bases/capsule.clastix.io_tenants.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@ spec:
description: The total amount of Namespaces in use
name: Namespace count
type: integer
- JSONPath: .spec.owner
- JSONPath: .spec.owner.name
description: The assigned Tenant owner
name: Owner
name: Owner name
type: string
- JSONPath: .spec.owner.kind
description: The assigned Tenant owner kind
name: Owner kind
type: string
- JSONPath: .metadata.creationTimestamp
description: Age
Expand Down Expand Up @@ -617,7 +621,19 @@ spec:
type: string
type: object
owner:
type: string
description: OwnerSpec defines tenant owner name and kind
properties:
kind:
enum:
- User
- Group
type: string
name:
type: string
required:
- kind
- name
type: object
resourceQuotas:
items:
description: ResourceQuotaSpec defines the desired hard limits to
Expand Down
4 changes: 3 additions & 1 deletion config/samples/capsule_v1alpha1_tenant.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ spec:
- Egress
nodeSelector:
kubernetes.io/os: linux
owner: alice
owner:
name: alice
kind: User
resourceQuotas:
-
hard:
Expand Down
17 changes: 17 additions & 0 deletions config/webhook/manifests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,23 @@ webhooks:
- CREATE
resources:
- persistentvolumeclaims
- clientConfig:
caBundle: Cg==
service:
name: webhook-service
namespace: system
path: /validating-v1-tenant-name
failurePolicy: Fail
name: tenant.name.capsule.clastix.io
rules:
- apiGroups:
- capsule.clastix.io
apiVersions:
- v1alpha1
operations:
- CREATE
resources:
- tenants
- clientConfig:
caBundle: Cg==
service:
Expand Down
4 changes: 2 additions & 2 deletions controllers/tenant_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -519,8 +519,8 @@ func (r *TenantReconciler) ownerRoleBinding(tenant *capsulev1alpha1.Tenant) erro
l := map[string]string{tl: tenant.Name}
s := []rbacv1.Subject{
{
Kind: "User",
Name: tenant.Spec.Owner,
Kind: tenant.Spec.Owner.Kind.String(),
Name: tenant.Spec.Owner.Name,
},
}

Expand Down
7 changes: 5 additions & 2 deletions e2e/custom_capsule_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,13 @@ import (
var _ = Describe("creating a Namespace as Tenant owner with custom --capsule-group", func() {
tnt := &v1alpha1.Tenant{
ObjectMeta: metav1.ObjectMeta{
Name: "tenant-assigned-custom-group",
Name: "tenantassignedcustomgroup",
},
Spec: v1alpha1.TenantSpec{
Owner: "alice",
Owner: v1alpha1.OwnerSpec{
Name: "alice",
Kind: "User",
},
NamespacesMetadata: v1alpha1.AdditionalMetadata{},
ServicesMetadata: v1alpha1.AdditionalMetadata{},
StorageClasses: []string{},
Expand Down
96 changes: 96 additions & 0 deletions e2e/force_tenant_prefix_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//+build e2e

/*
Copyright 2020 Clastix Labs.

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 e2e

import (
"context"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/clastix/capsule/api/v1alpha1"
)

var _ = Describe("creating a Namespace with --force-tenant-name flag", func() {
MaxFedotov marked this conversation as resolved.
Show resolved Hide resolved
t1 := &v1alpha1.Tenant{
ObjectMeta: metav1.ObjectMeta{
Name: "first",
},
Spec: v1alpha1.TenantSpec{
Owner: v1alpha1.OwnerSpec{
Name: "john",
Kind: "User",
},
NamespacesMetadata: v1alpha1.AdditionalMetadata{},
ServicesMetadata: v1alpha1.AdditionalMetadata{},
StorageClasses: []string{},
IngressClasses: []string{},
LimitRanges: []corev1.LimitRangeSpec{},
NamespaceQuota: 10,
NodeSelector: map[string]string{},
ResourceQuota: []corev1.ResourceQuotaSpec{},
},
}
t2 := &v1alpha1.Tenant{
ObjectMeta: metav1.ObjectMeta{
Name: "second",
},
Spec: v1alpha1.TenantSpec{
Owner: v1alpha1.OwnerSpec{
Name: "john",
Kind: "User",
},
NamespacesMetadata: v1alpha1.AdditionalMetadata{},
ServicesMetadata: v1alpha1.AdditionalMetadata{},
StorageClasses: []string{},
IngressClasses: []string{},
LimitRanges: []corev1.LimitRangeSpec{},
NamespaceQuota: 10,
NodeSelector: map[string]string{},
ResourceQuota: []corev1.ResourceQuotaSpec{},
},
}
JustBeforeEach(func() {
t1.ResourceVersion = ""
t2.ResourceVersion = ""
Expect(k8sClient.Create(context.TODO(), t1)).Should(Succeed())
Expect(k8sClient.Create(context.TODO(), t2)).Should(Succeed())
})
JustAfterEach(func() {
Expect(k8sClient.Delete(context.TODO(), t1)).Should(Succeed())
Expect(k8sClient.Delete(context.TODO(), t2)).Should(Succeed())
})
It("should fail", func() {
args := append(defaulManagerPodArgs, []string{"--force-tenant-prefix"}...)
ModifyCapsuleManagerPodArgs(args)
ns := NewNamespace("test")
NamespaceCreationShouldNotSucceed(ns, t1, podRecreationTimeoutInterval)
})
It("should be assigned to the second Tenant", func() {
ns := NewNamespace("second-test")
ns2 := NewNamespace("second-test2")
NamespaceCreationShouldSucceed(ns, t2, podRecreationTimeoutInterval)
NamespaceShouldBeManagedByTenant(ns, t2, podRecreationTimeoutInterval)
NamespaceCreationShouldNotSucceed(ns2, t1, podRecreationTimeoutInterval)
args := defaulManagerPodArgs
ModifyCapsuleManagerPodArgs(args)
})
})
7 changes: 5 additions & 2 deletions e2e/ingress_class_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,13 @@ import (
var _ = Describe("when Tenant handles Ingress classes", func() {
tnt := &v1alpha1.Tenant{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-class",
Name: "ingressclass",
MaxFedotov marked this conversation as resolved.
Show resolved Hide resolved
},
Spec: v1alpha1.TenantSpec{
Owner: "ingress",
Owner: v1alpha1.OwnerSpec{
Name: "ingress",
Kind: "User",
},
NamespacesMetadata: v1alpha1.AdditionalMetadata{},
ServicesMetadata: v1alpha1.AdditionalMetadata{},
StorageClasses: []string{},
Expand Down
5 changes: 4 additions & 1 deletion e2e/missing_tenant_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ var _ = Describe("Namespace creation with no Tenant assigned", func() {
It("should fail", func() {
tnt := &v1alpha1.Tenant{
Spec: v1alpha1.TenantSpec{
Owner: "missing",
Owner: v1alpha1.OwnerSpec{
Name: "missing",
Kind: "User",
},
},
}
ns := NewNamespace("no-namespace")
Expand Down
7 changes: 5 additions & 2 deletions e2e/namespace_metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,13 @@ import (
var _ = Describe("creating a Namespace for a Tenant with additional metadata", func() {
tnt := &v1alpha1.Tenant{
ObjectMeta: metav1.ObjectMeta{
Name: "tenant-metadata",
Name: "tenantmetadata",
},
Spec: v1alpha1.TenantSpec{
Owner: "gatsby",
Owner: v1alpha1.OwnerSpec{
Name: "gatsby",
Kind: "User",
},
StorageClasses: []string{},
IngressClasses: []string{},
NamespacesMetadata: v1alpha1.AdditionalMetadata{
Expand Down
7 changes: 5 additions & 2 deletions e2e/new_namespace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,13 @@ import (
var _ = Describe("creating a Namespace as Tenant owner", func() {
tnt := &v1alpha1.Tenant{
ObjectMeta: metav1.ObjectMeta{
Name: "tenant-assigned",
Name: "tenantassigned",
},
Spec: v1alpha1.TenantSpec{
Owner: "alice",
Owner: v1alpha1.OwnerSpec{
Name: "alice",
Kind: "User",
},
StorageClasses: []string{},
IngressClasses: []string{},
NamespacesMetadata: v1alpha1.AdditionalMetadata{},
Expand Down
7 changes: 5 additions & 2 deletions e2e/overquota_namespace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,13 @@ import (
var _ = Describe("creating a Namespace over-quota", func() {
tnt := &v1alpha1.Tenant{
ObjectMeta: metav1.ObjectMeta{
Name: "overquota-tenant",
Name: "overquotatenant",
},
Spec: v1alpha1.TenantSpec{
Owner: "bob",
Owner: v1alpha1.OwnerSpec{
Name: "bob",
Kind: "User",
},
NamespacesMetadata: v1alpha1.AdditionalMetadata{},
ServicesMetadata: v1alpha1.AdditionalMetadata{},
StorageClasses: []string{},
Expand Down
7 changes: 5 additions & 2 deletions e2e/owner_webhooks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,13 @@ import (
var _ = Describe("when Tenant owner interacts with the webhooks", func() {
tnt := &v1alpha1.Tenant{
ObjectMeta: metav1.ObjectMeta{
Name: "tenant-owner",
Name: "tenantowner",
},
Spec: v1alpha1.TenantSpec{
Owner: "ruby",
Owner: v1alpha1.OwnerSpec{
Name: "ruby",
Kind: "User",
},
NamespacesMetadata: v1alpha1.AdditionalMetadata{},
ServicesMetadata: v1alpha1.AdditionalMetadata{},
StorageClasses: []string{
Expand Down
7 changes: 5 additions & 2 deletions e2e/protected_namespace_regex_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ var _ = Describe("creating a Namespace with --protected-namespace-regex enabled"
Name: "tenantprotectednamespace",
},
Spec: v1alpha1.TenantSpec{
Owner: "alice",
Owner: v1alpha1.OwnerSpec{
Name: "alice",
Kind: "User",
},
NamespacesMetadata: v1alpha1.AdditionalMetadata{},
ServicesMetadata: v1alpha1.AdditionalMetadata{},
StorageClasses: []string{},
Expand All @@ -61,8 +64,8 @@ var _ = Describe("creating a Namespace with --protected-namespace-regex enabled"
NamespaceShouldBeManagedByTenant(ns, tnt, podRecreationTimeoutInterval)
})
It("should fail", func() {
ModifyCapsuleManagerPodArgs(defaulManagerPodArgs)
ns := NewNamespace("test-system")
NamespaceCreationShouldNotSucceed(ns, tnt, podRecreationTimeoutInterval)
ModifyCapsuleManagerPodArgs(defaulManagerPodArgs)
})
})
7 changes: 5 additions & 2 deletions e2e/resource_quota_exceeded_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,13 @@ import (
var _ = Describe("exceeding Tenant resource quota", func() {
tnt := &v1alpha1.Tenant{
ObjectMeta: metav1.ObjectMeta{
Name: "tenant-resources-changes",
Name: "tenantresourceschanges",
},
Spec: v1alpha1.TenantSpec{
Owner: "bobby",
Owner: v1alpha1.OwnerSpec{
Name: "bobby",
Kind: "User",
},
NamespacesMetadata: v1alpha1.AdditionalMetadata{},
ServicesMetadata: v1alpha1.AdditionalMetadata{},
StorageClasses: []string{},
Expand Down
Loading