mirror of
https://github.com/projectcapsule/capsule.git
synced 2026-08-19 04:26:45 +00:00
feat(tenant): add label with tenant name for each tenant
Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>
This commit is contained in:
committed by
Dario Tranchitella
parent
3c85657d9a
commit
c58b46cedf
@@ -48,6 +48,7 @@ const (
|
||||
PriorityClassesProxy ProxyServiceKind = "PriorityClasses"
|
||||
RuntimeClassesProxy ProxyServiceKind = "RuntimeClasses"
|
||||
PersistentVolumesProxy ProxyServiceKind = "PersistentVolumes"
|
||||
TenantProxy ProxyServiceKind = "Tenant"
|
||||
|
||||
ListOperation ProxyOperation = "List"
|
||||
UpdateOperation ProxyOperation = "Update"
|
||||
|
||||
@@ -60,6 +60,13 @@ func (r Manager) Reconcile(ctx context.Context, request ctrl.Request) (result ct
|
||||
|
||||
return
|
||||
}
|
||||
// Ensuring Metadata
|
||||
if err = r.ensureMetadata(ctx, instance); err != nil {
|
||||
r.Log.Error(err, "Cannot ensure metadata")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Ensuring ResourceQuota
|
||||
r.Log.Info("Ensuring limit resources count is updated")
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright 2020-2023 Project Capsule Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package tenant
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2"
|
||||
capsuleapi "github.com/projectcapsule/capsule/pkg/api"
|
||||
)
|
||||
|
||||
// Sets a label on the Tenant object with it's name.
|
||||
func (r *Manager) ensureMetadata(ctx context.Context, tnt *capsulev1beta2.Tenant) (err error) {
|
||||
// Assign Labels
|
||||
if tnt.Labels == nil {
|
||||
tnt.Labels = make(map[string]string)
|
||||
}
|
||||
|
||||
tnt.Labels[capsuleapi.TenantNameLabel] = tnt.Name
|
||||
|
||||
return r.Client.Update(ctx, tnt)
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
//go:build e2e
|
||||
|
||||
// Copyright 2020-2023 Project Capsule Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
||||
capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2"
|
||||
)
|
||||
|
||||
func getLabels(tnt capsulev1beta2.Tenant) (map[string]string, error) {
|
||||
current := &capsulev1beta2.Tenant{}
|
||||
err := k8sClient.Get(context.TODO(), types.NamespacedName{Name: tnt.GetName()}, current)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return current.GetLabels(), nil
|
||||
}
|
||||
|
||||
var _ = Describe("adding metadata to a Tenant", func() {
|
||||
tnt := &capsulev1beta2.Tenant{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "tenant-metadata",
|
||||
Labels: map[string]string{
|
||||
"custom-label": "test",
|
||||
},
|
||||
},
|
||||
Spec: capsulev1beta2.TenantSpec{
|
||||
Owners: capsulev1beta2.OwnerListSpec{
|
||||
{
|
||||
Name: "jim",
|
||||
Kind: "User",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
JustBeforeEach(func() {
|
||||
EventuallyCreation(func() error {
|
||||
return k8sClient.Create(context.TODO(), tnt)
|
||||
}).Should(Succeed())
|
||||
})
|
||||
|
||||
JustAfterEach(func() {
|
||||
Expect(k8sClient.Delete(context.TODO(), tnt)).Should(Succeed())
|
||||
})
|
||||
|
||||
It("Should ensure label metadata", func() {
|
||||
By("Default labels", func() {
|
||||
currentlabels, _ := getLabels(*tnt)
|
||||
Expect(currentlabels["kubernetes.io/metadata.name"]).To(Equal("tenant-metadata"))
|
||||
Expect(currentlabels["custom-label"]).To(Equal("test"))
|
||||
})
|
||||
By("Disallow name overwritte", func() {
|
||||
tnt.Labels["kubernetes.io/metadata.name"] = "evil"
|
||||
Expect(k8sClient.Update(context.TODO(), tnt)).ShouldNot(Succeed())
|
||||
})
|
||||
|
||||
})
|
||||
})
|
||||
@@ -225,7 +225,7 @@ func main() {
|
||||
route.Service(service.Handler()),
|
||||
route.TenantResourceObjects(utils.InCapsuleGroups(cfg, tntresource.WriteOpsHandler())),
|
||||
route.NetworkPolicy(utils.InCapsuleGroups(cfg, networkpolicy.Handler())),
|
||||
route.Tenant(tenant.NameHandler(), tenant.RoleBindingRegexHandler(), tenant.IngressClassRegexHandler(), tenant.StorageClassRegexHandler(), tenant.ContainerRegistryRegexHandler(), tenant.HostnameRegexHandler(), tenant.FreezedEmitter(), tenant.ServiceAccountNameHandler(), tenant.ForbiddenAnnotationsRegexHandler(), tenant.ProtectedHandler()),
|
||||
route.Tenant(tenant.NameHandler(), tenant.RoleBindingRegexHandler(), tenant.IngressClassRegexHandler(), tenant.StorageClassRegexHandler(), tenant.ContainerRegistryRegexHandler(), tenant.HostnameRegexHandler(), tenant.FreezedEmitter(), tenant.ServiceAccountNameHandler(), tenant.ForbiddenAnnotationsRegexHandler(), tenant.ProtectedHandler(), tenant.MetaHandler()),
|
||||
route.OwnerReference(utils.InCapsuleGroups(cfg, ownerreference.Handler(cfg))),
|
||||
route.Cordoning(tenant.CordoningHandler(cfg), tenant.ResourceCounterHandler(manager.GetClient())),
|
||||
route.Node(utils.InCapsuleGroups(cfg, node.UserMetadataHandler(cfg, kubeVersion))),
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright 2020-2023 Project Capsule Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package api
|
||||
|
||||
const (
|
||||
TenantNameLabel = "kubernetes.io/metadata.name"
|
||||
)
|
||||
@@ -0,0 +1,57 @@
|
||||
// Copyright 2020-2023 Project Capsule Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package tenant
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/client-go/tools/record"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
|
||||
|
||||
capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2"
|
||||
capsuleapi "github.com/projectcapsule/capsule/pkg/api"
|
||||
capsulewebhook "github.com/projectcapsule/capsule/pkg/webhook"
|
||||
"github.com/projectcapsule/capsule/pkg/webhook/utils"
|
||||
)
|
||||
|
||||
type metaHandler struct{}
|
||||
|
||||
func MetaHandler() capsulewebhook.Handler {
|
||||
return &metaHandler{}
|
||||
}
|
||||
|
||||
func (h *metaHandler) OnCreate(_ client.Client, decoder *admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
|
||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (h *metaHandler) OnDelete(client.Client, *admission.Decoder, record.EventRecorder) capsulewebhook.Func {
|
||||
return func(context.Context, admission.Request) *admission.Response {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (h *metaHandler) OnUpdate(_ client.Client, decoder *admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
|
||||
return func(ctx context.Context, req admission.Request) *admission.Response {
|
||||
tenant := &capsulev1beta2.Tenant{}
|
||||
if err := decoder.Decode(req, tenant); err != nil {
|
||||
return utils.ErroredResponse(err)
|
||||
}
|
||||
|
||||
if tenant.Labels != nil {
|
||||
if tenant.Labels[capsuleapi.TenantNameLabel] != "" {
|
||||
if tenant.Labels[capsuleapi.TenantNameLabel] != tenant.Name {
|
||||
response := admission.Denied(fmt.Sprintf("tenant label '%s' is immutable", capsuleapi.TenantNameLabel))
|
||||
|
||||
return &response
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user