chore(deps): update dependency golangci/golangci-lint to v2 (#1405)

* chore(deps): update dependency golangci/golangci-lint to v2

* chore(golint): bump v2 and satisfy linters

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>

---------

Signed-off-by: Oliver Bähler <oliverbaehler@hotmail.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Oliver Bähler <oliverbaehler@hotmail.com>
This commit is contained in:
renovate[bot]
2025-04-30 13:45:10 +02:00
committed by GitHub
parent 5a32195091
commit e286dc94a7
44 changed files with 453 additions and 429 deletions

83
.golangci.yaml Normal file
View File

@@ -0,0 +1,83 @@
version: "2"
run:
tests: false
allow-parallel-runners: true
linters:
default: all
disable:
- depguard
- err113
- exhaustruct
- funlen
- gochecknoglobals
- gochecknoinits
- ireturn
- lll
- mnd
- nilnil
- nonamedreturns
- paralleltest
- perfsprint
- recvcheck
- testpackage
- unparam
- varnamelen
- wrapcheck
settings:
cyclop:
max-complexity: 27
dupl:
threshold: 100
gocognit:
min-complexity: 50
goconst:
min-len: 2
min-occurrences: 2
goheader:
template: |-
Copyright 2020-2023 Project Capsule Authors.
SPDX-License-Identifier: Apache-2.0
inamedparam:
skip-single-param: true
nakedret:
max-func-lines: 50
exclusions:
generated: lax
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
paths:
- zz_.*\.go$
- .+\.generated.go
- .+_test.go
- .+_test_.+.go
- third_party$
- builtin$
- examples$
formatters:
enable:
- gci
- gofmt
- gofumpt
- goimports
settings:
gci:
sections:
- standard
- default
- prefix(github.com/projectcapsule/capsule)
gofumpt:
module-path: github.com/projectcapsule/capsule
extra-rules: false
exclusions:
generated: lax
paths:
- zz_.*\.go$
- .+\.generated.go
- .+_test.go
- .+_test_.+.go
- third_party$
- builtin$
- examples$

View File

@@ -1,60 +0,0 @@
linters-settings:
dupl:
threshold: 100
goconst:
min-len: 2
min-occurrences: 2
cyclop:
max-complexity: 27
gocognit:
min-complexity: 50
gci:
sections:
- standard
- default
- prefix(github.com/projectcapsule/capsule)
goheader:
template: |-
Copyright 2020-2023 Project Capsule Authors.
SPDX-License-Identifier: Apache-2.0
gofumpt:
module-path: github.com/projectcapsule/capsule
extra-rules: false
inamedparam:
# Skips check for interface methods with only a single parameter.
# Default: false
skip-single-param: true
nakedret:
# Make an issue if func has more lines of code than this setting, and it has naked returns.
max-func-lines: 50
linters:
enable-all: true
disable:
- err113
- depguard
- perfsprint
- funlen
- gochecknoinits
- lll
- gochecknoglobals
- mnd
- nilnil
- recvcheck
- unparam
- paralleltest
- ireturn
- testpackage
- varnamelen
- wrapcheck
- exhaustruct
- nonamedreturns
issues:
exclude-files:
- "zz_.*\\.go$"
- ".+\\.generated.go"
- ".+_test.go"
- ".+_test_.+.go"
run:
timeout: 3m
allow-parallel-runners: true
tests: false

View File

@@ -217,7 +217,7 @@ goimports:
# Linting code as PR is expecting
.PHONY: golint
golint: golangci-lint
$(GOLANGCI_LINT) run -c .golangci.yml --verbose --fix
$(GOLANGCI_LINT) run -c .golangci.yaml --verbose --fix
# Running e2e tests in a KinD instance
.PHONY: e2e
@@ -357,11 +357,11 @@ ko:
$(call go-install-tool,$(KO),github.com/$(KO_LOOKUP)@$(KO_VERSION))
GOLANGCI_LINT := $(LOCALBIN)/golangci-lint
GOLANGCI_LINT_VERSION := v1.64.5
GOLANGCI_LINT_VERSION := v2.1.5
GOLANGCI_LINT_LOOKUP := golangci/golangci-lint
golangci-lint: ## Download golangci-lint locally if necessary.
@test -s $(GOLANGCI_LINT) && $(GOLANGCI_LINT) -h | grep -q $(GOLANGCI_LINT_VERSION) || \
$(call go-install-tool,$(GOLANGCI_LINT),github.com/$(GOLANGCI_LINT_LOOKUP)/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION))
$(call go-install-tool,$(GOLANGCI_LINT),github.com/$(GOLANGCI_LINT_LOOKUP)/v2/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION))
APIDOCS_GEN := $(LOCALBIN)/crdoc
APIDOCS_GEN_VERSION := v0.6.4

View File

@@ -28,6 +28,12 @@ type MetadataReconciler struct {
Client client.Client
}
func (m *MetadataReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&corev1.Pod{}, m.forOptionPerInstanceName(ctx)).
Complete(m)
}
func (m *MetadataReconciler) Reconcile(ctx context.Context, request ctrl.Request) (ctrl.Result, error) {
var pod corev1.Pod
@@ -122,9 +128,3 @@ func (m *MetadataReconciler) isNamespaceInTenant(ctx context.Context, namespace
return len(tl.Items) > 0
}
func (m *MetadataReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&corev1.Pod{}, m.forOptionPerInstanceName(ctx)).
Complete(m)
}

View File

