mirror of
https://github.com/projectcapsule/capsule.git
synced 2026-02-14 18:09:58 +00:00
refactor(api): switching to v1beta2 as storage version
This commit is contained in:
21
api/v1alpha1/capsuleconfiguration_webhook.go
Normal file
21
api/v1alpha1/capsuleconfiguration_webhook.go
Normal 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()
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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],
|
||||
}
|
||||
}
|
||||
|
||||
21
api/v1beta1/tenant_webhook.go
Normal file
21
api/v1beta1/tenant_webhook.go
Normal 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()
|
||||
}
|
||||
@@ -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
|
||||
|
||||
17
api/v1beta2/tenant_annotations.go
Normal file
17
api/v1beta2/tenant_annotations.go
Normal 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(), "/", "_")
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
12
main.go
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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(), "/", "_")
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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{},
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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()))
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user