// Copyright 2020-2026 Project Capsule Authors // SPDX-License-Identifier: Apache-2.0 //nolint:dupl package validation import ( "context" "regexp" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" capsulev1beta2 "github.com/projectcapsule/capsule/api/v1beta2" ad "github.com/projectcapsule/capsule/pkg/runtime/admission" "github.com/projectcapsule/capsule/pkg/runtime/events" "github.com/projectcapsule/capsule/pkg/runtime/handlers" ) type storageClassRegexHandler struct{} func StorageClassRegexHandler() handlers.TypedHandler[*capsulev1beta2.Tenant] { return &storageClassRegexHandler{} } func (h *storageClassRegexHandler) OnCreate( _ client.Client, _ client.Reader, tnt *capsulev1beta2.Tenant, decoder admission.Decoder, _ events.EventRecorder, ) handlers.Func { return func(_ context.Context, req admission.Request) *admission.Response { if err := h.validate(tnt, req); err != nil { return err } return nil } } func (h *storageClassRegexHandler) OnDelete( client.Client, client.Reader, *capsulev1beta2.Tenant, admission.Decoder, events.EventRecorder, ) handlers.Func { return func(context.Context, admission.Request) *admission.Response { return nil } } func (h *storageClassRegexHandler) OnUpdate( _ client.Client, _ client.Reader, tnt *capsulev1beta2.Tenant, old *capsulev1beta2.Tenant, _ admission.Decoder, _ events.EventRecorder, ) handlers.Func { return func(_ context.Context, req admission.Request) *admission.Response { if err := h.validate(tnt, req); err != nil { return err } return nil } } func (h *storageClassRegexHandler) validate(tnt *capsulev1beta2.Tenant, req admission.Request) *admission.Response { //nolint:staticcheck if tnt.Spec.StorageClasses != nil && len(tnt.Spec.StorageClasses.Regex) > 0 { if _, err := regexp.Compile(tnt.Spec.StorageClasses.Regex); err != nil { return ad.Deny("unable to compile storageClasses allowedRegex") } } return nil }