@@ -29,40 +29,6 @@ type Global struct {
processor Processor
}
func (r *Global) enqueueRequestFromTenant(ctx context.Context, object client.Object) (reqs []reconcile.Request) {
tnt := object.(*capsulev1beta2.Tenant) //nolint:forcetypeassert
resList := capsulev1beta2.GlobalTenantResourceList{}
if err := r.client.List(ctx, &resList); err != nil {
return nil
}
set := sets.NewString()
for _, res := range resList.Items {
tntSelector := res.Spec.TenantSelector
selector, err := metav1.LabelSelectorAsSelector(&tntSelector)
if err != nil {
continue
}
if selector.Matches(labels.Set(tnt.GetLabels())) {
set.Insert(res.GetName())
}
}
// No need of ordered value here
for res := range set {
reqs = append(reqs, reconcile.Request{
NamespacedName: types.NamespacedName{
Name: res,
},
})
}
return reqs
}
func (r *Global) SetupWithManager(mgr ctrl.Manager) error {
r.client = mgr.GetClient()
r.processor = Processor{
@@ -115,6 +81,40 @@ func (r *Global) Reconcile(ctx context.Context, request reconcile.Request) (reco
return r.reconcileNormal(ctx, tntResource)
}
func (r *Global) enqueueRequestFromTenant(ctx context.Context, object client.Object) (reqs []reconcile.Request) {
tnt := object.(*capsulev1beta2.Tenant) //nolint:forcetypeassert
resList := capsulev1beta2.GlobalTenantResourceList{}
if err := r.client.List(ctx, &resList); err != nil {
return nil
}
set := sets.NewString()
for _, res := range resList.Items {
tntSelector := res.Spec.TenantSelector
selector, err := metav1.LabelSelectorAsSelector(&tntSelector)
if err != nil {
continue
}
if selector.Matches(labels.Set(tnt.GetLabels())) {
set.Insert(res.GetName())
}
}
// No need of ordered value here
for res := range set {
reqs = append(reqs, reconcile.Request{
NamespacedName: types.NamespacedName{
Name: res,
},
})
}
return reqs
}
func (r *Global) reconcileNormal(ctx context.Context, tntResource *capsulev1beta2.GlobalTenantResource) (reconcile.Result, error) {
log := ctrllog.FromContext(ctx)

View File

@@ -39,6 +39,7 @@ func prepareAdditionalMetadata(m map[string]string) map[string]string {
if m == nil {
return make(map[string]string)
}
return m
}

View File

@@ -64,6 +64,17 @@ func (r *abstractServiceLabelsReconciler) Reconcile(ctx context.Context, request
return reconcile.Result{}, err
}
func (r *abstractServiceLabelsReconciler) IsNamespaceInTenant(ctx context.Context, namespace string) bool {
tl := &capsulev1beta2.TenantList{}
if err := r.client.List(ctx, tl, client.MatchingFieldsSelector{
Selector: fields.OneTermEqualSelector(".status.namespaces", namespace),
}); err != nil {
return false
}
return len(tl.Items) > 0
}
func (r *abstractServiceLabelsReconciler) getTenant(ctx context.Context, namespacedName types.NamespacedName, client client.Client) (*capsulev1beta2.Tenant, error) {
ns := &corev1.Namespace{}
tenant := &capsulev1beta2.Tenant{}
@@ -109,14 +120,3 @@ func (r *abstractServiceLabelsReconciler) forOptionPerInstanceName(ctx context.C
return r.IsNamespaceInTenant(ctx, object.GetNamespace())
}))
}
func (r *abstractServiceLabelsReconciler) IsNamespaceInTenant(ctx context.Context, namespace string) bool {
tl := &capsulev1beta2.TenantList{}
if err := r.client.List(ctx, tl, client.MatchingFieldsSelector{
Selector: fields.OneTermEqualSelector(".status.namespaces", namespace),
}); err != nil {
return false
}
return len(tl.Items) > 0
}

View File

@@ -32,9 +32,9 @@ func (r *EndpointSlicesLabelsReconciler) SetupWithManager(ctx context.Context, m
return nil
case r.VersionMajor == 1 && r.VersionMinor < 25:
r.abstractServiceLabelsReconciler.obj = &discoveryv1beta1.EndpointSlice{}
r.obj = &discoveryv1beta1.EndpointSlice{}
default:
r.abstractServiceLabelsReconciler.obj = &discoveryv1.EndpointSlice{}
r.obj = &discoveryv1.EndpointSlice{}
}
return ctrl.NewControllerManagedBy(mgr).

View File

@@ -76,7 +76,7 @@ func (r *Manager) syncLimitRange(ctx context.Context, tenant *capsulev1beta2.Ten
target.SetLabels(labels)
target.Spec = spec
return controllerutil.SetControllerReference(tenant, target, r.Client.Scheme())
return controllerutil.SetControllerReference(tenant, target, r.Scheme())
})
r.emitEvent(tenant, target.GetNamespace(), res, fmt.Sprintf("Ensuring LimitRange %s", target.GetName()), err)

View File

@@ -19,5 +19,5 @@ func (r *Manager) ensureMetadata(ctx context.Context, tnt *capsulev1beta2.Tenant
tnt.Labels[capsuleapi.TenantNameLabel] = tnt.Name
return r.Client.Update(ctx, tnt)
return r.Update(ctx, tnt)
}

View File

