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

View File

@@ -0,0 +1,21 @@
// Copyright 2020-2021 Clastix Labs
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
import (
"os"
ctrl "sigs.k8s.io/controller-runtime"
)
func (in *CapsuleConfiguration) SetupWebhookWithManager(mgr ctrl.Manager) error {
certData, _ := os.ReadFile("/tmp/k8s-webhook-server/serving-certs/tls.crt")
if len(certData) == 0 {
return nil
}
return ctrl.NewWebhookManagedBy(mgr).
For(in).
Complete()
}

View File

@@ -9,14 +9,6 @@ import (
corev1 "k8s.io/api/core/v1"
)
func (in *Tenant) IsCordoned() bool {
if v, ok := in.Labels["capsule.clastix.io/cordon"]; ok && v == "enabled" {
return true
}
return false
}
func (in *Tenant) IsFull() bool {
// we don't have limits on assigned Namespaces
if in.Spec.NamespaceQuota == nil {

View File

@@ -18,11 +18,11 @@ type NamespaceOptions struct {
}
func (in *Tenant) hasForbiddenNamespaceLabelsAnnotations() bool {
if _, ok := in.Annotations[ForbiddenNamespaceLabelsAnnotation]; ok {
if _, ok := in.Annotations[api.ForbiddenNamespaceLabelsAnnotation]; ok {
return true
}
if _, ok := in.Annotations[ForbiddenNamespaceLabelsRegexpAnnotation]; ok {
if _, ok := in.Annotations[api.ForbiddenNamespaceLabelsRegexpAnnotation]; ok {
return true
}
@@ -30,11 +30,11 @@ func (in *Tenant) hasForbiddenNamespaceLabelsAnnotations() bool {
}
func (in *Tenant) hasForbiddenNamespaceAnnotationsAnnotations() bool {
if _, ok := in.Annotations[ForbiddenNamespaceAnnotationsAnnotation]; ok {
if _, ok := in.Annotations[api.ForbiddenNamespaceAnnotationsAnnotation]; ok {
return true
}
if _, ok := in.Annotations[ForbiddenNamespaceAnnotationsRegexpAnnotation]; ok {
if _, ok := in.Annotations[api.ForbiddenNamespaceAnnotationsRegexpAnnotation]; ok {
return true
}
@@ -47,8 +47,8 @@ func (in *Tenant) ForbiddenUserNamespaceLabels() *api.ForbiddenListSpec {
}
return &api.ForbiddenListSpec{
Exact: strings.Split(in.Annotations[ForbiddenNamespaceLabelsAnnotation], ","),
Regex: in.Annotations[ForbiddenNamespaceLabelsRegexpAnnotation],
Exact: strings.Split(in.Annotations[api.ForbiddenNamespaceLabelsAnnotation], ","),
Regex: in.Annotations[api.ForbiddenNamespaceLabelsRegexpAnnotation],
}
}
@@ -58,7 +58,7 @@ func (in *Tenant) ForbiddenUserNamespaceAnnotations() *api.ForbiddenListSpec {
}
return &api.ForbiddenListSpec{
Exact: strings.Split(in.Annotations[ForbiddenNamespaceAnnotationsAnnotation], ","),
Regex: in.Annotations[ForbiddenNamespaceAnnotationsRegexpAnnotation],
Exact: strings.Split(in.Annotations[api.ForbiddenNamespaceAnnotationsAnnotation], ","),
Regex: in.Annotations[api.ForbiddenNamespaceAnnotationsRegexpAnnotation],
}
}

View File

@@ -0,0 +1,21 @@
// Copyright 2020-2021 Clastix Labs
// SPDX-License-Identifier: Apache-2.0
package v1beta1
import (
"os"
ctrl "sigs.k8s.io/controller-runtime"
)
func (in *Tenant) SetupWebhookWithManager(mgr ctrl.Manager) error {
certData, _ := os.ReadFile("/tmp/k8s-webhook-server/serving-certs/tls.crt")
if len(certData) == 0 {
return nil
}
return ctrl.NewWebhookManagedBy(mgr).
For(in).
Complete()
}

View File

@@ -22,10 +22,11 @@ type CapsuleConfigurationSpec struct {
ProtectedNamespaceRegexpString string `json:"protectedNamespaceRegex,omitempty"`
// Allows to set different name rather than the canonical one for the Capsule configuration objects,
// such as webhook secret or configurations.
CapsuleResources CapsuleResources `json:"overrides"`
// +kubebuilder:default={TLSSecretName:"capsule-tls",mutatingWebhookConfigurationName:"capsule-mutating-webhook-configuration",validatingWebhookConfigurationName:"capsule-validating-webhook-configuration"}
CapsuleResources CapsuleResources `json:"overrides,omitempty"`
// Allows to set the forbidden metadata for the worker nodes that could be patched by a Tenant.
// This applies only if the Tenant has an active NodeSelector, and the Owner have right to patch their nodes.
NodeMetadata *NodeMetadata `json:"nodeMetadata"`
NodeMetadata *NodeMetadata `json:"nodeMetadata,omitempty"`
// Toggles the TLS reconciler, the controller that is able to generate CA and certificates for the webhooks
// when not using an already provided CA and certificate, or when these are managed externally with Vault, or cert-manager.
// +kubebuilder:default=true

View File

@@ -0,0 +1,17 @@
// Copyright 2020-2021 Clastix Labs
// SPDX-License-Identifier: Apache-2.0
package v1beta2
import (
"fmt"
"strings"
)
func UsedQuotaFor(resource fmt.Stringer) string {
return "quota.capsule.clastix.io/used-" + strings.ReplaceAll(resource.String(), "/", "_")
}
func HardQuotaFor(resource fmt.Stringer) string {
return "quota.capsule.clastix.io/hard-" + strings.ReplaceAll(resource.String(), "/", "_")
}

View File

@@ -11,6 +11,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/conversion"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
"github.com/clastix/capsule/pkg/api"
)
func (in *Tenant) ConvertFrom(raw conversion.Hub) error {
@@ -58,28 +59,28 @@ func (in *Tenant) ConvertFrom(raw conversion.Hub) error {
in.Spec.NamespaceOptions.AdditionalMetadata = nsOpts.AdditionalMetadata
if value, found := annotations[capsulev1beta1.ForbiddenNamespaceLabelsAnnotation]; found {
if value, found := annotations[api.ForbiddenNamespaceLabelsAnnotation]; found {
in.Spec.NamespaceOptions.ForbiddenLabels.Exact = strings.Split(value, ",")
delete(annotations, capsulev1beta1.ForbiddenNamespaceLabelsAnnotation)
delete(annotations, api.ForbiddenNamespaceLabelsAnnotation)
}
if value, found := annotations[capsulev1beta1.ForbiddenNamespaceLabelsRegexpAnnotation]; found {
if value, found := annotations[api.ForbiddenNamespaceLabelsRegexpAnnotation]; found {
in.Spec.NamespaceOptions.ForbiddenLabels.Regex = value
delete(annotations, capsulev1beta1.ForbiddenNamespaceLabelsRegexpAnnotation)
delete(annotations, api.ForbiddenNamespaceLabelsRegexpAnnotation)
}
if value, found := annotations[capsulev1beta1.ForbiddenNamespaceAnnotationsAnnotation]; found {
if value, found := annotations[api.ForbiddenNamespaceAnnotationsAnnotation]; found {
in.Spec.NamespaceOptions.ForbiddenAnnotations.Exact = strings.Split(value, ",")
delete(annotations, capsulev1beta1.ForbiddenNamespaceAnnotationsAnnotation)
delete(annotations, api.ForbiddenNamespaceAnnotationsAnnotation)
}
if value, found := annotations[capsulev1beta1.ForbiddenNamespaceAnnotationsRegexpAnnotation]; found {
if value, found := annotations[api.ForbiddenNamespaceAnnotationsRegexpAnnotation]; found {
in.Spec.NamespaceOptions.ForbiddenAnnotations.Regex = value
delete(annotations, capsulev1beta1.ForbiddenNamespaceAnnotationsRegexpAnnotation)
delete(annotations, api.ForbiddenNamespaceAnnotationsRegexpAnnotation)
}
}
@@ -126,10 +127,10 @@ func (in *Tenant) ConvertFrom(raw conversion.Hub) error {
in.Spec.Cordoned = value
}
if _, found := annotations[capsulev1beta1.ProtectedTenantAnnotation]; found {
if _, found := annotations[api.ProtectedTenantAnnotation]; found {
in.Spec.PreventDeletion = true
delete(annotations, capsulev1beta1.ProtectedTenantAnnotation)
delete(annotations, api.ProtectedTenantAnnotation)
}
in.SetAnnotations(annotations)
@@ -189,19 +190,19 @@ func (in *Tenant) ConvertTo(raw conversion.Hub) error {
dst.Spec.NamespaceOptions.AdditionalMetadata = nsOpts.AdditionalMetadata
if exact := nsOpts.ForbiddenAnnotations.Exact; len(exact) > 0 {
annotations[capsulev1beta1.ForbiddenNamespaceAnnotationsAnnotation] = strings.Join(exact, ",")
annotations[api.ForbiddenNamespaceAnnotationsAnnotation] = strings.Join(exact, ",")
}
if regex := nsOpts.ForbiddenAnnotations.Regex; len(regex) > 0 {
annotations[capsulev1beta1.ForbiddenNamespaceAnnotationsRegexpAnnotation] = regex
annotations[api.ForbiddenNamespaceAnnotationsRegexpAnnotation] = regex
}
if exact := nsOpts.ForbiddenLabels.Exact; len(exact) > 0 {
annotations[capsulev1beta1.ForbiddenNamespaceLabelsAnnotation] = strings.Join(exact, ",")
annotations[api.ForbiddenNamespaceLabelsAnnotation] = strings.Join(exact, ",")
}
if regex := nsOpts.ForbiddenLabels.Regex; len(regex) > 0 {
annotations[capsulev1beta1.ForbiddenNamespaceLabelsRegexpAnnotation] = regex
annotations[api.ForbiddenNamespaceLabelsRegexpAnnotation] = regex
}
}
@@ -233,7 +234,7 @@ func (in *Tenant) ConvertTo(raw conversion.Hub) error {
dst.Spec.PriorityClasses = in.Spec.PriorityClasses
if in.Spec.PreventDeletion {
annotations[capsulev1beta1.ProtectedTenantAnnotation] = "true" //nolint:goconst
annotations[api.ProtectedTenantAnnotation] = "true" //nolint:goconst
}
if in.Spec.Cordoned {

View File

@@ -20,7 +20,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
"github.com/clastix/capsule/pkg/utils"
)
@@ -70,15 +70,15 @@ func (r *abstractServiceLabelsReconciler) Reconcile(ctx context.Context, request
return reconcile.Result{}, err
}
func (r *abstractServiceLabelsReconciler) getTenant(ctx context.Context, namespacedName types.NamespacedName, client client.Client) (*capsulev1beta1.Tenant, error) {
func (r *abstractServiceLabelsReconciler) getTenant(ctx context.Context, namespacedName types.NamespacedName, client client.Client) (*capsulev1beta2.Tenant, error) {
ns := &corev1.Namespace{}
tenant := &capsulev1beta1.Tenant{}
tenant := &capsulev1beta2.Tenant{}
if err := client.Get(ctx, types.NamespacedName{Name: namespacedName.Namespace}, ns); err != nil {
return nil, err
}
capsuleLabel, _ := utils.GetTypeLabel(&capsulev1beta1.Tenant{})
capsuleLabel, _ := utils.GetTypeLabel(&capsulev1beta2.Tenant{})
if _, ok := ns.GetLabels()[capsuleLabel]; !ok {
return nil, NewNonTenantObject(namespacedName.Name)
}
@@ -117,7 +117,7 @@ func (r *abstractServiceLabelsReconciler) forOptionPerInstanceName(ctx context.C
}
func (r *abstractServiceLabelsReconciler) IsNamespaceInTenant(ctx context.Context, namespace string) bool {
tl := &capsulev1beta1.TenantList{}
tl := &capsulev1beta2.TenantList{}
if err := r.client.List(ctx, tl, client.MatchingFieldsSelector{
Selector: fields.OneTermEqualSelector(".status.namespaces", namespace),
}); err != nil {

View File

@@ -13,13 +13,13 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
"github.com/clastix/capsule/pkg/utils"
)
// nolint:dupl
// Ensuring all the LimitRange are applied to each Namespace handled by the Tenant.
func (r *Manager) syncLimitRanges(ctx context.Context, tenant *capsulev1beta1.Tenant) error {
func (r *Manager) syncLimitRanges(ctx context.Context, tenant *capsulev1beta2.Tenant) error {
// getting requested LimitRange keys
keys := make([]string, 0, len(tenant.Spec.LimitRanges.Items))
@@ -40,11 +40,11 @@ func (r *Manager) syncLimitRanges(ctx context.Context, tenant *capsulev1beta1.Te
return group.Wait()
}
func (r *Manager) syncLimitRange(ctx context.Context, tenant *capsulev1beta1.Tenant, namespace string, keys []string) (err error) {
func (r *Manager) syncLimitRange(ctx context.Context, tenant *capsulev1beta2.Tenant, namespace string, keys []string) (err error) {
// getting LimitRange labels for the mutateFn
var tenantLabel, limitRangeLabel string
if tenantLabel, err = utils.GetTypeLabel(&capsulev1beta1.Tenant{}); err != nil {
if tenantLabel, err = utils.GetTypeLabel(&capsulev1beta2.Tenant{}); err != nil {
return err
}

View File

@@ -18,7 +18,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
)
type Manager struct {
@@ -30,7 +30,7 @@ type Manager struct {
func (r *Manager) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&capsulev1beta1.Tenant{}).
For(&capsulev1beta2.Tenant{}).
Owns(&corev1.Namespace{}).
Owns(&networkingv1.NetworkPolicy{}).
Owns(&corev1.LimitRange{}).
@@ -42,7 +42,7 @@ func (r *Manager) SetupWithManager(mgr ctrl.Manager) error {
func (r Manager) Reconcile(ctx context.Context, request ctrl.Request) (result ctrl.Result, err error) {
r.Log = r.Log.WithValues("Request.Name", request.Name)
// Fetch the Tenant instance
instance := &capsulev1beta1.Tenant{}
instance := &capsulev1beta2.Tenant{}
if err = r.Get(ctx, request.NamespacedName, instance); err != nil {
if apierrors.IsNotFound(err) {
r.Log.Info("Request object not found, could have been deleted after reconcile request")
@@ -130,12 +130,12 @@ func (r Manager) Reconcile(ctx context.Context, request ctrl.Request) (result ct
return ctrl.Result{}, err
}
func (r *Manager) updateTenantStatus(ctx context.Context, tnt *capsulev1beta1.Tenant) error {
func (r *Manager) updateTenantStatus(ctx context.Context, tnt *capsulev1beta2.Tenant) error {
return retry.RetryOnConflict(retry.DefaultBackoff, func() (err error) {
if tnt.IsCordoned() {
tnt.Status.State = capsulev1beta1.TenantStateCordoned
if tnt.Spec.Cordoned {
tnt.Status.State = capsulev1beta2.TenantStateCordoned
} else {
tnt.Status.State = capsulev1beta1.TenantStateActive
tnt.Status.State = capsulev1beta2.TenantStateActive
}
return r.Client.Status().Update(ctx, tnt)

View File

@@ -16,12 +16,13 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
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/utils"
)
// Ensuring all annotations are applied to each Namespace handled by the Tenant.
func (r *Manager) syncNamespaces(ctx context.Context, tenant *capsulev1beta1.Tenant) (err error) {
func (r *Manager) syncNamespaces(ctx context.Context, tenant *capsulev1beta2.Tenant) (err error) {
group := new(errgroup.Group)
for _, item := range tenant.Status.Namespaces {
@@ -42,7 +43,7 @@ func (r *Manager) syncNamespaces(ctx context.Context, tenant *capsulev1beta1.Ten
}
// nolint:gocognit
func (r *Manager) syncNamespaceMetadata(ctx context.Context, namespace string, tnt *capsulev1beta1.Tenant) (err error) {
func (r *Manager) syncNamespaceMetadata(ctx context.Context, namespace string, tnt *capsulev1beta2.Tenant) (err error) {
var res controllerutil.OperationResult
err = retry.RetryOnConflict(retry.DefaultBackoff, func() (conflictErr error) {
@@ -51,7 +52,7 @@ func (r *Manager) syncNamespaceMetadata(ctx context.Context, namespace string, t
return
}
capsuleLabel, _ := utils.GetTypeLabel(&capsulev1beta1.Tenant{})
capsuleLabel, _ := utils.GetTypeLabel(&capsulev1beta2.Tenant{})
res, conflictErr = controllerutil.CreateOrUpdate(ctx, r.Client, ns, func() error {
annotations := make(map[string]string)
@@ -103,20 +104,20 @@ func (r *Manager) syncNamespaceMetadata(ctx context.Context, namespace string, t
}
}
if value, ok := tnt.Annotations[capsulev1beta1.ForbiddenNamespaceLabelsAnnotation]; ok {
annotations[capsulev1beta1.ForbiddenNamespaceLabelsAnnotation] = value
if value, ok := tnt.Annotations[api.ForbiddenNamespaceLabelsAnnotation]; ok {
annotations[api.ForbiddenNamespaceLabelsAnnotation] = value
}
if value, ok := tnt.Annotations[capsulev1beta1.ForbiddenNamespaceLabelsRegexpAnnotation]; ok {
annotations[capsulev1beta1.ForbiddenNamespaceLabelsRegexpAnnotation] = value
if value, ok := tnt.Annotations[api.ForbiddenNamespaceLabelsRegexpAnnotation]; ok {
annotations[api.ForbiddenNamespaceLabelsRegexpAnnotation] = value
}
if value, ok := tnt.Annotations[capsulev1beta1.ForbiddenNamespaceAnnotationsAnnotation]; ok {
annotations[capsulev1beta1.ForbiddenNamespaceAnnotationsAnnotation] = value
if value, ok := tnt.Annotations[api.ForbiddenNamespaceAnnotationsAnnotation]; ok {
annotations[api.ForbiddenNamespaceAnnotationsAnnotation] = value
}
if value, ok := tnt.Annotations[capsulev1beta1.ForbiddenNamespaceAnnotationsRegexpAnnotation]; ok {
annotations[capsulev1beta1.ForbiddenNamespaceAnnotationsRegexpAnnotation] = value
if value, ok := tnt.Annotations[api.ForbiddenNamespaceAnnotationsRegexpAnnotation]; ok {
annotations[api.ForbiddenNamespaceAnnotationsRegexpAnnotation] = value
}
if ns.Annotations == nil {
@@ -146,11 +147,11 @@ func (r *Manager) syncNamespaceMetadata(ctx context.Context, namespace string, t
return err
}
func (r *Manager) ensureNamespaceCount(ctx context.Context, tenant *capsulev1beta1.Tenant) error {
func (r *Manager) ensureNamespaceCount(ctx context.Context, tenant *capsulev1beta2.Tenant) error {
return retry.RetryOnConflict(retry.DefaultBackoff, func() error {
tenant.Status.Size = uint(len(tenant.Status.Namespaces))
found := &capsulev1beta1.Tenant{}
found := &capsulev1beta2.Tenant{}
if err := r.Client.Get(ctx, types.NamespacedName{Name: tenant.GetName()}, found); err != nil {
return err
}
@@ -161,7 +162,7 @@ func (r *Manager) ensureNamespaceCount(ctx context.Context, tenant *capsulev1bet
})
}
func (r *Manager) collectNamespaces(ctx context.Context, tenant *capsulev1beta1.Tenant) error {
func (r *Manager) collectNamespaces(ctx context.Context, tenant *capsulev1beta2.Tenant) error {
return retry.RetryOnConflict(retry.DefaultBackoff, func() (err error) {
list := &corev1.NamespaceList{}
err = r.Client.List(ctx, list, client.MatchingFieldsSelector{

View File

@@ -13,13 +13,13 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
"github.com/clastix/capsule/pkg/utils"
)
// nolint:dupl
// Ensuring all the NetworkPolicies are applied to each Namespace handled by the Tenant.
func (r *Manager) syncNetworkPolicies(ctx context.Context, tenant *capsulev1beta1.Tenant) error {
func (r *Manager) syncNetworkPolicies(ctx context.Context, tenant *capsulev1beta2.Tenant) error {
// getting requested NetworkPolicy keys
keys := make([]string, 0, len(tenant.Spec.NetworkPolicies.Items))
@@ -40,14 +40,14 @@ func (r *Manager) syncNetworkPolicies(ctx context.Context, tenant *capsulev1beta
return group.Wait()
}
func (r *Manager) syncNetworkPolicy(ctx context.Context, tenant *capsulev1beta1.Tenant, namespace string, keys []string) (err error) {
func (r *Manager) syncNetworkPolicy(ctx context.Context, tenant *capsulev1beta2.Tenant, namespace string, keys []string) (err error) {
if err = r.pruningResources(ctx, namespace, keys, &networkingv1.NetworkPolicy{}); err != nil {
return err
}
// getting NetworkPolicy labels for the mutateFn
var tenantLabel, networkPolicyLabel string
if tenantLabel, err = utils.GetTypeLabel(&capsulev1beta1.Tenant{}); err != nil {
if tenantLabel, err = utils.GetTypeLabel(&capsulev1beta2.Tenant{}); err != nil {
return err
}

View File

@@ -19,7 +19,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
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/utils"
)
@@ -37,11 +37,11 @@ import (
//
// In case of Namespace-scoped Resource Budget, we're just replicating the resources across all registered Namespaces.
// nolint:gocognit
func (r *Manager) syncResourceQuotas(ctx context.Context, tenant *capsulev1beta1.Tenant) (err error) {
func (r *Manager) syncResourceQuotas(ctx context.Context, tenant *capsulev1beta2.Tenant) (err error) {
// getting ResourceQuota labels for the mutateFn
var tenantLabel, typeLabel string
if tenantLabel, err = utils.GetTypeLabel(&capsulev1beta1.Tenant{}); err != nil {
if tenantLabel, err = utils.GetTypeLabel(&capsulev1beta2.Tenant{}); err != nil {
return err
}
@@ -158,11 +158,11 @@ func (r *Manager) syncResourceQuotas(ctx context.Context, tenant *capsulev1beta1
return group.Wait()
}
func (r *Manager) syncResourceQuota(ctx context.Context, tenant *capsulev1beta1.Tenant, namespace string, keys []string) (err error) {
func (r *Manager) syncResourceQuota(ctx context.Context, tenant *capsulev1beta2.Tenant, namespace string, keys []string) (err error) {
// getting ResourceQuota labels for the mutateFn
var tenantLabel, typeLabel string
if tenantLabel, err = utils.GetTypeLabel(&capsulev1beta1.Tenant{}); err != nil {
if tenantLabel, err = utils.GetTypeLabel(&capsulev1beta2.Tenant{}); err != nil {
return err
}
@@ -238,8 +238,8 @@ func (r *Manager) resourceQuotasUpdate(ctx context.Context, resourceName corev1.
found.Annotations = make(map[string]string)
}
found.Labels = rq.Labels
found.Annotations[capsulev1beta1.UsedQuotaFor(resourceName)] = actual.String()
found.Annotations[capsulev1beta1.HardQuotaFor(resourceName)] = limit.String()
found.Annotations[capsulev1beta2.UsedQuotaFor(resourceName)] = actual.String()
found.Annotations[capsulev1beta2.HardQuotaFor(resourceName)] = limit.String()
// Updating the Resource according to the actual.Cmp result
found.Spec.Hard = rq.Spec.Hard

View File

@@ -16,10 +16,10 @@ import (
"k8s.io/client-go/dynamic"
"k8s.io/client-go/util/retry"
capsulev1beta1 "github.com/clastix/capsule/api/v1beta1"
capsulev1beta2 "github.com/clastix/capsule/api/v1beta2"
)
func (r *Manager) syncCustomResourceQuotaUsages(ctx context.Context, tenant *capsulev1beta1.Tenant) error {
func (r *Manager) syncCustomResourceQuotaUsages(ctx context.Context, tenant *capsulev1beta2.Tenant) error {
type resource struct {
kind string
group string
@@ -29,7 +29,7 @@ func (r *Manager) syncCustomResourceQuotaUsages(ctx context.Context, tenant *cap
var resourceList []resource
for k := range tenant.GetAnnotations() {
if !strings.HasPrefix(k, capsulev1beta1.ResourceQuotaAnnotationPrefix) {
if !strings.HasPrefix(k, capsulev1beta2.ResourceQuotaAnnotationPrefix) {
continue
}
@@ -69,7 +69,7 @@ func (r *Manager) syncCustomResourceQuotaUsages(ctx context.Context, tenant *cap
defer func() {
for gvk, used := range usedMap {
err := retry.RetryOnConflict(retry.DefaultBackoff, func() (retryErr error) {
tnt := &capsulev1beta1.Tenant{}
tnt := &capsulev1beta2.Tenant{}
if retryErr = r.Client.Get(ctx, types.NamespacedName{Name: tenant.GetName()}, tnt); retryErr != nil {
return
}
@@ -78,7 +78,7 @@ func (r *Manager) syncCustomResourceQuotaUsages(ctx context.Context, tenant *cap
tnt.Annotations = make(map[string]string)
}
tnt.Annotations[capsulev1beta1.UsedAnnotationForResource(gvk)] = fmt.Sprintf("%d", used)
tnt.Annotations[capsulev1beta2.UsedAnnotationForResource(gvk)] = fmt.Sprintf("%d", used)
return r.Client.Update(ctx, tnt)
})

View File

@@ -14,14 +14,14 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
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/utils"
)
// ownerClusterRoleBindings generates a Capsule AdditionalRoleBinding object for the Owner dynamic clusterrole in order
// to take advantage of the additional role binding feature.
func (r *Manager) ownerClusterRoleBindings(owner capsulev1beta1.OwnerSpec, clusterRole string) api.AdditionalRoleBindingsSpec {
func (r *Manager) ownerClusterRoleBindings(owner capsulev1beta2.OwnerSpec, clusterRole string) api.AdditionalRoleBindingsSpec {
var subject rbacv1.Subject
if owner.Kind == "ServiceAccount" {
@@ -50,7 +50,7 @@ func (r *Manager) ownerClusterRoleBindings(owner capsulev1beta1.OwnerSpec, clust
// Sync the dynamic Tenant Owner specific cluster-roles and additional Role Bindings, which can be used in many ways:
// applying Pod Security Policies or giving access to CRDs or specific API groups.
func (r *Manager) syncRoleBindings(ctx context.Context, tenant *capsulev1beta1.Tenant) (err error) {
func (r *Manager) syncRoleBindings(ctx context.Context, tenant *capsulev1beta2.Tenant) (err error) {
// hashing the RoleBinding name due to DNS RFC-1123 applied to Kubernetes labels
hashFn := func(binding api.AdditionalRoleBindingsSpec) string {
h := fnv.New64a()
@@ -66,8 +66,8 @@ func (r *Manager) syncRoleBindings(ctx context.Context, tenant *capsulev1beta1.T
// getting requested Role Binding keys
keys := make([]string, 0, len(tenant.Spec.Owners))
// Generating for dynamic tenant owners cluster roles
for index, owner := range tenant.Spec.Owners {
for _, clusterRoleName := range owner.GetRoles(*tenant, index) {
for _, owner := range tenant.Spec.Owners {
for _, clusterRoleName := range owner.ClusterRoles {
cr := r.ownerClusterRoleBindings(owner, clusterRoleName)
keys = append(keys, hashFn(cr))
@@ -91,10 +91,10 @@ func (r *Manager) syncRoleBindings(ctx context.Context, tenant *capsulev1beta1.T
return group.Wait()
}
func (r *Manager) syncAdditionalRoleBinding(ctx context.Context, tenant *capsulev1beta1.Tenant, ns string, keys []string, hashFn func(binding api.AdditionalRoleBindingsSpec) string) (err error) {
func (r *Manager) syncAdditionalRoleBinding(ctx context.Context, tenant *capsulev1beta2.Tenant, ns string, keys []string, hashFn func(binding api.AdditionalRoleBindingsSpec) string) (err error) {
var tenantLabel, roleBindingLabel string
if tenantLabel, err = utils.GetTypeLabel(&capsulev1beta1.Tenant{}); err != nil {
if tenantLabel, err = utils.GetTypeLabel(&capsulev1beta2.Tenant{}); err != nil {
return
}
@@ -108,8 +108,8 @@ func (r *Manager) syncAdditionalRoleBinding(ctx context.Context, tenant *capsule
var roleBindings []api.AdditionalRoleBindingsSpec
for index, owner := range tenant.Spec.Owners {
for _, clusterRoleName := range owner.GetRoles(*tenant, index) {
for _, owner := range tenant.Spec.Owners {
for _, clusterRoleName := range owner.ClusterRoles {
roleBindings = append(roleBindings, r.ownerClusterRoleBindings(owner, clusterRoleName))
}
}

View File

@@ -14,7 +14,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
capsulev1beta1 "github.com/clastix/capsule/pkg/utils"
capsulev1beta2 "github.com/clastix/capsule/pkg/utils"
)
// pruningResources is taking care of removing the no more requested sub-resources as LimitRange, ResourceQuota or
@@ -22,7 +22,7 @@ import (
func (r *Manager) pruningResources(ctx context.Context, ns string, keys []string, obj client.Object) (err error) {
var capsuleLabel string
if capsuleLabel, err = capsulev1beta1.GetTypeLabel(obj); err != nil {
if capsuleLabel, err = capsulev1beta2.GetTypeLabel(obj); err != nil {
return
}

12
main.go
View File

@@ -206,7 +206,17 @@ func main() {
}
if err = (&capsulev1alpha1.Tenant{}).SetupWebhookWithManager(manager); err != nil {
setupLog.Error(err, "unable to create conversion webhook", "webhook", "Tenant")
setupLog.Error(err, "unable to create conversion webhook", "webhook", "capsulev1alpha1.Tenant")
os.Exit(1)
}
if err = (&capsulev1alpha1.CapsuleConfiguration{}).SetupWebhookWithManager(manager); err != nil {
setupLog.Error(err, "unable to create conversion webhook", "webhook", "capsulev1alpha1.CapsuleConfiguration")
os.Exit(1)
}
if err = (&capsulev1beta1.Tenant{}).SetupWebhookWithManager(manager); err != nil {
setupLog.Error(err, "unable to create conversion webhook", "webhook", "capsulev1beta1.Tenant")
os.Exit(1)
}

View File

@@ -1,12 +1,7 @@
// Copyright 2020-2021 Clastix Labs
// SPDX-License-Identifier: Apache-2.0
package v1beta1
import (
"fmt"
"strings"
)
package api
const (
ForbiddenNamespaceLabelsAnnotation = "capsule.clastix.io/forbidden-namespace-labels"
@@ -15,11 +10,3 @@ const (
ForbiddenNamespaceAnnotationsRegexpAnnotation = "capsule.clastix.io/forbidden-namespace-annotations-regexp"
ProtectedTenantAnnotation = "capsule.clastix.io/protected"
)
func UsedQuotaFor(resource fmt.Stringer) string {
return "quota.capsule.clastix.io/used-" + strings.ReplaceAll(resource.String(), "/", "_")
}
func HardQuotaFor(resource fmt.Stringer) string {
return "quota.capsule.clastix.io/hard-" + strings.ReplaceAll(resource.String(), "/", "_")
}

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