refactor(api): switching to v1beta2 as storage version

This commit is contained in:
Dario Tranchitella
2022-12-23 10:23:29 +01:00
parent 2cb37abc51
commit 43bd2491ae
60 changed files with 344 additions and 373 deletions

12
pkg/api/annotations.go Normal file
View File

@@ -0,0 +1,12 @@
// Copyright 2020-2021 Clastix Labs
// SPDX-License-Identifier: Apache-2.0
package api
const (
ForbiddenNamespaceLabelsAnnotation = "capsule.clastix.io/forbidden-namespace-labels"
ForbiddenNamespaceLabelsRegexpAnnotation = "capsule.clastix.io/forbidden-namespace-labels-regexp"
ForbiddenNamespaceAnnotationsAnnotation = "capsule.clastix.io/forbidden-namespace-annotations"
ForbiddenNamespaceAnnotationsRegexpAnnotation = "capsule.clastix.io/forbidden-namespace-annotations-regexp"
ProtectedTenantAnnotation = "capsule.clastix.io/protected"
)

View File

@@ -6,32 +6,30 @@ package configuration
import (
"context"
"regexp"
"strconv"
"strings"
"github.com/pkg/errors"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
capsulev1alpha1 "github.com/clastix/capsule/api/v1alpha1"
capsulev1beta1 "github.com/clastix/capsule/pkg/api"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
capsuleapi "github.com/clastix/capsule/pkg/api"
)
// capsuleConfiguration is the Capsule Configuration retrieval mode
// using a closure that provides the desired configuration.
type capsuleConfiguration struct {
retrievalFn func() *capsulev1alpha1.CapsuleConfiguration
retrievalFn func() *capsulev1beta2.CapsuleConfiguration
}
func NewCapsuleConfiguration(ctx context.Context, client client.Client, name string) Configuration {
return &capsuleConfiguration{retrievalFn: func() *capsulev1alpha1.CapsuleConfiguration {
config := &capsulev1alpha1.CapsuleConfiguration{}
return &capsuleConfiguration{retrievalFn: func() *capsulev1beta2.CapsuleConfiguration {
config := &capsulev1beta2.CapsuleConfiguration{}
if err := client.Get(ctx, types.NamespacedName{Name: name}, config); err != nil {
if apierrors.IsNotFound(err) {
return &capsulev1alpha1.CapsuleConfiguration{
Spec: capsulev1alpha1.CapsuleConfigurationSpec{
return &capsulev1beta2.CapsuleConfiguration{
Spec: capsulev1beta2.CapsuleConfigurationSpec{
UserGroups: []string{"capsule.clastix.io"},
ForceTenantPrefix: false,
ProtectedNamespaceRegexpString: "",
@@ -45,7 +43,7 @@ func NewCapsuleConfiguration(ctx context.Context, client client.Client, name str
}}
}
func (c capsuleConfiguration) ProtectedNamespaceRegexp() (*regexp.Regexp, error) {
func (c *capsuleConfiguration) ProtectedNamespaceRegexp() (*regexp.Regexp, error) {
expr := c.retrievalFn().Spec.ProtectedNamespaceRegexpString
if len(expr) == 0 {
return nil, nil // nolint:nilnil
@@ -59,120 +57,46 @@ func (c capsuleConfiguration) ProtectedNamespaceRegexp() (*regexp.Regexp, error)
return r, nil
}
func (c capsuleConfiguration) ForceTenantPrefix() bool {
func (c *capsuleConfiguration) ForceTenantPrefix() bool {
return c.retrievalFn().Spec.ForceTenantPrefix
}
func (c capsuleConfiguration) TLSSecretName() (name string) {
name = TLSSecretName
if c.retrievalFn().Annotations == nil {
return
}
v, ok := c.retrievalFn().Annotations[capsulev1alpha1.TLSSecretNameAnnotation]
if ok {
return v
}
return
func (c *capsuleConfiguration) TLSSecretName() (name string) {
return c.retrievalFn().Spec.CapsuleResources.TLSSecretName
}
func (c capsuleConfiguration) EnableTLSConfiguration() bool {
annotationValue, ok := c.retrievalFn().Annotations[capsulev1alpha1.EnableTLSConfigurationAnnotationName]
if ok {
value, err := strconv.ParseBool(annotationValue)
if err != nil {
return false
}
return value
}
return false
func (c *capsuleConfiguration) EnableTLSConfiguration() bool {
return c.retrievalFn().Spec.EnableTLSReconciler
}
func (c capsuleConfiguration) MutatingWebhookConfigurationName() (name string) {
name = MutatingWebhookConfigurationName
if c.retrievalFn().Annotations == nil {
return
}
v, ok := c.retrievalFn().Annotations[capsulev1alpha1.MutatingWebhookConfigurationName]
if ok {
return v
}
return
func (c *capsuleConfiguration) MutatingWebhookConfigurationName() (name string) {
return c.retrievalFn().Spec.CapsuleResources.MutatingWebhookConfigurationName
}
func (c capsuleConfiguration) TenantCRDName() string {
func (c *capsuleConfiguration) TenantCRDName() string {
return TenantCRDName
}
func (c capsuleConfiguration) ValidatingWebhookConfigurationName() (name string) {
name = ValidatingWebhookConfigurationName
if c.retrievalFn().Annotations == nil {
return
}
v, ok := c.retrievalFn().Annotations[capsulev1alpha1.ValidatingWebhookConfigurationName]
if ok {
return v
}
return
func (c *capsuleConfiguration) ValidatingWebhookConfigurationName() (name string) {
return c.retrievalFn().Spec.CapsuleResources.ValidatingWebhookConfigurationName
}
func (c capsuleConfiguration) UserGroups() []string {
func (c *capsuleConfiguration) UserGroups() []string {
return c.retrievalFn().Spec.UserGroups
}
func (c capsuleConfiguration) hasForbiddenNodeLabelsAnnotations() bool {
if _, ok := c.retrievalFn().Annotations[capsulev1alpha1.ForbiddenNodeLabelsAnnotation]; ok {
return true
}
if _, ok := c.retrievalFn().Annotations[capsulev1alpha1.ForbiddenNodeLabelsRegexpAnnotation]; ok {
return true
}
return false
}
func (c capsuleConfiguration) hasForbiddenNodeAnnotationsAnnotations() bool {
if _, ok := c.retrievalFn().Annotations[capsulev1alpha1.ForbiddenNodeAnnotationsAnnotation]; ok {
return true
}
if _, ok := c.retrievalFn().Annotations[capsulev1alpha1.ForbiddenNodeAnnotationsRegexpAnnotation]; ok {
return true
}
return false
}
func (c *capsuleConfiguration) ForbiddenUserNodeLabels() *capsulev1beta1.ForbiddenListSpec {
if !c.hasForbiddenNodeLabelsAnnotations() {
func (c *capsuleConfiguration) ForbiddenUserNodeLabels() *capsuleapi.ForbiddenListSpec {
if c.retrievalFn().Spec.NodeMetadata == nil {
return nil
}
return &capsulev1beta1.ForbiddenListSpec{
Exact: strings.Split(c.retrievalFn().Annotations[capsulev1alpha1.ForbiddenNodeLabelsAnnotation], ","),
Regex: c.retrievalFn().Annotations[capsulev1alpha1.ForbiddenNodeLabelsRegexpAnnotation],
}
return &c.retrievalFn().Spec.NodeMetadata.ForbiddenLabels
}
func (c *capsuleConfiguration) ForbiddenUserNodeAnnotations() *capsulev1beta1.ForbiddenListSpec {
if !c.hasForbiddenNodeAnnotationsAnnotations() {
func (c *capsuleConfiguration) ForbiddenUserNodeAnnotations() *capsuleapi.ForbiddenListSpec {
if c.retrievalFn().Spec.NodeMetadata == nil {
return nil
}
return &capsulev1beta1.ForbiddenListSpec{
Exact: strings.Split(c.retrievalFn().Annotations[capsulev1alpha1.ForbiddenNodeAnnotationsAnnotation], ","),
Regex: c.retrievalFn().Annotations[capsulev1alpha1.ForbiddenNodeAnnotationsRegexpAnnotation],
}
return &c.retrievalFn().Spec.NodeMetadata.ForbiddenAnnotations
}

View File

@@ -6,14 +6,11 @@ package configuration
import (
"regexp"
capsulev1beta1 "github.com/clastix/capsule/pkg/api"
capsuleapi "github.com/clastix/capsule/pkg/api"
)
const (
TLSSecretName = "capsule-tls"
MutatingWebhookConfigurationName = "capsule-mutating-webhook-configuration"
ValidatingWebhookConfigurationName = "capsule-validating-webhook-configuration"
TenantCRDName = "tenants.capsule.clastix.io"
TenantCRDName = "tenants.capsule.clastix.io"
)
type Configuration interface {
@@ -27,6 +24,6 @@ type Configuration interface {
ValidatingWebhookConfigurationName() string
TenantCRDName() string
UserGroups() []string
ForbiddenUserNodeLabels() *capsulev1beta1.ForbiddenListSpec
ForbiddenUserNodeAnnotations() *capsulev1beta1.ForbiddenListSpec
ForbiddenUserNodeLabels() *capsuleapi.ForbiddenListSpec
ForbiddenUserNodeAnnotations() *capsuleapi.ForbiddenListSpec
}

View File

@@ -16,7 +16,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/manager"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
"github.com/clastix/capsule/pkg/indexer/ingress"
"github.com/clastix/capsule/pkg/indexer/namespace"
@@ -31,7 +30,6 @@ type CustomIndexer interface {
func AddToManager(ctx context.Context, log logr.Logger, mgr manager.Manager) error {
indexers := []CustomIndexer{
tenant.NamespacesReference{Obj: &capsulev1beta1.Tenant{}},
tenant.NamespacesReference{Obj: &capsulev1beta2.Tenant{}},
tenant.OwnerReference{},
namespace.OwnerReference{},

View File

@@ -9,7 +9,7 @@ import (
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
)
type OwnerReference struct{}
@@ -32,7 +32,7 @@ func (o OwnerReference) Func() client.IndexerFunc {
}
for _, or := range ns.OwnerReferences {
if or.APIVersion == capsulev1beta1.GroupVersion.String() {
if or.APIVersion == capsulev1beta2.GroupVersion.String() {
res = append(res, or.Name)
}
}

View File

@@ -8,14 +8,14 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
"github.com/clastix/capsule/pkg/utils"
)
type OwnerReference struct{}
func (o OwnerReference) Object() client.Object {
return &capsulev1beta1.Tenant{}
return &capsulev1beta2.Tenant{}
}
func (o OwnerReference) Field() string {
@@ -24,9 +24,9 @@ func (o OwnerReference) Field() string {
func (o OwnerReference) Func() client.IndexerFunc {
return func(object client.Object) []string {
tenant, ok := object.(*capsulev1beta1.Tenant)
tenant, ok := object.(*capsulev1beta2.Tenant)
if !ok {
panic(fmt.Errorf("expected type *capsulev1beta1.Tenant, got %T", tenant))
panic(fmt.Errorf("expected type *capsulev1beta2.Tenant, got %T", tenant))
}
return utils.GetOwnersWithKinds(tenant)

View File

@@ -8,14 +8,14 @@ import (
"sort"
"strings"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
)
const (
NodeSelectorAnnotation = "scheduler.alpha.kubernetes.io/node-selector"
)
func BuildNodeSelector(tnt *capsulev1beta1.Tenant, nsAnnotations map[string]string) map[string]string {
func BuildNodeSelector(tnt *capsulev1beta2.Tenant, nsAnnotations map[string]string) map[string]string {
if nsAnnotations == nil {
nsAnnotations = make(map[string]string)
}

View File

@@ -6,10 +6,10 @@ package utils
import (
"fmt"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
)
func GetOwnersWithKinds(tenant *capsulev1beta1.Tenant) (owners []string) {
func GetOwnersWithKinds(tenant *capsulev1beta2.Tenant) (owners []string) {
for _, owner := range tenant.Spec.Owners {
owners = append(owners, fmt.Sprintf("%s:%s", owner.Kind.String(), owner.Name))
}

View File

@@ -14,11 +14,11 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
)
func tenantFromIngress(ctx context.Context, c client.Client, ingress Ingress) (*capsulev1beta1.Tenant, error) {
tenantList := &capsulev1beta1.TenantList{}
func tenantFromIngress(ctx context.Context, c client.Client, ingress Ingress) (*capsulev1beta2.Tenant, error) {
tenantList := &capsulev1beta2.TenantList{}
if err := c.List(ctx, tenantList, client.MatchingFieldsSelector{
Selector: fields.OneTermEqualSelector(".status.namespaces", ingress.Namespace()),
}); err != nil {

View File

@@ -12,7 +12,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
"github.com/clastix/capsule/pkg/configuration"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
@@ -34,7 +34,7 @@ func (r *class) OnCreate(client client.Client, decoder *admission.Decoder, recor
return utils.ErroredResponse(err)
}
var tenant *capsulev1beta1.Tenant
var tenant *capsulev1beta2.Tenant
tenant, err = tenantFromIngress(ctx, client, ingress)
if err != nil {
@@ -75,7 +75,7 @@ func (r *class) OnUpdate(client client.Client, decoder *admission.Decoder, recor
return utils.ErroredResponse(err)
}
var tenant *capsulev1beta1.Tenant
var tenant *capsulev1beta2.Tenant
tenant, err = tenantFromIngress(ctx, client, ingress)
if err != nil {
@@ -114,7 +114,7 @@ func (r *class) OnDelete(client.Client, *admission.Decoder, record.EventRecorder
}
}
func (r *class) validateClass(tenant capsulev1beta1.Tenant, ingressClass *string) error {
func (r *class) validateClass(tenant capsulev1beta2.Tenant, ingressClass *string) error {
if tenant.Spec.IngressOptions.AllowedClasses == nil {
return nil
}

View File

@@ -18,7 +18,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
"github.com/clastix/capsule/pkg/api"
"github.com/clastix/capsule/pkg/configuration"
"github.com/clastix/capsule/pkg/indexer/ingress"
@@ -42,7 +42,7 @@ func (r *collision) OnCreate(client client.Client, decoder *admission.Decoder, r
return utils.ErroredResponse(err)
}
var tenant *capsulev1beta1.Tenant
var tenant *capsulev1beta2.Tenant
tenant, err = tenantFromIngress(ctx, client, ing)
if err != nil {
@@ -77,7 +77,7 @@ func (r *collision) OnUpdate(client client.Client, decoder *admission.Decoder, r
return utils.ErroredResponse(err)
}
var tenant *capsulev1beta1.Tenant
var tenant *capsulev1beta2.Tenant
tenant, err = tenantFromIngress(ctx, client, ing)
if err != nil {
@@ -129,7 +129,7 @@ func (r *collision) validateCollision(ctx context.Context, clt client.Client, in
// nolint:exhaustive
switch scope {
case api.HostnameCollisionScopeCluster:
tenantList := &capsulev1beta1.TenantList{}
tenantList := &capsulev1beta2.TenantList{}
if err := clt.List(ctx, tenantList); err != nil {
return err
}
@@ -140,7 +140,7 @@ func (r *collision) validateCollision(ctx context.Context, clt client.Client, in
case api.HostnameCollisionScopeTenant:
selector := client.MatchingFieldsSelector{Selector: fields.OneTermEqualSelector(".status.namespaces", ing.Namespace())}
tenantList := &capsulev1beta1.TenantList{}
tenantList := &capsulev1beta2.TenantList{}
if err := clt.List(ctx, tenantList, selector); err != nil {
return err
}

View File

@@ -14,7 +14,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
"github.com/clastix/capsule/pkg/configuration"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
@@ -35,7 +35,7 @@ func (r *hostnames) OnCreate(c client.Client, decoder *admission.Decoder, record
return utils.ErroredResponse(err)
}
var tenant *capsulev1beta1.Tenant
var tenant *capsulev1beta2.Tenant
tenant, err = tenantFromIngress(ctx, c, ingress)
if err != nil {
@@ -76,7 +76,7 @@ func (r *hostnames) OnUpdate(c client.Client, decoder *admission.Decoder, record
return utils.ErroredResponse(err)
}
var tenant *capsulev1beta1.Tenant
var tenant *capsulev1beta2.Tenant
tenant, err = tenantFromIngress(ctx, c, ingress)
if err != nil {
@@ -116,7 +116,7 @@ func (r *hostnames) OnDelete(client.Client, *admission.Decoder, record.EventReco
}
}
func (r *hostnames) validateHostnames(tenant capsulev1beta1.Tenant, hostnames sets.String) error {
func (r *hostnames) validateHostnames(tenant capsulev1beta2.Tenant, hostnames sets.String) error {
if tenant.Spec.IngressOptions.AllowedHostnames == nil {
return nil
}

View File

@@ -14,7 +14,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
)
@@ -44,7 +44,7 @@ func (h *wildcard) OnUpdate(client client.Client, decoder *admission.Decoder, re
}
func (h *wildcard) wildcardHandler(ctx context.Context, clt client.Client, req admission.Request, recorder record.EventRecorder, decoder *admission.Decoder) *admission.Response {
tntList := &capsulev1beta1.TenantList{}
tntList := &capsulev1beta2.TenantList{}
if err := clt.List(ctx, tntList, client.MatchingFieldsSelector{
Selector: fields.OneTermEqualSelector(".status.namespaces", req.Namespace),
@@ -59,8 +59,7 @@ func (h *wildcard) wildcardHandler(ctx context.Context, clt client.Client, req a
tnt := tntList.Items[0]
// Check if Annotation in manifest has value "capsule.clastix.io/deny-wildcard" set to "true".
if tnt.IsWildcardDenied() {
if !tnt.Spec.IngressOptions.AllowWildcardHostnames {
// Retrieve ingress resource from request.
ingress, err := ingressFromRequest(req, decoder)
if err != nil {

View File

@@ -7,11 +7,11 @@ import (
"fmt"
"strings"
capsulev1beta1 "github.com/clastix/capsule/pkg/api"
capsuleapi "github.com/clastix/capsule/pkg/api"
)
// nolint:predeclared
func appendForbiddenError(spec *capsulev1beta1.ForbiddenListSpec) (append string) {
func appendForbiddenError(spec *capsuleapi.ForbiddenListSpec) (append string) {
append += "Forbidden are "
if len(spec.Exact) > 0 {
append += fmt.Sprintf("one of the following (%s)", strings.Join(spec.Exact, ", "))
@@ -39,10 +39,10 @@ func (namespaceQuotaExceededError) Error() string {
type namespaceLabelForbiddenError struct {
label string
spec *capsulev1beta1.ForbiddenListSpec
spec *capsuleapi.ForbiddenListSpec
}
func NewNamespaceLabelForbiddenError(label string, forbiddenSpec *capsulev1beta1.ForbiddenListSpec) error {
func NewNamespaceLabelForbiddenError(label string, forbiddenSpec *capsuleapi.ForbiddenListSpec) error {
return &namespaceLabelForbiddenError{
label: label,
spec: forbiddenSpec,
@@ -55,10 +55,10 @@ func (f namespaceLabelForbiddenError) Error() string {
type namespaceAnnotationForbiddenError struct {
annotation string
spec *capsulev1beta1.ForbiddenListSpec
spec *capsuleapi.ForbiddenListSpec
}
func NewNamespaceAnnotationForbiddenError(annotation string, forbiddenSpec *capsulev1beta1.ForbiddenListSpec) error {
func NewNamespaceAnnotationForbiddenError(annotation string, forbiddenSpec *capsuleapi.ForbiddenListSpec) error {
return &namespaceAnnotationForbiddenError{
annotation: annotation,
spec: forbiddenSpec,

View File

@@ -13,7 +13,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
"github.com/clastix/capsule/pkg/configuration"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
@@ -36,12 +36,12 @@ func (r *freezedHandler) OnCreate(client client.Client, decoder *admission.Decod
for _, objectRef := range ns.ObjectMeta.OwnerReferences {
// retrieving the selected Tenant
tnt := &capsulev1beta1.Tenant{}
tnt := &capsulev1beta2.Tenant{}
if err := client.Get(ctx, types.NamespacedName{Name: objectRef.Name}, tnt); err != nil {
return utils.ErroredResponse(err)
}
if tnt.IsCordoned() {
if tnt.Spec.Cordoned {
recorder.Eventf(tnt, corev1.EventTypeWarning, "TenantFreezed", "Namespace %s cannot be attached, the current Tenant is freezed", ns.GetName())
response := admission.Denied("the selected Tenant is freezed")
@@ -56,7 +56,7 @@ func (r *freezedHandler) OnCreate(client client.Client, decoder *admission.Decod
func (r *freezedHandler) OnDelete(c client.Client, _ *admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
tntList := &capsulev1beta1.TenantList{}
tntList := &capsulev1beta2.TenantList{}
if err := c.List(ctx, tntList, client.MatchingFieldsSelector{
Selector: fields.OneTermEqualSelector(".status.namespaces", req.Name),
}); err != nil {
@@ -69,7 +69,7 @@ func (r *freezedHandler) OnDelete(c client.Client, _ *admission.Decoder, recorde
tnt := tntList.Items[0]
if tnt.IsCordoned() && utils.IsCapsuleUser(ctx, req, c, r.configuration.UserGroups()) {
if tnt.Spec.Cordoned && utils.IsCapsuleUser(ctx, req, c, r.configuration.UserGroups()) {
recorder.Eventf(&tnt, corev1.EventTypeWarning, "TenantFreezed", "Namespace %s cannot be deleted, the current Tenant is freezed", req.Name)
response := admission.Denied("the selected Tenant is freezed")
@@ -88,7 +88,7 @@ func (r *freezedHandler) OnUpdate(c client.Client, decoder *admission.Decoder, r
return utils.ErroredResponse(err)
}
tntList := &capsulev1beta1.TenantList{}
tntList := &capsulev1beta2.TenantList{}
if err := c.List(ctx, tntList, client.MatchingFieldsSelector{
Selector: fields.OneTermEqualSelector(".status.namespaces", ns.Name),
}); err != nil {
@@ -101,7 +101,7 @@ func (r *freezedHandler) OnUpdate(c client.Client, decoder *admission.Decoder, r
tnt := tntList.Items[0]
if tnt.IsCordoned() && utils.IsCapsuleUser(ctx, req, c, r.configuration.UserGroups()) {
if tnt.Spec.Cordoned && utils.IsCapsuleUser(ctx, req, c, r.configuration.UserGroups()) {
recorder.Eventf(&tnt, corev1.EventTypeWarning, "TenantFreezed", "Namespace %s cannot be updated, the current Tenant is freezed", ns.GetName())
response := admission.Denied("the selected Tenant is freezed")

View File

@@ -14,8 +14,8 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
utils2 "github.com/clastix/capsule/pkg/utils"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
capsuleutils "github.com/clastix/capsule/pkg/utils"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
)
@@ -47,7 +47,7 @@ func (r *patchHandler) OnUpdate(c client.Client, decoder *admission.Decoder, rec
}
// Get Tenant Label
ln, err := utils2.GetTypeLabel(&capsulev1beta1.Tenant{})
ln, err := capsuleutils.GetTypeLabel(&capsulev1beta2.Tenant{})
if err != nil {
response := admission.Errored(http.StatusBadRequest, err)
@@ -59,7 +59,7 @@ func (r *patchHandler) OnUpdate(c client.Client, decoder *admission.Decoder, rec
if label, ok := ns.ObjectMeta.Labels[ln]; ok {
// retrieving the selected Tenant
tnt := &capsulev1beta1.Tenant{}
tnt := &capsulev1beta2.Tenant{}
if err = c.Get(ctx, types.NamespacedName{Name: label}, tnt); err != nil {
response := admission.Errored(http.StatusBadRequest, err)

View File

@@ -14,7 +14,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
"github.com/clastix/capsule/pkg/configuration"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
@@ -46,7 +46,7 @@ func (r *prefixHandler) OnCreate(clt client.Client, decoder *admission.Decoder,
}
if r.configuration.ForceTenantPrefix() {
tnt := &capsulev1beta1.Tenant{}
tnt := &capsulev1beta2.Tenant{}
for _, or := range ns.ObjectMeta.OwnerReferences {
// retrieving the selected Tenant

View File

@@ -12,7 +12,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
)
@@ -32,7 +32,7 @@ func (r *quotaHandler) OnCreate(client client.Client, decoder *admission.Decoder
for _, objectRef := range ns.ObjectMeta.OwnerReferences {
// retrieving the selected Tenant
tnt := &capsulev1beta1.Tenant{}
tnt := &capsulev1beta2.Tenant{}
if err := client.Get(ctx, types.NamespacedName{Name: objectRef.Name}, tnt); err != nil {
return utils.ErroredResponse(err)
}

View File

@@ -13,7 +13,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
)
@@ -24,9 +24,9 @@ func UserMetadataHandler() capsulewebhook.Handler {
return &userMetadataHandler{}
}
func (r *userMetadataHandler) validateUserMetadata(tnt *capsulev1beta1.Tenant, recorder record.EventRecorder, labels map[string]string, annotations map[string]string) *admission.Response {
if tnt.ForbiddenUserNamespaceLabels() != nil {
forbiddenLabels := tnt.ForbiddenUserNamespaceLabels()
func (r *userMetadataHandler) validateUserMetadata(tnt *capsulev1beta2.Tenant, recorder record.EventRecorder, labels map[string]string, annotations map[string]string) *admission.Response {
if tnt.Spec.NamespaceOptions != nil {
forbiddenLabels := tnt.Spec.NamespaceOptions.ForbiddenLabels
for label := range labels {
var forbidden, matched bool
@@ -36,28 +36,30 @@ func (r *userMetadataHandler) validateUserMetadata(tnt *capsulev1beta1.Tenant, r
if forbidden || matched {
recorder.Eventf(tnt, corev1.EventTypeWarning, "ForbiddenNamespaceLabel", fmt.Sprintf("Label %s is forbidden for a namespaces of the current Tenant ", label))
response := admission.Denied(NewNamespaceLabelForbiddenError(label, forbiddenLabels).Error())
response := admission.Denied(NewNamespaceLabelForbiddenError(label, &forbiddenLabels).Error())
return &response
}
}
}
if tnt.ForbiddenUserNamespaceAnnotations() != nil {
forbiddenAnnotations := tnt.ForbiddenUserNamespaceLabels()
if tnt.Spec.NamespaceOptions == nil {
return nil
}
for annotation := range annotations {
var forbidden, matched bool
forbidden = forbiddenAnnotations.ExactMatch(annotation)
matched = forbiddenAnnotations.RegexMatch(annotation)
forbiddenAnnotations := tnt.Spec.NamespaceOptions.ForbiddenLabels
if forbidden || matched {
recorder.Eventf(tnt, corev1.EventTypeWarning, "ForbiddenNamespaceAnnotation", fmt.Sprintf("Annotation %s is forbidden for a namespaces of the current Tenant ", annotation))
for annotation := range annotations {
var forbidden, matched bool
forbidden = forbiddenAnnotations.ExactMatch(annotation)
matched = forbiddenAnnotations.RegexMatch(annotation)
response := admission.Denied(NewNamespaceAnnotationForbiddenError(annotation, forbiddenAnnotations).Error())
if forbidden || matched {
recorder.Eventf(tnt, corev1.EventTypeWarning, "ForbiddenNamespaceAnnotation", fmt.Sprintf("Annotation %s is forbidden for a namespaces of the current Tenant ", annotation))
return &response
}
response := admission.Denied(NewNamespaceAnnotationForbiddenError(annotation, &forbiddenAnnotations).Error())
return &response
}
}
@@ -71,7 +73,7 @@ func (r *userMetadataHandler) OnCreate(client client.Client, decoder *admission.
return utils.ErroredResponse(err)
}
tnt := &capsulev1beta1.Tenant{}
tnt := &capsulev1beta2.Tenant{}
for _, objectRef := range ns.ObjectMeta.OwnerReferences {
// retrieving the selected Tenant
if err := client.Get(ctx, types.NamespacedName{Name: objectRef.Name}, tnt); err != nil {
@@ -104,7 +106,7 @@ func (r *userMetadataHandler) OnUpdate(client client.Client, decoder *admission.
return utils.ErroredResponse(err)
}
tnt := &capsulev1beta1.Tenant{}
tnt := &capsulev1beta2.Tenant{}
for _, objectRef := range newNs.ObjectMeta.OwnerReferences {
// retrieving the selected Tenant
if err := client.Get(ctx, types.NamespacedName{Name: objectRef.Name}, tnt); err != nil {

View File

@@ -13,8 +13,8 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
utils2 "github.com/clastix/capsule/pkg/utils"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
capsuleutils "github.com/clastix/capsule/pkg/utils"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
)
@@ -31,7 +31,7 @@ func (r *handler) OnCreate(client.Client, *admission.Decoder, record.EventRecord
}
}
func (r *handler) generic(ctx context.Context, req admission.Request, client client.Client, _ *admission.Decoder) (*capsulev1beta1.Tenant, error) {
func (r *handler) generic(ctx context.Context, req admission.Request, client client.Client, _ *admission.Decoder) (*capsulev1beta2.Tenant, error) {
var err error
np := &networkingv1.NetworkPolicy{}
@@ -39,9 +39,9 @@ func (r *handler) generic(ctx context.Context, req admission.Request, client cli
return nil, err
}
tnt := &capsulev1beta1.Tenant{}
tnt := &capsulev1beta2.Tenant{}
l, _ := utils2.GetTypeLabel(&capsulev1beta1.Tenant{})
l, _ := capsuleutils.GetTypeLabel(&capsulev1beta2.Tenant{})
if v, ok := np.GetLabels()[l]; ok {
if err = client.Get(ctx, types.NamespacedName{Name: v}, tnt); err != nil {
return nil, err

View File

@@ -7,11 +7,11 @@ import (
"fmt"
"strings"
capsulev1beta1 "github.com/clastix/capsule/pkg/api"
capsulev1beta2 "github.com/clastix/capsule/pkg/api"
)
// nolint:predeclared
func appendForbiddenError(spec *capsulev1beta1.ForbiddenListSpec) (append string) {
func appendForbiddenError(spec *capsulev1beta2.ForbiddenListSpec) (append string) {
append += "Forbidden are "
if len(spec.Exact) > 0 {
append += fmt.Sprintf("one of the following (%s)", strings.Join(spec.Exact, ", "))
@@ -28,10 +28,10 @@ func appendForbiddenError(spec *capsulev1beta1.ForbiddenListSpec) (append string
}
type nodeLabelForbiddenError struct {
spec *capsulev1beta1.ForbiddenListSpec
spec *capsulev1beta2.ForbiddenListSpec
}
func NewNodeLabelForbiddenError(forbiddenSpec *capsulev1beta1.ForbiddenListSpec) error {
func NewNodeLabelForbiddenError(forbiddenSpec *capsulev1beta2.ForbiddenListSpec) error {
return &nodeLabelForbiddenError{
spec: forbiddenSpec,
}
@@ -42,10 +42,10 @@ func (f nodeLabelForbiddenError) Error() string {
}
type nodeAnnotationForbiddenError struct {
spec *capsulev1beta1.ForbiddenListSpec
spec *capsulev1beta2.ForbiddenListSpec
}
func NewNodeAnnotationForbiddenError(forbiddenSpec *capsulev1beta1.ForbiddenListSpec) error {
func NewNodeAnnotationForbiddenError(forbiddenSpec *capsulev1beta2.ForbiddenListSpec) error {
return &nodeAnnotationForbiddenError{
spec: forbiddenSpec,
}

View File

@@ -19,9 +19,9 @@ import (
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
"github.com/clastix/capsule/pkg/configuration"
utils2 "github.com/clastix/capsule/pkg/utils"
capsuleutils "github.com/clastix/capsule/pkg/utils"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
)
@@ -62,7 +62,7 @@ func (h *handler) setOwnerRef(ctx context.Context, req admission.Request, client
return &response
}
ln, err := utils2.GetTypeLabel(&capsulev1beta1.Tenant{})
ln, err := capsuleutils.GetTypeLabel(&capsulev1beta2.Tenant{})
if err != nil {
response := admission.Errored(http.StatusBadRequest, err)
@@ -71,7 +71,7 @@ func (h *handler) setOwnerRef(ctx context.Context, req admission.Request, client
// If we already had TenantName label on NS -> assign to it
if label, ok := ns.ObjectMeta.Labels[ln]; ok {
// retrieving the selected Tenant
tnt := &capsulev1beta1.Tenant{}
tnt := &capsulev1beta2.Tenant{}
if err = client.Get(ctx, types.NamespacedName{Name: label}, tnt); err != nil {
response := admission.Errored(http.StatusBadRequest, err)
@@ -96,7 +96,7 @@ func (h *handler) setOwnerRef(ctx context.Context, req admission.Request, client
// Find tenants belonging to user (it can be regular user or ServiceAccount)
if strings.HasPrefix(req.UserInfo.Username, "system:serviceaccount:") {
var tntList *capsulev1beta1.TenantList
var tntList *capsulev1beta2.TenantList
if tntList, err = h.listTenantsForOwnerKind(ctx, "ServiceAccount", req.UserInfo.Username, client); err != nil {
response := admission.Errored(http.StatusBadRequest, err)
@@ -108,7 +108,7 @@ func (h *handler) setOwnerRef(ctx context.Context, req admission.Request, client
tenants = append(tenants, tnt)
}
} else {
var tntList *capsulev1beta1.TenantList
var tntList *capsulev1beta2.TenantList
if tntList, err = h.listTenantsForOwnerKind(ctx, "User", req.UserInfo.Username, client); err != nil {
response := admission.Errored(http.StatusBadRequest, err)
@@ -170,9 +170,9 @@ func (h *handler) setOwnerRef(ctx context.Context, req admission.Request, client
return &response
}
func (h *handler) patchResponseForOwnerRef(tenant *capsulev1beta1.Tenant, ns *corev1.Namespace, recorder record.EventRecorder) admission.Response {
func (h *handler) patchResponseForOwnerRef(tenant *capsulev1beta2.Tenant, ns *corev1.Namespace, recorder record.EventRecorder) admission.Response {
scheme := runtime.NewScheme()
_ = capsulev1beta1.AddToScheme(scheme)
_ = capsulev1beta2.AddToScheme(scheme)
_ = corev1.AddToScheme(scheme)
o, err := json.Marshal(ns.DeepCopy())
@@ -196,8 +196,8 @@ func (h *handler) patchResponseForOwnerRef(tenant *capsulev1beta1.Tenant, ns *co
return admission.PatchResponseFromRaw(o, c)
}
func (h *handler) listTenantsForOwnerKind(ctx context.Context, ownerKind string, ownerName string, clt client.Client) (*capsulev1beta1.TenantList, error) {
tntList := &capsulev1beta1.TenantList{}
func (h *handler) listTenantsForOwnerKind(ctx context.Context, ownerKind string, ownerName string, clt client.Client) (*capsulev1beta2.TenantList, error) {
tntList := &capsulev1beta2.TenantList{}
fields := client.MatchingFields{
".spec.owner.ownerkind": fmt.Sprintf("%s:%s", ownerKind, ownerName),
}
@@ -206,7 +206,7 @@ func (h *handler) listTenantsForOwnerKind(ctx context.Context, ownerKind string,
return tntList, err
}
type sortedTenants []capsulev1beta1.Tenant
type sortedTenants []capsulev1beta2.Tenant
func (s sortedTenants) Len() int {
return len(s)

View File

@@ -12,7 +12,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
)
@@ -30,7 +30,7 @@ func (h *containerRegistryHandler) OnCreate(c client.Client, decoder *admission.
return utils.ErroredResponse(err)
}
tntList := &capsulev1beta1.TenantList{}
tntList := &capsulev1beta2.TenantList{}
if err := c.List(ctx, tntList, client.MatchingFieldsSelector{
Selector: fields.OneTermEqualSelector(".status.namespaces", pod.Namespace),
}); err != nil {

View File

@@ -12,7 +12,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
)
@@ -30,7 +30,7 @@ func (r *imagePullPolicy) OnCreate(c client.Client, decoder *admission.Decoder,
return utils.ErroredResponse(err)
}
tntList := &capsulev1beta1.TenantList{}
tntList := &capsulev1beta2.TenantList{}
if err := c.List(ctx, tntList, client.MatchingFieldsSelector{
Selector: fields.OneTermEqualSelector(".status.namespaces", pod.Namespace),
}); err != nil {

View File

@@ -6,7 +6,7 @@ package pod
import (
"strings"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
)
type PullPolicy interface {
@@ -32,7 +32,7 @@ func (i imagePullPolicyValidator) AllowedPullPolicies() []string {
return i.allowedPolicies
}
func NewPullPolicy(tenant *capsulev1beta1.Tenant) PullPolicy {
func NewPullPolicy(tenant *capsulev1beta2.Tenant) PullPolicy {
// the Tenant doesn't enforce the allowed image pull policy, returning nil
if len(tenant.Spec.ImagePullPolicies) == 0 {
return nil

View File

@@ -12,7 +12,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
)
@@ -30,7 +30,7 @@ func (h *priorityClass) OnCreate(c client.Client, decoder *admission.Decoder, re
return utils.ErroredResponse(err)
}
tntList := &capsulev1beta1.TenantList{}
tntList := &capsulev1beta2.TenantList{}
if err := c.List(ctx, tntList, client.MatchingFieldsSelector{
Selector: fields.OneTermEqualSelector(".status.namespaces", pod.Namespace),

View File

@@ -12,7 +12,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
)
@@ -32,7 +32,7 @@ func (h *handler) OnCreate(c client.Client, decoder *admission.Decoder, recorder
return utils.ErroredResponse(err)
}
tntList := &capsulev1beta1.TenantList{}
tntList := &capsulev1beta2.TenantList{}
if err := c.List(ctx, tntList, client.MatchingFieldsSelector{
Selector: fields.OneTermEqualSelector(".status.namespaces", pvc.Namespace),
}); err != nil {

View File

@@ -7,7 +7,7 @@ import (
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
)
// +kubebuilder:webhook:path=/tenants,mutating=false,sideEffects=None,admissionReviewVersions=v1,failurePolicy=fail,groups="capsule.clastix.io",resources=tenants,verbs=create;update;delete,versions=v1beta1,name=tenants.capsule.clastix.io
// +kubebuilder:webhook:path=/tenants,mutating=false,sideEffects=None,admissionReviewVersions=v1,failurePolicy=fail,groups="capsule.clastix.io",resources=tenants,verbs=create;update;delete,versions=v1beta2,name=tenants.capsule.clastix.io
type tenant struct {
handlers []capsulewebhook.Handler

View File

@@ -14,7 +14,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
)
@@ -31,7 +31,7 @@ func (r *handler) handleService(ctx context.Context, clt client.Client, decoder
return utils.ErroredResponse(err)
}
tntList := &capsulev1beta1.TenantList{}
tntList := &capsulev1beta2.TenantList{}
if err := clt.List(ctx, tntList, client.MatchingFieldsSelector{
Selector: fields.OneTermEqualSelector(".status.namespaces", svc.GetNamespace()),
}); err != nil {

View File

@@ -12,7 +12,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
)
@@ -24,7 +24,7 @@ func ContainerRegistryRegexHandler() capsulewebhook.Handler {
}
func (h *containerRegistryRegexHandler) validate(decoder *admission.Decoder, req admission.Request) *admission.Response {
tenant := &capsulev1beta1.Tenant{}
tenant := &capsulev1beta2.Tenant{}
if err := decoder.Decode(req, tenant); err != nil {
return utils.ErroredResponse(err)
}

View File

@@ -14,7 +14,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
"github.com/clastix/capsule/pkg/configuration"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
@@ -31,7 +31,7 @@ func CordoningHandler(configuration configuration.Configuration) capsulewebhook.
}
func (h *cordoningHandler) cordonHandler(ctx context.Context, clt client.Client, req admission.Request, recorder record.EventRecorder) *admission.Response {
tntList := &capsulev1beta1.TenantList{}
tntList := &capsulev1beta2.TenantList{}
if err := clt.List(ctx, tntList, client.MatchingFieldsSelector{
Selector: fields.OneTermEqualSelector(".status.namespaces", req.Namespace),
@@ -44,7 +44,7 @@ func (h *cordoningHandler) cordonHandler(ctx context.Context, clt client.Client,
}
tnt := tntList.Items[0]
if tnt.IsCordoned() && utils.IsCapsuleUser(ctx, req, clt, h.configuration.UserGroups()) {
if tnt.Spec.Cordoned && utils.IsCapsuleUser(ctx, req, clt, h.configuration.UserGroups()) {
recorder.Eventf(&tnt, corev1.EventTypeWarning, "TenantFreezed", "%s %s/%s cannot be %sd, current Tenant is freezed", req.Kind.String(), req.Namespace, req.Name, strings.ToLower(string(req.Operation)))
response := admission.Denied(fmt.Sprintf("tenant %s is freezed: please, reach out to the system administrator", tnt.GetName()))

View File

@@ -16,7 +16,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
)
@@ -36,7 +36,7 @@ func ResourceCounterHandler() capsulewebhook.Handler {
}
func (r *resourceCounterHandler) getTenantName(ctx context.Context, clt client.Client, req admission.Request) (string, error) {
tntList := &capsulev1beta1.TenantList{}
tntList := &capsulev1beta2.TenantList{}
if err := clt.List(ctx, tntList, client.MatchingFieldsSelector{
Selector: fields.OneTermEqualSelector(".status.namespaces", req.Namespace),
@@ -67,7 +67,7 @@ func (r *resourceCounterHandler) OnCreate(clt client.Client, decoder *admission.
kgv := fmt.Sprintf("%s.%s_%s", req.Resource.Resource, req.Resource.Group, req.Resource.Version)
tnt := &capsulev1beta1.Tenant{}
tnt := &capsulev1beta2.Tenant{}
var limit int64
@@ -76,20 +76,20 @@ func (r *resourceCounterHandler) OnCreate(clt client.Client, decoder *admission.
return retryErr
}
if limit, retryErr = capsulev1beta1.GetLimitResourceFromTenant(*tnt, kgv); retryErr != nil {
if errors.As(err, &capsulev1beta1.NonLimitedResourceError{}) {
if limit, retryErr = capsulev1beta2.GetLimitResourceFromTenant(*tnt, kgv); retryErr != nil {
if errors.As(err, &capsulev1beta2.NonLimitedResourceError{}) {
return nil
}
return err
}
used, _ := capsulev1beta1.GetUsedResourceFromTenant(*tnt, kgv)
used, _ := capsulev1beta2.GetUsedResourceFromTenant(*tnt, kgv)
if used >= limit {
return NewCustomResourceQuotaError(kgv, limit)
}
tnt.Annotations[capsulev1beta1.UsedAnnotationForResource(kgv)] = fmt.Sprintf("%d", used+1)
tnt.Annotations[capsulev1beta2.UsedAnnotationForResource(kgv)] = fmt.Sprintf("%d", used+1)
return clt.Update(ctx, tnt)
})
@@ -122,7 +122,7 @@ func (r *resourceCounterHandler) OnDelete(clt client.Client, decoder *admission.
kgv := fmt.Sprintf("%s.%s_%s", req.Resource.Resource, req.Resource.Group, req.Resource.Version)
err = retry.RetryOnConflict(retry.DefaultRetry, func() (retryErr error) {
tnt := &capsulev1beta1.Tenant{}
tnt := &capsulev1beta2.Tenant{}
if retryErr = clt.Get(ctx, types.NamespacedName{Name: tntName}, tnt); err != nil {
return
}
@@ -131,13 +131,13 @@ func (r *resourceCounterHandler) OnDelete(clt client.Client, decoder *admission.
return
}
if _, ok := tnt.Annotations[capsulev1beta1.UsedAnnotationForResource(kgv)]; !ok {
if _, ok := tnt.Annotations[capsulev1beta2.UsedAnnotationForResource(kgv)]; !ok {
return
}
used, _ := capsulev1beta1.GetUsedResourceFromTenant(*tnt, kgv)
used, _ := capsulev1beta2.GetUsedResourceFromTenant(*tnt, kgv)
tnt.Annotations[capsulev1beta1.UsedAnnotationForResource(kgv)] = fmt.Sprintf("%d", used-1)
tnt.Annotations[capsulev1beta2.UsedAnnotationForResource(kgv)] = fmt.Sprintf("%d", used-1)
return clt.Update(ctx, tnt)
})

View File

@@ -5,13 +5,14 @@ package tenant
import (
"context"
"fmt"
"regexp"
"k8s.io/client-go/tools/record"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
)
@@ -23,23 +24,23 @@ func ForbiddenAnnotationsRegexHandler() capsulewebhook.Handler {
}
func (h *forbiddenAnnotationsRegexHandler) validate(decoder *admission.Decoder, req admission.Request) *admission.Response {
tenant := &capsulev1beta1.Tenant{}
tenant := &capsulev1beta2.Tenant{}
if err := decoder.Decode(req, tenant); err != nil {
return utils.ErroredResponse(err)
}
if tenant.Annotations == nil {
if tenant.Spec.NamespaceOptions == nil {
return nil
}
annotationsToCheck := []string{
capsulev1beta1.ForbiddenNamespaceAnnotationsRegexpAnnotation,
capsulev1beta1.ForbiddenNamespaceLabelsRegexpAnnotation,
annotationsToCheck := map[string]string{
"labels": tenant.Spec.NamespaceOptions.ForbiddenLabels.Regex,
"annotations": tenant.Spec.NamespaceOptions.ForbiddenAnnotations.Regex,
}
for _, annotation := range annotationsToCheck {
if _, err := regexp.Compile(tenant.Annotations[annotation]); err != nil {
response := admission.Denied("unable to compile " + annotation + " regex annotation")
for scope, annotation := range annotationsToCheck {
if _, err := regexp.Compile(tenant.Spec.NamespaceOptions.ForbiddenLabels.Regex); err != nil {
response := admission.Denied(fmt.Sprintf("unable to compile %s regex for forbidden %s", annotation, scope))
return &response
}

View File

@@ -11,7 +11,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
)
@@ -36,20 +36,20 @@ func (h *freezedEmitterHandler) OnDelete(client.Client, *admission.Decoder, reco
func (h *freezedEmitterHandler) OnUpdate(_ client.Client, decoder *admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
oldTnt := &capsulev1beta1.Tenant{}
oldTnt := &capsulev1beta2.Tenant{}
if err := decoder.DecodeRaw(req.OldObject, oldTnt); err != nil {
return utils.ErroredResponse(err)
}
newTnt := &capsulev1beta1.Tenant{}
newTnt := &capsulev1beta2.Tenant{}
if err := decoder.Decode(req, newTnt); err != nil {
return utils.ErroredResponse(err)
}
switch {
case !oldTnt.IsCordoned() && newTnt.IsCordoned():
case !oldTnt.Spec.Cordoned && newTnt.Spec.Cordoned:
recorder.Eventf(newTnt, corev1.EventTypeNormal, "TenantCordoned", "Tenant has been cordoned")
case oldTnt.IsCordoned() && !newTnt.IsCordoned():
case oldTnt.Spec.Cordoned && !newTnt.Spec.Cordoned:
recorder.Eventf(newTnt, corev1.EventTypeNormal, "TenantUncordoned", "Tenant has been uncordoned")
}

View File

@@ -12,7 +12,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
)
@@ -24,7 +24,7 @@ func HostnameRegexHandler() capsulewebhook.Handler {
}
func (h *hostnameRegexHandler) validate(decoder *admission.Decoder, req admission.Request) *admission.Response {
tenant := &capsulev1beta1.Tenant{}
tenant := &capsulev1beta2.Tenant{}
if err := decoder.Decode(req, tenant); err != nil {
return utils.ErroredResponse(err)
}

View File

@@ -12,7 +12,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
)
@@ -24,7 +24,7 @@ func IngressClassRegexHandler() capsulewebhook.Handler {
}
func (h *ingressClassRegexHandler) validate(decoder *admission.Decoder, req admission.Request) *admission.Response {
tenant := &capsulev1beta1.Tenant{}
tenant := &capsulev1beta2.Tenant{}
if err := decoder.Decode(req, tenant); err != nil {
return utils.ErroredResponse(err)
}

View File

@@ -11,7 +11,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
)
@@ -24,7 +24,7 @@ func NameHandler() capsulewebhook.Handler {
func (h *nameHandler) OnCreate(_ client.Client, decoder *admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
tenant := &capsulev1beta1.Tenant{}
tenant := &capsulev1beta2.Tenant{}
if err := decoder.Decode(req, tenant); err != nil {
return utils.ErroredResponse(err)
}

View File

@@ -5,14 +5,13 @@ package tenant
import (
"context"
"fmt"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/record"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
)
@@ -31,14 +30,14 @@ func (h *protectedHandler) OnCreate(client.Client, *admission.Decoder, record.Ev
func (h *protectedHandler) OnDelete(clt client.Client, decoder *admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
tenant := &capsulev1beta1.Tenant{}
tenant := &capsulev1beta2.Tenant{}
if err := clt.Get(ctx, types.NamespacedName{Name: req.AdmissionRequest.Name}, tenant); err != nil {
return utils.ErroredResponse(err)
}
if _, protected := tenant.Annotations[capsulev1beta1.ProtectedTenantAnnotation]; protected {
response := admission.Denied(fmt.Sprintf("tenant is protected and cannot be deleted, remove %s annotation before proceeding", capsulev1beta1.ProtectedTenantAnnotation))
if tenant.Spec.PreventDeletion {
response := admission.Denied("tenant is protected and cannot be deleted")
return &response
}

View File

@@ -14,7 +14,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
)
@@ -26,7 +26,7 @@ func RoleBindingRegexHandler() capsulewebhook.Handler {
}
func (h *rbRegexHandler) validate(req admission.Request, decoder *admission.Decoder) *admission.Response {
tenant := &capsulev1beta1.Tenant{}
tenant := &capsulev1beta2.Tenant{}
if err := decoder.Decode(req, tenant); err != nil {
return utils.ErroredResponse(err)
}

View File

@@ -12,7 +12,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
)
@@ -24,7 +24,7 @@ func ServiceAccountNameHandler() capsulewebhook.Handler {
}
func (h *saNameHandler) validateServiceAccountName(req admission.Request, decoder *admission.Decoder) *admission.Response {
tenant := &capsulev1beta1.Tenant{}
tenant := &capsulev1beta2.Tenant{}
if err := decoder.Decode(req, tenant); err != nil {
return utils.ErroredResponse(err)
}

View File

@@ -12,7 +12,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
capsulewebhook "github.com/clastix/capsule/pkg/webhook"
"github.com/clastix/capsule/pkg/webhook/utils"
)
@@ -24,7 +24,7 @@ func StorageClassRegexHandler() capsulewebhook.Handler {
}
func (h *storageClassRegexHandler) validate(decoder *admission.Decoder, req admission.Request) *admission.Response {
tenant := &capsulev1beta1.Tenant{}
tenant := &capsulev1beta2.Tenant{}
if err := decoder.Decode(req, tenant); err != nil {
return utils.ErroredResponse(err)
}

View File

@@ -12,7 +12,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
"github.com/clastix/capsule/pkg/utils"
)
@@ -31,7 +31,7 @@ func IsCapsuleUser(ctx context.Context, req admission.Request, clt client.Client
targetNamespace := parts[2]
if len(targetNamespace) > 0 {
tl := &capsulev1beta1.TenantList{}
tl := &capsulev1beta2.TenantList{}
if err := clt.List(ctx, tl, client.MatchingFieldsSelector{Selector: fields.OneTermEqualSelector(".status.namespaces", targetNamespace)}); err != nil {
return false
}

View File

@@ -6,17 +6,17 @@ package utils
import (
authenticationv1 "k8s.io/api/authentication/v1"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
)
func IsTenantOwner(owners capsulev1beta1.OwnerListSpec, userInfo authenticationv1.UserInfo) bool {
func IsTenantOwner(owners capsulev1beta2.OwnerListSpec, userInfo authenticationv1.UserInfo) bool {
for _, owner := range owners {
switch owner.Kind {
case capsulev1beta1.UserOwner, capsulev1beta1.ServiceAccountOwner:
case capsulev1beta2.UserOwner, capsulev1beta2.ServiceAccountOwner:
if userInfo.Username == owner.Name {
return true
}
case capsulev1beta1.GroupOwner:
case capsulev1beta2.GroupOwner:
for _, group := range userInfo.Groups {
if group == owner.Name {
return true