@@ -48,7 +48,7 @@ func (r *Manager) syncNamespaceMetadata(ctx context.Context, namespace string, t
err = retry.RetryOnConflict(retry.DefaultBackoff, func() (conflictErr error) {
ns := &corev1.Namespace{}
if conflictErr = r.Client.Get(ctx, types.NamespacedName{Name: namespace}, ns); err != nil {
if conflictErr = r.Get(ctx, types.NamespacedName{Name: namespace}, ns); err != nil {
return
}
@@ -155,7 +155,7 @@ func (r *Manager) ensureNamespaceCount(ctx context.Context, tenant *capsulev1bet
tenant.Status.Size = uint(len(tenant.Status.Namespaces))
found := &capsulev1beta2.Tenant{}
if err := r.Client.Get(ctx, types.NamespacedName{Name: tenant.GetName()}, found); err != nil {
if err := r.Get(ctx, types.NamespacedName{Name: tenant.GetName()}, found); err != nil {
return err
}
@@ -169,7 +169,7 @@ func (r *Manager) collectNamespaces(ctx context.Context, tenant *capsulev1beta2.
return retry.RetryOnConflict(retry.DefaultBackoff, func() (err error) {
list := &corev1.NamespaceList{}
err = r.Client.List(ctx, list, client.MatchingFieldsSelector{
err = r.List(ctx, list, client.MatchingFieldsSelector{
Selector: fields.OneTermEqualSelector(".metadata.ownerReferences[*].capsule", tenant.GetName()),
})
if err != nil {

View File

@@ -75,7 +75,7 @@ func (r *Manager) syncNetworkPolicy(ctx context.Context, tenant *capsulev1beta2.
target.SetLabels(labels)
target.Spec = spec
return controllerutil.SetControllerReference(tenant, target, r.Client.Scheme())
return controllerutil.SetControllerReference(tenant, target, r.Scheme())
})
r.emitEvent(tenant, target.GetNamespace(), res, fmt.Sprintf("Ensuring NetworkPolicy %s", target.GetName()), err)

View File

@@ -255,7 +255,7 @@ func (r *Manager) syncResourceQuota(ctx context.Context, tenant *capsulev1beta2.
target.Spec.Hard = resQuota.Hard
}
return controllerutil.SetControllerReference(tenant, target, r.Client.Scheme())
return controllerutil.SetControllerReference(tenant, target, r.Scheme())
})
return retryErr

View File

@@ -70,7 +70,7 @@ func (r *Manager) syncCustomResourceQuotaUsages(ctx context.Context, tenant *cap
for gvk, used := range usedMap {
err := retry.RetryOnConflict(retry.DefaultBackoff, func() (retryErr error) {
tnt := &capsulev1beta2.Tenant{}
if retryErr = r.Client.Get(ctx, types.NamespacedName{Name: tenant.GetName()}, tnt); retryErr != nil {
if retryErr = r.Get(ctx, types.NamespacedName{Name: tenant.GetName()}, tnt); retryErr != nil {
return
}
@@ -80,7 +80,7 @@ func (r *Manager) syncCustomResourceQuotaUsages(ctx context.Context, tenant *cap
tnt.Annotations[capsulev1beta2.UsedAnnotationForResource(gvk)] = fmt.Sprintf("%d", used)
return r.Client.Update(ctx, tnt)
return r.Update(ctx, tnt)
})
if err != nil {
r.Log.Error(err, "cannot update custom Resource Quota", "GVK", gvk)

View File

@@ -129,12 +129,12 @@ func (r *Manager) syncAdditionalRoleBinding(ctx context.Context, tenant *capsule
var res controllerutil.OperationResult
res, err = controllerutil.CreateOrUpdate(ctx, r.Client, target, func() error {
if target.ObjectMeta.Labels == nil {
target.ObjectMeta.Labels = map[string]string{}
if target.Labels == nil {
target.Labels = map[string]string{}
}
target.ObjectMeta.Labels[tenantLabel] = tenant.Name
target.ObjectMeta.Labels[roleBindingLabel] = roleBindingHashLabel
target.Labels[tenantLabel] = tenant.Name
target.Labels[roleBindingLabel] = roleBindingHashLabel
target.RoleRef = rbacv1.RoleRef{
APIGroup: rbacv1.GroupName,
Kind: "ClusterRole",
@@ -142,7 +142,7 @@ func (r *Manager) syncAdditionalRoleBinding(ctx context.Context, tenant *capsule
}
target.Subjects = roleBinding.Subjects
return controllerutil.SetControllerReference(tenant, target, r.Client.Scheme())
return controllerutil.SetControllerReference(tenant, target, r.Scheme())
})
r.emitEvent(tenant, target.GetNamespace(), res, fmt.Sprintf("Ensuring RoleBinding %s", target.GetName()), err)

View File

@@ -170,7 +170,7 @@ func (r Reconciler) Reconcile(ctx context.Context, request ctrl.Request) (ctrl.R
certSecret := &corev1.Secret{}
if err := r.Client.Get(ctx, request.NamespacedName, certSecret); err != nil {
if err := r.Get(ctx, request.NamespacedName, certSecret); err != nil {
// Error reading the object - requeue the request.
return reconcile.Result{}, err
}
@@ -302,7 +302,7 @@ func (r Reconciler) updateOperatorPod(ctx context.Context, pod corev1.Pod) error
// Need to get latest version of pod
p := &corev1.Pod{}
if err := r.Client.Get(ctx, types.NamespacedName{Namespace: pod.Namespace, Name: pod.Name}, p); err != nil && !apierrors.IsNotFound(err) {
if err := r.Get(ctx, types.NamespacedName{Namespace: pod.Namespace, Name: pod.Name}, p); err != nil && !apierrors.IsNotFound(err) {
r.Log.Error(err, "cannot get pod", "name", pod.Name, "namespace", pod.Namespace)
return err
@@ -314,7 +314,7 @@ func (r Reconciler) updateOperatorPod(ctx context.Context, pod corev1.Pod) error
p.Annotations[PodUpdateAnnotationName] = time.Now().Format(time.RFC3339Nano)
if err := r.Client.Update(ctx, p, &client.UpdateOptions{}); err != nil {
if err := r.Update(ctx, p, &client.UpdateOptions{}); err != nil {
r.Log.Error(err, "cannot update pod", "name", pod.Name, "namespace", pod.Namespace)
return err
@@ -329,12 +329,12 @@ func (r Reconciler) getOperatorPods(ctx context.Context) (*corev1.PodList, error
leaderPod := &corev1.Pod{}
if err := r.Client.Get(ctx, types.NamespacedName{Namespace: os.Getenv("NAMESPACE"), Name: hostname}, leaderPod); err != nil {
if err := r.Get(ctx, types.NamespacedName{Namespace: os.Getenv("NAMESPACE"), Name: hostname}, leaderPod); err != nil {
return nil, RunningInOutOfClusterModeError{}
}
podList := &corev1.PodList{}
if err := r.Client.List(ctx, podList, client.MatchingLabels(leaderPod.ObjectMeta.Labels)); err != nil {
if err := r.List(ctx, podList, client.MatchingLabels(leaderPod.Labels)); err != nil {
r.Log.Error(err, "cannot retrieve list of Capsule pods")
return nil, err

View File

@@ -33,7 +33,7 @@ type SelectorAllowedListSpec struct {
func (in *SelectorAllowedListSpec) MatchSelectByName(obj client.Object) bool {
if obj != nil {
return in.AllowedListSpec.Match(obj.GetName()) || in.SelectorMatch(obj)
return in.Match(obj.GetName()) || in.SelectorMatch(obj)
}
return false

View File

@@ -58,6 +58,10 @@ func NewForbiddenError(key string, forbiddenSpec ForbiddenListSpec) error {
}
}
func (f ForbiddenError) Error() string {
return fmt.Sprintf("%s is forbidden for the current Tenant. %s", f.key, f.appendForbiddenError())
}
//nolint:predeclared,revive
func (f *ForbiddenError) appendForbiddenError() (append string) {
append += "Forbidden are "
@@ -75,10 +79,6 @@ func (f *ForbiddenError) appendForbiddenError() (append string) {
return
}
func (f ForbiddenError) Error() string {
return fmt.Sprintf("%s is forbidden for the current Tenant. %s", f.key, f.appendForbiddenError())
}
func ValidateForbidden(metadata map[string]string, forbiddenList ForbiddenListSpec) error {
if reflect.DeepEqual(ForbiddenListSpec{}, forbiddenList) {
return nil

View File

@@ -29,6 +29,18 @@ type CapsuleCA struct {
key *rsa.PrivateKey
}
func NewCertificateAuthorityFromBytes(certBytes, keyBytes []byte) (*CapsuleCA, error) {
cert, key, err := GetCertificateWithPrivateKeyFromBytes(certBytes, keyBytes)
if err != nil {
return nil, err
}
return &CapsuleCA{
certificate: cert,
key: key,
}, nil
}
func (c CapsuleCA) CACertificatePem() (b *bytes.Buffer, err error) {
var crtBytes []byte
@@ -132,18 +144,6 @@ func GetCertificateWithPrivateKeyFromBytes(certBytes, keyBytes []byte) (*x509.Ce
return cert, key, nil
}
func NewCertificateAuthorityFromBytes(certBytes, keyBytes []byte) (*CapsuleCA, error) {
cert, key, err := GetCertificateWithPrivateKeyFromBytes(certBytes, keyBytes)
if err != nil {
return nil, err
}
return &CapsuleCA{
certificate: cert,
key: key,
}, nil
}
//nolint:nakedret
func (c *CapsuleCA) GenerateCertificate(opts CertificateOptions) (certificatePem *bytes.Buffer, certificateKey *bytes.Buffer, err error) {
var certPrivKey *rsa.PrivateKey

View File

@@ -49,12 +49,12 @@ func (h *handler) OnUpdate(client client.Client, decoder admission.Decoder, reco
func (h *handler) mutate(ctx context.Context, req admission.Request, c client.Client, decoder admission.Decoder, recorder record.EventRecorder) *admission.Response {
var response *admission.Response
switch {
case req.Resource == (metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}):
switch req.Resource {
case metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}:
response = mutatePodDefaults(ctx, req, c, decoder, recorder, req.Namespace)
case req.Resource == (metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "persistentvolumeclaims"}):
case metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "persistentvolumeclaims"}:
response = mutatePVCDefaults(ctx, req, c, decoder, recorder, req.Namespace)
case req.Resource == (metav1.GroupVersionResource{Group: "networking.k8s.io", Version: "v1", Resource: "ingresses"}) || req.Resource == (metav1.GroupVersionResource{Group: "networking.k8s.io", Version: "v1beta1", Resource: "ingresses"}):
case metav1.GroupVersionResource{Group: "networking.k8s.io", Version: "v1", Resource: "ingresses"}, metav1.GroupVersionResource{Group: "networking.k8s.io", Version: "v1beta1", Resource: "ingresses"}:
response = mutateIngressDefaults(ctx, req, h.version, c, decoder, recorder, req.Namespace)
}

View File

@@ -79,7 +79,7 @@ func (n NetworkingV1) HostnamePathsPairs() (pairs map[string]sets.Set[string]) {
pairs[host] = sets.New[string]()
}
if http := rule.IngressRuleValue.HTTP; http != nil {
if http := rule.HTTP; http != nil {
for _, path := range http.Paths {
pairs[host].Insert(path.Path)
}
@@ -149,7 +149,7 @@ func (n NetworkingV1Beta1) HostnamePathsPairs() (pairs map[string]sets.Set[strin
pairs[host] = sets.New[string]()
}
if http := rule.IngressRuleValue.HTTP; http != nil {
if http := rule.HTTP; http != nil {
for _, path := range http.Paths {
pairs[host].Insert(path.Path)
}
@@ -217,7 +217,7 @@ func (e Extension) HostnamePathsPairs() (pairs map[string]sets.Set[string]) {
pairs[host] = sets.New[string]()
}
if http := rule.IngressRuleValue.HTTP; http != nil {
if http := rule.HTTP; http != nil {
for _, path := range http.Paths {
pairs[host].Insert(path.Path)
}

View File

@@ -35,7 +35,7 @@ func (r *freezedHandler) OnCreate(client client.Client, decoder admission.Decode
return utils.ErroredResponse(err)
}
for _, objectRef := range ns.ObjectMeta.OwnerReferences {
for _, objectRef := range ns.OwnerReferences {
if !capsuleutils.IsTenantOwnerReference(objectRef) {
continue
}

View File

@@ -57,7 +57,7 @@ func (r *patchHandler) OnUpdate(c client.Client, decoder admission.Decoder, reco
// Extract Tenant from namespace
e := fmt.Sprintf("namespace/%s can not be patched", ns.Name)
if label, ok := ns.ObjectMeta.Labels[ln]; ok {
if label, ok := ns.Labels[ln]; ok {
// retrieving the selected Tenant
tnt := &capsulev1beta2.Tenant{}
if err = c.Get(ctx, types.NamespacedName{Name: label}, tnt); err != nil {

View File

@@ -49,7 +49,7 @@ func (r *prefixHandler) OnCreate(clt client.Client, decoder admission.Decoder, r
if r.configuration.ForceTenantPrefix() {
tnt := &capsulev1beta2.Tenant{}
for _, or := range ns.ObjectMeta.OwnerReferences {
for _, or := range ns.OwnerReferences {
if !capsuleutils.IsTenantOwnerReference(or) {
continue
}

View File

@@ -31,7 +31,7 @@ func (r *quotaHandler) OnCreate(client client.Client, decoder admission.Decoder,
return utils.ErroredResponse(err)
}
for _, objectRef := range ns.ObjectMeta.OwnerReferences {
for _, objectRef := range ns.OwnerReferences {
if !capsuleutils.IsTenantOwnerReference(objectRef) {
continue
}

View File

@@ -35,7 +35,7 @@ func (r *userMetadataHandler) OnCreate(client client.Client, decoder admission.D
tnt := &capsulev1beta2.Tenant{}
for _, objectRef := range ns.ObjectMeta.OwnerReferences {
for _, objectRef := range ns.OwnerReferences {
if !capsuleutils.IsTenantOwnerReference(objectRef) {
continue
}
@@ -47,7 +47,7 @@ func (r *userMetadataHandler) OnCreate(client client.Client, decoder admission.D
}
if tnt.Spec.NamespaceOptions != nil {
err := api.ValidateForbidden(ns.ObjectMeta.Annotations, tnt.Spec.NamespaceOptions.ForbiddenAnnotations)
err := api.ValidateForbidden(ns.Annotations, tnt.Spec.NamespaceOptions.ForbiddenAnnotations)
if err != nil {
err = errors.Wrap(err, "namespace annotations validation failed")
recorder.Eventf(tnt, corev1.EventTypeWarning, api.ForbiddenAnnotationReason, err.Error())
@@ -56,7 +56,7 @@ func (r *userMetadataHandler) OnCreate(client client.Client, decoder admission.D
return &response
}
err = api.ValidateForbidden(ns.ObjectMeta.Labels, tnt.Spec.NamespaceOptions.ForbiddenLabels)
err = api.ValidateForbidden(ns.Labels, tnt.Spec.NamespaceOptions.ForbiddenLabels)
if err != nil {
err = errors.Wrap(err, "namespace labels validation failed")
recorder.Eventf(tnt, corev1.EventTypeWarning, api.ForbiddenLabelReason, err.Error())
@@ -90,7 +90,7 @@ func (r *userMetadataHandler) OnUpdate(client client.Client, decoder admission.D
tnt := &capsulev1beta2.Tenant{}
for _, objectRef := range newNs.ObjectMeta.OwnerReferences {
for _, objectRef := range newNs.OwnerReferences {
if !capsuleutils.IsTenantOwnerReference(objectRef) {
continue
}

View File

@@ -67,7 +67,7 @@ func (r *handler) handle(ctx context.Context, req admission.Request, client clie
allowed = true
np := &networkingv1.NetworkPolicy{}
if err = client.Get(ctx, types.NamespacedName{Namespace: req.AdmissionRequest.Namespace, Name: req.AdmissionRequest.Name}, np); err != nil {
if err = client.Get(ctx, types.NamespacedName{Namespace: req.Namespace, Name: req.Name}, np); err != nil {
return false, err
}

View File

@@ -42,42 +42,6 @@ func (r *userMetadataHandler) OnDelete(client.Client, admission.Decoder, record.
}
}
func (r *userMetadataHandler) getForbiddenNodeLabels(node *corev1.Node) map[string]string {
forbiddenNodeLabels := make(map[string]string)
forbiddenLabels := r.configuration.ForbiddenUserNodeLabels()
for label, value := range node.GetLabels() {
var forbidden, matched bool
forbidden = forbiddenLabels.ExactMatch(label)
matched = forbiddenLabels.RegexMatch(label)
if forbidden || matched {
forbiddenNodeLabels[label] = value
}
}
return forbiddenNodeLabels
}
func (r *userMetadataHandler) getForbiddenNodeAnnotations(node *corev1.Node) map[string]string {
forbiddenNodeAnnotations := make(map[string]string)
forbiddenAnnotations := r.configuration.ForbiddenUserNodeAnnotations()
for annotation, value := range node.GetAnnotations() {
var forbidden, matched bool
forbidden = forbiddenAnnotations.ExactMatch(annotation)
matched = forbiddenAnnotations.RegexMatch(annotation)
if forbidden || matched {
forbiddenNodeAnnotations[annotation] = value
}
}
return forbiddenNodeAnnotations
}
func (r *userMetadataHandler) OnUpdate(_ client.Client, decoder admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
return func(_ context.Context, req admission.Request) *admission.Response {
nodeWebhookSupported, _ := utils.NodeWebhookSupported(r.version)
@@ -125,3 +89,39 @@ func (r *userMetadataHandler) OnUpdate(_ client.Client, decoder admission.Decode
return nil
}
}
func (r *userMetadataHandler) getForbiddenNodeLabels(node *corev1.Node) map[string]string {
forbiddenNodeLabels := make(map[string]string)
forbiddenLabels := r.configuration.ForbiddenUserNodeLabels()
for label, value := range node.GetLabels() {
var forbidden, matched bool
forbidden = forbiddenLabels.ExactMatch(label)
matched = forbiddenLabels.RegexMatch(label)
if forbidden || matched {
forbiddenNodeLabels[label] = value
}
}
return forbiddenNodeLabels
}
func (r *userMetadataHandler) getForbiddenNodeAnnotations(node *corev1.Node) map[string]string {
forbiddenNodeAnnotations := make(map[string]string)
forbiddenAnnotations := r.configuration.ForbiddenUserNodeAnnotations()
for annotation, value := range node.GetAnnotations() {
var forbidden, matched bool
forbidden = forbiddenAnnotations.ExactMatch(annotation)
matched = forbiddenAnnotations.RegexMatch(annotation)
if forbidden || matched {
forbiddenNodeAnnotations[annotation] = value
}
}
return forbiddenNodeAnnotations
}

View File

@@ -145,7 +145,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 {
if label, ok := ns.Labels[ln]; ok {
// retrieving the selected Tenant
tnt := &capsulev1beta2.Tenant{}
if err = client.Get(ctx, types.NamespacedName{Name: label}, tnt); err != nil {

View File

@@ -64,14 +64,14 @@ func (h *containerRegistryHandler) validate(ctx context.Context, c client.Client
if tnt.Spec.ContainerRegistries != nil {
// Evaluate init containers
for _, container := range pod.Spec.InitContainers {
if response := h.VerifyContainerRegistry(recorder, req, container, tnt); response != nil {
if response := h.verifyContainerRegistry(recorder, req, container, tnt); response != nil {
return response
}
}
// Evaluate containers
for _, container := range pod.Spec.Containers {
if response := h.VerifyContainerRegistry(recorder, req, container, tnt); response != nil {
if response := h.verifyContainerRegistry(recorder, req, container, tnt); response != nil {
return response
}
}
@@ -80,7 +80,7 @@ func (h *containerRegistryHandler) validate(ctx context.Context, c client.Client
return nil
}
func (h *containerRegistryHandler) VerifyContainerRegistry(recorder record.EventRecorder, req admission.Request, container corev1.Container, tnt capsulev1beta2.Tenant) *admission.Response {
func (h *containerRegistryHandler) verifyContainerRegistry(recorder record.EventRecorder, req admission.Request, container corev1.Container, tnt capsulev1beta2.Tenant) *admission.Response {
var valid, matched bool
reg := NewRegistry(container.Image)

View File

@@ -49,6 +49,13 @@ func (r registry) Tag() string {
return res
}
type Registry interface {
Registry() string
Repository() string
Image() string
Tag() string
}
func NewRegistry(value string) Registry {
reg := make(registry)
r := regexp.MustCompile(`((?P<registry>[a-zA-Z0-9-._]+(:\d+)?)\/)?(?P<repository>.*\/)?(?P<image>[a-zA-Z0-9-._]+:(?P<tag>[a-zA-Z0-9-._]+))?`)
@@ -62,10 +69,3 @@ func NewRegistry(value string) Registry {
return reg
}
type Registry interface {
Registry() string
Repository() string
Image() string
Tag() string
}

View File

@@ -24,19 +24,6 @@ func RuntimeClass() capsulewebhook.Handler {
return &runtimeClass{}
}
func (h *runtimeClass) class(ctx context.Context, c client.Client, name string) (client.Object, error) {
if len(name) == 0 {
return nil, nil
}
obj := &nodev1.RuntimeClass{}
if err := c.Get(ctx, types.NamespacedName{Name: name}, obj); err != nil {
return nil, err
}
return obj, nil
}
func (h *runtimeClass) OnCreate(c client.Client, decoder admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
return h.validate(ctx, c, decoder, recorder, req)
@@ -55,6 +42,19 @@ func (h *runtimeClass) OnUpdate(client.Client, admission.Decoder, record.EventRe
}
}
func (h *runtimeClass) class(ctx context.Context, c client.Client, name string) (client.Object, error) {
if len(name) == 0 {
return nil, nil
}
obj := &nodev1.RuntimeClass{}
if err := c.Get(ctx, types.NamespacedName{Name: name}, obj); err != nil {
return nil, err
}
return obj, nil
}
func (h *runtimeClass) validate(ctx context.Context, c client.Client, decoder admission.Decoder, recorder record.EventRecorder, req admission.Request) *admission.Response {
pod := &corev1.Pod{}
if err := decoder.Decode(req, pod); err != nil {

View File

@@ -27,6 +27,24 @@ func Handler() capsulewebhook.Handler {
return &handler{}
}
func (r *handler) OnCreate(client client.Client, decoder admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
return r.handleService(ctx, client, decoder, req, recorder)
}
}
func (r *handler) OnUpdate(client client.Client, decoder admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
return r.handleService(ctx, client, decoder, req, recorder)
}
}
func (r *handler) OnDelete(client.Client, admission.Decoder, record.EventRecorder) capsulewebhook.Func {
return func(context.Context, admission.Request) *admission.Response {
return nil
}
}
func (r *handler) handleService(ctx context.Context, clt client.Client, decoder admission.Decoder, req admission.Request, recorder record.EventRecorder) *admission.Response {
svc := &corev1.Service{}
if err := decoder.Decode(req, svc); err != nil {
@@ -124,21 +142,3 @@ func (r *handler) handleService(ctx context.Context, clt client.Client, decoder
return nil
}
func (r *handler) OnCreate(client client.Client, decoder admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
return r.handleService(ctx, client, decoder, req, recorder)
}
}
func (r *handler) OnUpdate(client client.Client, decoder admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
return r.handleService(ctx, client, decoder, req, recorder)
}
}
func (r *handler) OnDelete(client.Client, admission.Decoder, record.EventRecorder) capsulewebhook.Func {
return func(context.Context, admission.Request) *admission.Response {
return nil
}
}

View File

@@ -23,23 +23,6 @@ func ContainerRegistryRegexHandler() capsulewebhook.Handler {
return &containerRegistryRegexHandler{}
}
func (h *containerRegistryRegexHandler) validate(decoder admission.Decoder, req admission.Request) *admission.Response {
tenant := &capsulev1beta2.Tenant{}
if err := decoder.Decode(req, tenant); err != nil {
return utils.ErroredResponse(err)
}
if tenant.Spec.ContainerRegistries != nil && len(tenant.Spec.ContainerRegistries.Regex) > 0 {
if _, err := regexp.Compile(tenant.Spec.ContainerRegistries.Regex); err != nil {
response := admission.Denied("unable to compile containerRegistries allowedRegex")
return &response
}
}
return nil
}
func (h *containerRegistryRegexHandler) OnCreate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
return func(_ context.Context, req admission.Request) *admission.Response {
if err := h.validate(decoder, req); err != nil {
@@ -65,3 +48,20 @@ func (h *containerRegistryRegexHandler) OnUpdate(_ client.Client, decoder admiss
return nil
}
}
func (h *containerRegistryRegexHandler) validate(decoder admission.Decoder, req admission.Request) *admission.Response {
tenant := &capsulev1beta2.Tenant{}
if err := decoder.Decode(req, tenant); err != nil {
return utils.ErroredResponse(err)
}
if tenant.Spec.ContainerRegistries != nil && len(tenant.Spec.ContainerRegistries.Regex) > 0 {
if _, err := regexp.Compile(tenant.Spec.ContainerRegistries.Regex); err != nil {
response := admission.Denied("unable to compile containerRegistries allowedRegex")
return &response
}
}
return nil
}

View File

@@ -30,6 +30,24 @@ func CordoningHandler(configuration configuration.Configuration) capsulewebhook.
}
}
func (h *cordoningHandler) OnCreate(client client.Client, _ admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
return h.cordonHandler(ctx, client, req, recorder)
}
}
func (h *cordoningHandler) OnDelete(client client.Client, _ admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
return h.cordonHandler(ctx, client, req, recorder)
}
}
func (h *cordoningHandler) OnUpdate(client client.Client, _ admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
return h.cordonHandler(ctx, client, req, recorder)
}
}
func (h *cordoningHandler) cordonHandler(ctx context.Context, clt client.Client, req admission.Request, recorder record.EventRecorder) *admission.Response {
tntList := &capsulev1beta2.TenantList{}
@@ -54,21 +72,3 @@ func (h *cordoningHandler) cordonHandler(ctx context.Context, clt client.Client,
return nil
}
func (h *cordoningHandler) OnCreate(client client.Client, _ admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
return h.cordonHandler(ctx, client, req, recorder)
}
}
func (h *cordoningHandler) OnDelete(client client.Client, _ admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
return h.cordonHandler(ctx, client, req, recorder)
}
}
func (h *cordoningHandler) OnUpdate(client client.Client, _ admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
return h.cordonHandler(ctx, client, req, recorder)
}
}

View File

@@ -31,22 +31,6 @@ func ResourceCounterHandler(client client.Client) capsulewebhook.Handler {
}
}
func (r *resourceCounterHandler) getTenantName(ctx context.Context, clt client.Client, req admission.Request) (string, error) {
tntList := &capsulev1beta2.TenantList{}
if err := clt.List(ctx, tntList, client.MatchingFieldsSelector{
Selector: fields.OneTermEqualSelector(".status.namespaces", req.Namespace),
}); err != nil {
return "", err
}
if len(tntList.Items) == 0 {
return "", nil
}
return tntList.Items[0].GetName(), nil
}
func (r *resourceCounterHandler) OnCreate(clt client.Client, _ admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
var tntName string
@@ -150,3 +134,19 @@ func (r *resourceCounterHandler) OnUpdate(client.Client, admission.Decoder, reco
return nil
}
}
func (r *resourceCounterHandler) getTenantName(ctx context.Context, clt client.Client, req admission.Request) (string, error) {
tntList := &capsulev1beta2.TenantList{}
if err := clt.List(ctx, tntList, client.MatchingFieldsSelector{
Selector: fields.OneTermEqualSelector(".status.namespaces", req.Namespace),
}); err != nil {
return "", err
}
if len(tntList.Items) == 0 {
return "", nil
}
return tntList.Items[0].GetName(), nil
}

View File

@@ -23,32 +23,6 @@ func ForbiddenAnnotationsRegexHandler() capsulewebhook.Handler {
return &forbiddenAnnotationsRegexHandler{}
}
func (h *forbiddenAnnotationsRegexHandler) validate(decoder admission.Decoder, req admission.Request) *admission.Response {
tenant := &capsulev1beta2.Tenant{}
if err := decoder.Decode(req, tenant); err != nil {
return utils.ErroredResponse(err)
}
if tenant.Spec.NamespaceOptions == nil {
return nil
}
annotationsToCheck := map[string]string{
"labels": tenant.Spec.NamespaceOptions.ForbiddenLabels.Regex,
"annotations": tenant.Spec.NamespaceOptions.ForbiddenAnnotations.Regex,
}
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
}
}
return nil
}
func (h *forbiddenAnnotationsRegexHandler) OnCreate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
return func(_ context.Context, req admission.Request) *admission.Response {
if err := h.validate(decoder, req); err != nil {
@@ -74,3 +48,29 @@ func (h *forbiddenAnnotationsRegexHandler) OnUpdate(_ client.Client, decoder adm
return nil
}
}
func (h *forbiddenAnnotationsRegexHandler) validate(decoder admission.Decoder, req admission.Request) *admission.Response {
tenant := &capsulev1beta2.Tenant{}
if err := decoder.Decode(req, tenant); err != nil {
return utils.ErroredResponse(err)
}
if tenant.Spec.NamespaceOptions == nil {
return nil
}
annotationsToCheck := map[string]string{
"labels": tenant.Spec.NamespaceOptions.ForbiddenLabels.Regex,
"annotations": tenant.Spec.NamespaceOptions.ForbiddenAnnotations.Regex,
}
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
}
}
return nil
}

View File

@@ -23,23 +23,6 @@ func HostnameRegexHandler() capsulewebhook.Handler {
return &hostnameRegexHandler{}
}
func (h *hostnameRegexHandler) validate(decoder admission.Decoder, req admission.Request) *admission.Response {
tenant := &capsulev1beta2.Tenant{}
if err := decoder.Decode(req, tenant); err != nil {
return utils.ErroredResponse(err)
}
if tenant.Spec.IngressOptions.AllowedHostnames != nil && len(tenant.Spec.IngressOptions.AllowedHostnames.Regex) > 0 {
if _, err := regexp.Compile(tenant.Spec.IngressOptions.AllowedHostnames.Regex); err != nil {
response := admission.Denied("unable to compile allowedHostnames allowedRegex")
return &response
}
}
return nil
}
func (h *hostnameRegexHandler) OnCreate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
return func(_ context.Context, req admission.Request) *admission.Response {
if response := h.validate(decoder, req); response != nil {
@@ -65,3 +48,20 @@ func (h *hostnameRegexHandler) OnUpdate(_ client.Client, decoder admission.Decod
return nil
}
}
func (h *hostnameRegexHandler) validate(decoder admission.Decoder, req admission.Request) *admission.Response {
tenant := &capsulev1beta2.Tenant{}
if err := decoder.Decode(req, tenant); err != nil {
return utils.ErroredResponse(err)
}
if tenant.Spec.IngressOptions.AllowedHostnames != nil && len(tenant.Spec.IngressOptions.AllowedHostnames.Regex) > 0 {
if _, err := regexp.Compile(tenant.Spec.IngressOptions.AllowedHostnames.Regex); err != nil {
response := admission.Denied("unable to compile allowedHostnames allowedRegex")
return &response
}
}
return nil
}

View File

@@ -23,23 +23,6 @@ func IngressClassRegexHandler() capsulewebhook.Handler {
return &ingressClassRegexHandler{}
}
func (h *ingressClassRegexHandler) validate(decoder admission.Decoder, req admission.Request) *admission.Response {
tenant := &capsulev1beta2.Tenant{}
if err := decoder.Decode(req, tenant); err != nil {
return utils.ErroredResponse(err)
}
if tenant.Spec.IngressOptions.AllowedClasses != nil && len(tenant.Spec.IngressOptions.AllowedClasses.Regex) > 0 {
if _, err := regexp.Compile(tenant.Spec.IngressOptions.AllowedClasses.Regex); err != nil {
response := admission.Denied("unable to compile ingressClasses allowedRegex")
return &response
}
}
return nil
}
func (h *ingressClassRegexHandler) OnCreate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
return func(_ context.Context, req admission.Request) *admission.Response {
if response := h.validate(decoder, req); response != nil {
@@ -65,3 +48,20 @@ func (h *ingressClassRegexHandler) OnUpdate(_ client.Client, decoder admission.D
return nil
}
}
func (h *ingressClassRegexHandler) validate(decoder admission.Decoder, req admission.Request) *admission.Response {
tenant := &capsulev1beta2.Tenant{}
if err := decoder.Decode(req, tenant); err != nil {
return utils.ErroredResponse(err)
}
if tenant.Spec.IngressOptions.AllowedClasses != nil && len(tenant.Spec.IngressOptions.AllowedClasses.Regex) > 0 {
if _, err := regexp.Compile(tenant.Spec.IngressOptions.AllowedClasses.Regex); err != nil {
response := admission.Denied("unable to compile ingressClasses allowedRegex")
return &response
}
}
return nil
}

View File

@@ -32,7 +32,7 @@ func (h *protectedHandler) OnDelete(clt client.Client, _ admission.Decoder, _ re
return func(ctx context.Context, req admission.Request) *admission.Response {
tenant := &capsulev1beta2.Tenant{}
if err := clt.Get(ctx, types.NamespacedName{Name: req.AdmissionRequest.Name}, tenant); err != nil {
if err := clt.Get(ctx, types.NamespacedName{Name: req.Name}, tenant); err != nil {
return utils.ErroredResponse(err)
}

View File

@@ -25,6 +25,24 @@ func RoleBindingRegexHandler() capsulewebhook.Handler {
return &rbRegexHandler{}
}
func (h *rbRegexHandler) OnCreate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
return func(_ context.Context, req admission.Request) *admission.Response {
return h.validate(req, decoder)
}
}
func (h *rbRegexHandler) OnDelete(client.Client, admission.Decoder, record.EventRecorder) capsulewebhook.Func {
return func(context.Context, admission.Request) *admission.Response {
return nil
}
}
func (h *rbRegexHandler) OnUpdate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
return func(_ context.Context, req admission.Request) *admission.Response {
return h.validate(req, decoder)
}
}
func (h *rbRegexHandler) validate(req admission.Request, decoder admission.Decoder) *admission.Response {
tenant := &capsulev1beta2.Tenant{}
if err := decoder.Decode(req, tenant); err != nil {
@@ -48,21 +66,3 @@ func (h *rbRegexHandler) validate(req admission.Request, decoder admission.Decod
return nil
}
func (h *rbRegexHandler) OnCreate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
return func(_ context.Context, req admission.Request) *admission.Response {
return h.validate(req, decoder)
}
}
func (h *rbRegexHandler) OnDelete(client.Client, admission.Decoder, record.EventRecorder) capsulewebhook.Func {
return func(context.Context, admission.Request) *admission.Response {
return nil
}
}
func (h *rbRegexHandler) OnUpdate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
return func(_ context.Context, req admission.Request) *admission.Response {
return h.validate(req, decoder)
}
}

View File

@@ -23,6 +23,24 @@ func ServiceAccountNameHandler() capsulewebhook.Handler {
return &saNameHandler{}
}
func (h *saNameHandler) OnCreate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
return func(_ context.Context, req admission.Request) *admission.Response {
return h.validateServiceAccountName(req, decoder)
}
}
func (h *saNameHandler) OnDelete(client.Client, admission.Decoder, record.EventRecorder) capsulewebhook.Func {
return func(context.Context, admission.Request) *admission.Response {
return nil
}
}
func (h *saNameHandler) OnUpdate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
return func(_ context.Context, req admission.Request) *admission.Response {
return h.validateServiceAccountName(req, decoder)
}
}
func (h *saNameHandler) validateServiceAccountName(req admission.Request, decoder admission.Decoder) *admission.Response {
tenant := &capsulev1beta2.Tenant{}
if err := decoder.Decode(req, tenant); err != nil {
@@ -45,21 +63,3 @@ func (h *saNameHandler) validateServiceAccountName(req admission.Request, decode
return nil
}
func (h *saNameHandler) OnCreate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
return func(_ context.Context, req admission.Request) *admission.Response {
return h.validateServiceAccountName(req, decoder)
}
}
func (h *saNameHandler) OnDelete(client.Client, admission.Decoder, record.EventRecorder) capsulewebhook.Func {
return func(context.Context, admission.Request) *admission.Response {
return nil
}
}
func (h *saNameHandler) OnUpdate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
return func(_ context.Context, req admission.Request) *admission.Response {
return h.validateServiceAccountName(req, decoder)
}
}

View File

@@ -23,23 +23,6 @@ func StorageClassRegexHandler() capsulewebhook.Handler {
return &storageClassRegexHandler{}
}
func (h *storageClassRegexHandler) validate(decoder admission.Decoder, req admission.Request) *admission.Response {
tenant := &capsulev1beta2.Tenant{}
if err := decoder.Decode(req, tenant); err != nil {
return utils.ErroredResponse(err)
}
if tenant.Spec.StorageClasses != nil && len(tenant.Spec.StorageClasses.Regex) > 0 {
if _, err := regexp.Compile(tenant.Spec.StorageClasses.Regex); err != nil {
response := admission.Denied("unable to compile storageClasses allowedRegex")
return &response
}
}
return nil
}
func (h *storageClassRegexHandler) OnCreate(_ client.Client, decoder admission.Decoder, _ record.EventRecorder) capsulewebhook.Func {
return func(_ context.Context, req admission.Request) *admission.Response {
if err := h.validate(decoder, req); err != nil {
@@ -65,3 +48,20 @@ func (h *storageClassRegexHandler) OnUpdate(_ client.Client, decoder admission.D
return nil
}
}
func (h *storageClassRegexHandler) validate(decoder admission.Decoder, req admission.Request) *admission.Response {
tenant := &capsulev1beta2.Tenant{}
if err := decoder.Decode(req, tenant); err != nil {
return utils.ErroredResponse(err)
}
if tenant.Spec.StorageClasses != nil && len(tenant.Spec.StorageClasses.Regex) > 0 {
if _, err := regexp.Compile(tenant.Spec.StorageClasses.Regex); err != nil {
response := admission.Denied("unable to compile storageClasses allowedRegex")
return &response
}
}
return nil
}

View File

@@ -26,6 +26,24 @@ func WriteOpsHandler() capsulewebhook.Handler {
return &cordoningHandler{}
}
func (h *cordoningHandler) OnCreate(client.Client, admission.Decoder, record.EventRecorder) capsulewebhook.Func {
return func(context.Context, admission.Request) *admission.Response {
return nil
}
}
func (h *cordoningHandler) OnDelete(client client.Client, _ admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
return h.handler(ctx, client, req, recorder)
}
}
func (h *cordoningHandler) OnUpdate(client client.Client, _ admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
return h.handler(ctx, client, req, recorder)
}
}
func (h *cordoningHandler) handler(ctx context.Context, clt client.Client, req admission.Request, recorder record.EventRecorder) *admission.Response {
tntList := &capsulev1beta2.TenantList{}
@@ -69,21 +87,3 @@ func (h *cordoningHandler) handler(ctx context.Context, clt client.Client, req a
return nil
}
func (h *cordoningHandler) OnCreate(client.Client, admission.Decoder, record.EventRecorder) capsulewebhook.Func {
return func(context.Context, admission.Request) *admission.Response {
return nil
}
}
func (h *cordoningHandler) OnDelete(client client.Client, _ admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
return h.handler(ctx, client, req, recorder)
}
}
func (h *cordoningHandler) OnUpdate(client client.Client, _ admission.Decoder, recorder record.EventRecorder) capsulewebhook.Func {
return func(ctx context.Context, req admission.Request) *admission.Response {
return h.handler(ctx, client, req, recorder)
}
}