mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-29 02:45:06 +00:00
fix: split webhook handlers per failure policy (#4650)
* fix: split webhook handlers per failure policy Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com> * fix handlers Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com> * rolling update Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com> * better error message Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com> Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com> Co-authored-by: Vyankatesh Kudtarkar <vyankateshkd@gmail.com>
This commit is contained in:
parent
8741c34081
commit
665e513c5e
7 changed files with 117 additions and 38 deletions
|
@ -289,7 +289,8 @@ func defaultResourceWebhookRule(autoUpdate bool) admissionregistrationv1.Rule {
|
|||
}
|
||||
|
||||
func constructDefaultDebugMutatingWebhookConfig(serverIP string, caData []byte, timeoutSeconds int32, autoUpdate bool, owner metav1.OwnerReference) *admissionregistrationv1.MutatingWebhookConfiguration {
|
||||
name, url := config.MutatingWebhookName, fmt.Sprintf("https://%s%s", serverIP, config.MutatingWebhookServicePath)
|
||||
name, baseUrl := config.MutatingWebhookName, fmt.Sprintf("https://%s%s", serverIP, config.MutatingWebhookServicePath)
|
||||
url := fmt.Sprintf("%s/ignore", baseUrl)
|
||||
webhook := &admissionregistrationv1.MutatingWebhookConfiguration{
|
||||
ObjectMeta: generateObjectMeta(config.MutatingWebhookConfigurationDebugName, owner),
|
||||
Webhooks: []admissionregistrationv1.MutatingWebhook{
|
||||
|
@ -297,13 +298,15 @@ func constructDefaultDebugMutatingWebhookConfig(serverIP string, caData []byte,
|
|||
},
|
||||
}
|
||||
if autoUpdate {
|
||||
url := fmt.Sprintf("%s/fail", baseUrl)
|
||||
webhook.Webhooks = append(webhook.Webhooks, generateDebugMutatingWebhook(name+"-fail", url, caData, timeoutSeconds, defaultResourceWebhookRule(autoUpdate), createUpdate, admissionregistrationv1.Fail))
|
||||
}
|
||||
return webhook
|
||||
}
|
||||
|
||||
func constructDefaultMutatingWebhookConfig(caData []byte, timeoutSeconds int32, autoUpdate bool, owner metav1.OwnerReference) *admissionregistrationv1.MutatingWebhookConfiguration {
|
||||
name, path := config.MutatingWebhookName, config.MutatingWebhookServicePath
|
||||
name, basePath := config.MutatingWebhookName, config.MutatingWebhookServicePath
|
||||
path := fmt.Sprintf("%s/ignore", basePath)
|
||||
webhook := &admissionregistrationv1.MutatingWebhookConfiguration{
|
||||
ObjectMeta: generateObjectMeta(config.MutatingWebhookConfigurationName, owner),
|
||||
Webhooks: []admissionregistrationv1.MutatingWebhook{
|
||||
|
@ -311,13 +314,15 @@ func constructDefaultMutatingWebhookConfig(caData []byte, timeoutSeconds int32,
|
|||
},
|
||||
}
|
||||
if autoUpdate {
|
||||
path := fmt.Sprintf("%s/fail", basePath)
|
||||
webhook.Webhooks = append(webhook.Webhooks, generateMutatingWebhook(name+"-fail", path, caData, timeoutSeconds, defaultResourceWebhookRule(autoUpdate), createUpdate, admissionregistrationv1.Fail))
|
||||
}
|
||||
return webhook
|
||||
}
|
||||
|
||||
func constructDefaultDebugValidatingWebhookConfig(serverIP string, caData []byte, timeoutSeconds int32, autoUpdate bool, owner metav1.OwnerReference) *admissionregistrationv1.ValidatingWebhookConfiguration {
|
||||
name, url := config.ValidatingWebhookName, fmt.Sprintf("https://%s%s", serverIP, config.ValidatingWebhookServicePath)
|
||||
name, baseUrl := config.ValidatingWebhookName, fmt.Sprintf("https://%s%s", serverIP, config.ValidatingWebhookServicePath)
|
||||
url := fmt.Sprintf("%s/ignore", baseUrl)
|
||||
webhook := &admissionregistrationv1.ValidatingWebhookConfiguration{
|
||||
ObjectMeta: generateObjectMeta(config.ValidatingWebhookConfigurationDebugName, owner),
|
||||
Webhooks: []admissionregistrationv1.ValidatingWebhook{
|
||||
|
@ -325,13 +330,15 @@ func constructDefaultDebugValidatingWebhookConfig(serverIP string, caData []byte
|
|||
},
|
||||
}
|
||||
if autoUpdate {
|
||||
url := fmt.Sprintf("%s/fail", baseUrl)
|
||||
webhook.Webhooks = append(webhook.Webhooks, generateDebugValidatingWebhook(name+"-fail", url, caData, timeoutSeconds, defaultResourceWebhookRule(autoUpdate), all, admissionregistrationv1.Fail))
|
||||
}
|
||||
return webhook
|
||||
}
|
||||
|
||||
func constructDefaultValidatingWebhookConfig(caData []byte, timeoutSeconds int32, autoUpdate bool, owner metav1.OwnerReference) *admissionregistrationv1.ValidatingWebhookConfiguration {
|
||||
name, path := config.ValidatingWebhookName, config.ValidatingWebhookServicePath
|
||||
name, basePath := config.ValidatingWebhookName, config.ValidatingWebhookServicePath
|
||||
path := fmt.Sprintf("%s/ignore", basePath)
|
||||
webhook := &admissionregistrationv1.ValidatingWebhookConfiguration{
|
||||
ObjectMeta: generateObjectMeta(config.ValidatingWebhookConfigurationName, owner),
|
||||
Webhooks: []admissionregistrationv1.ValidatingWebhook{
|
||||
|
@ -339,6 +346,7 @@ func constructDefaultValidatingWebhookConfig(caData []byte, timeoutSeconds int32
|
|||
},
|
||||
}
|
||||
if autoUpdate {
|
||||
path := fmt.Sprintf("%s/fail", basePath)
|
||||
webhook.Webhooks = append(webhook.Webhooks, generateValidatingWebhook(name+"-fail", path, caData, timeoutSeconds, defaultResourceWebhookRule(autoUpdate), all, admissionregistrationv1.Fail))
|
||||
}
|
||||
return webhook
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
"github.com/kyverno/kyverno/pkg/metrics"
|
||||
tlsutils "github.com/kyverno/kyverno/pkg/tls"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
"github.com/pkg/errors"
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
|
@ -277,21 +278,31 @@ func (wrc *Register) UpdateWebhookConfigurations(configHandler config.Configurat
|
|||
<-wrc.UpdateWebhookChan
|
||||
logger.V(4).Info("received the signal to update webhook configurations")
|
||||
|
||||
webhookCfgs := configHandler.GetWebhooks()
|
||||
webhookCfg := config.WebhookConfig{}
|
||||
if len(webhookCfgs) > 0 {
|
||||
webhookCfg = webhookCfgs[0]
|
||||
}
|
||||
|
||||
retry := false
|
||||
if err := wrc.updateResourceMutatingWebhookConfiguration(webhookCfg); err != nil {
|
||||
logger.Error(err, "unable to update mutatingWebhookConfigurations", "name", getResourceMutatingWebhookConfigName(wrc.serverIP))
|
||||
deploy, err := wrc.GetKubePolicyDeployment()
|
||||
if err != nil {
|
||||
retry = true
|
||||
}
|
||||
if tlsutils.IsKyvernoInRollingUpdate(deploy) {
|
||||
retry = true
|
||||
}
|
||||
|
||||
if err := wrc.updateResourceValidatingWebhookConfiguration(webhookCfg); err != nil {
|
||||
logger.Error(err, "unable to update validatingWebhookConfigurations", "name", getResourceValidatingWebhookConfigName(wrc.serverIP))
|
||||
retry = true
|
||||
if !retry {
|
||||
webhookCfgs := configHandler.GetWebhooks()
|
||||
webhookCfg := config.WebhookConfig{}
|
||||
if len(webhookCfgs) > 0 {
|
||||
webhookCfg = webhookCfgs[0]
|
||||
}
|
||||
|
||||
if err := wrc.updateResourceMutatingWebhookConfiguration(webhookCfg); err != nil {
|
||||
logger.Error(err, "unable to update mutatingWebhookConfigurations", "name", getResourceMutatingWebhookConfigName(wrc.serverIP))
|
||||
retry = true
|
||||
}
|
||||
|
||||
if err := wrc.updateResourceValidatingWebhookConfiguration(webhookCfg); err != nil {
|
||||
logger.Error(err, "unable to update validatingWebhookConfigurations", "name", getResourceValidatingWebhookConfigName(wrc.serverIP))
|
||||
retry = true
|
||||
}
|
||||
}
|
||||
|
||||
if retry {
|
||||
|
@ -418,6 +429,13 @@ func (wrc *Register) checkEndpoint() error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("failed to get endpoint %s/%s: %v", config.KyvernoNamespace(), config.KyvernoServiceName(), err)
|
||||
}
|
||||
deploy, err := wrc.GetKubePolicyDeployment()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tlsutils.IsKyvernoInRollingUpdate(deploy) {
|
||||
return errors.New("kyverno is in rolling update, please update the timeout by setting the webhookRegistrationTimeout flag")
|
||||
}
|
||||
selector := &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"app.kubernetes.io/name": kyvernov1.ValueKyvernoApp,
|
||||
|
|
|
@ -21,7 +21,7 @@ type handlers struct {
|
|||
openAPIController *openapi.Controller
|
||||
}
|
||||
|
||||
func NewHandlers(client dclient.Interface, openAPIController *openapi.Controller) webhooks.Handlers {
|
||||
func NewHandlers(client dclient.Interface, openAPIController *openapi.Controller) webhooks.PolicyHandlers {
|
||||
return &handlers{
|
||||
client: client,
|
||||
openAPIController: openAPIController,
|
||||
|
|
|
@ -21,7 +21,7 @@ import (
|
|||
"k8s.io/client-go/kubernetes/fake"
|
||||
)
|
||||
|
||||
func NewFakeHandlers(ctx context.Context, policyCache policycache.Cache) webhooks.Handlers {
|
||||
func NewFakeHandlers(ctx context.Context, policyCache policycache.Cache) webhooks.ResourceHandlers {
|
||||
client := fake.NewSimpleClientset()
|
||||
metricsConfig := metrics.NewFakeMetricsConfig(client)
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ func NewHandlers(
|
|||
eventGen event.Interface,
|
||||
auditHandler audit.AuditHandler,
|
||||
openAPIController openapi.ValidateInterface,
|
||||
) webhooks.Handlers {
|
||||
) webhooks.ResourceHandlers {
|
||||
return &handlers{
|
||||
client: client,
|
||||
kyvernoClient: kyvernoClient,
|
||||
|
@ -96,7 +96,7 @@ func NewHandlers(
|
|||
}
|
||||
}
|
||||
|
||||
func (h *handlers) Validate(logger logr.Logger, request *admissionv1.AdmissionRequest, startTime time.Time) *admissionv1.AdmissionResponse {
|
||||
func (h *handlers) Validate(logger logr.Logger, request *admissionv1.AdmissionRequest, failurePolicy string, startTime time.Time) *admissionv1.AdmissionResponse {
|
||||
if webhookutils.ExcludeKyvernoResources(request.Kind.Kind) {
|
||||
return admissionutils.ResponseSuccess()
|
||||
}
|
||||
|
@ -105,10 +105,10 @@ func (h *handlers) Validate(logger logr.Logger, request *admissionv1.AdmissionRe
|
|||
logger.V(4).Info("received an admission request in validating webhook")
|
||||
|
||||
// timestamp at which this admission request got triggered
|
||||
policies := h.pCache.GetPolicies(policycache.ValidateEnforce, kind, request.Namespace)
|
||||
mutatePolicies := h.pCache.GetPolicies(policycache.Mutate, kind, request.Namespace)
|
||||
generatePolicies := h.pCache.GetPolicies(policycache.Generate, kind, request.Namespace)
|
||||
imageVerifyValidatePolicies := h.pCache.GetPolicies(policycache.VerifyImagesValidate, kind, request.Namespace)
|
||||
policies := filterPolicies(failurePolicy, h.pCache.GetPolicies(policycache.ValidateEnforce, kind, request.Namespace)...)
|
||||
mutatePolicies := filterPolicies(failurePolicy, h.pCache.GetPolicies(policycache.Mutate, kind, request.Namespace)...)
|
||||
generatePolicies := filterPolicies(failurePolicy, h.pCache.GetPolicies(policycache.Generate, kind, request.Namespace)...)
|
||||
imageVerifyValidatePolicies := filterPolicies(failurePolicy, h.pCache.GetPolicies(policycache.VerifyImagesValidate, kind, request.Namespace)...)
|
||||
policies = append(policies, imageVerifyValidatePolicies...)
|
||||
|
||||
if len(policies) == 0 && len(mutatePolicies) == 0 && len(generatePolicies) == 0 {
|
||||
|
@ -152,7 +152,7 @@ func (h *handlers) Validate(logger logr.Logger, request *admissionv1.AdmissionRe
|
|||
return admissionutils.ResponseSuccess()
|
||||
}
|
||||
|
||||
func (h *handlers) Mutate(logger logr.Logger, request *admissionv1.AdmissionRequest, startTime time.Time) *admissionv1.AdmissionResponse {
|
||||
func (h *handlers) Mutate(logger logr.Logger, request *admissionv1.AdmissionRequest, failurePolicy string, startTime time.Time) *admissionv1.AdmissionResponse {
|
||||
if webhookutils.ExcludeKyvernoResources(request.Kind.Kind) {
|
||||
return admissionutils.ResponseSuccess()
|
||||
}
|
||||
|
@ -162,8 +162,8 @@ func (h *handlers) Mutate(logger logr.Logger, request *admissionv1.AdmissionRequ
|
|||
kind := request.Kind.Kind
|
||||
logger = logger.WithValues("kind", kind)
|
||||
logger.V(4).Info("received an admission request in mutating webhook")
|
||||
mutatePolicies := h.pCache.GetPolicies(policycache.Mutate, kind, request.Namespace)
|
||||
verifyImagesPolicies := h.pCache.GetPolicies(policycache.VerifyImagesMutate, kind, request.Namespace)
|
||||
mutatePolicies := filterPolicies(failurePolicy, h.pCache.GetPolicies(policycache.Mutate, kind, request.Namespace)...)
|
||||
verifyImagesPolicies := filterPolicies(failurePolicy, h.pCache.GetPolicies(policycache.VerifyImagesMutate, kind, request.Namespace)...)
|
||||
if len(mutatePolicies) == 0 && len(verifyImagesPolicies) == 0 {
|
||||
logger.V(4).Info("no policies matched mutate admission request")
|
||||
return admissionutils.ResponseSuccess()
|
||||
|
@ -226,3 +226,21 @@ func (h *handlers) handleDelete(logger logr.Logger, request *admissionv1.Admissi
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func filterPolicies(failurePolicy string, policies ...kyvernov1.PolicyInterface) []kyvernov1.PolicyInterface {
|
||||
var results []kyvernov1.PolicyInterface
|
||||
for _, policy := range policies {
|
||||
if failurePolicy == "fail" {
|
||||
if policy.GetSpec().GetFailurePolicy() == kyvernov1.Fail {
|
||||
results = append(results, policy)
|
||||
}
|
||||
} else if failurePolicy == "ignore" {
|
||||
if policy.GetSpec().GetFailurePolicy() == kyvernov1.Ignore {
|
||||
results = append(results, policy)
|
||||
}
|
||||
} else {
|
||||
results = append(results, policy)
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
|
|
@ -176,18 +176,18 @@ func Test_AdmissionResponseValid(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
response := handlers.Mutate(logger, request, time.Now())
|
||||
response := handlers.Mutate(logger, request, "", time.Now())
|
||||
assert.Assert(t, response != nil)
|
||||
assert.Equal(t, response.Allowed, true)
|
||||
|
||||
response = handlers.Validate(logger, request, time.Now())
|
||||
response = handlers.Validate(logger, request, "", time.Now())
|
||||
assert.Equal(t, response.Allowed, true)
|
||||
assert.Equal(t, len(response.Warnings), 0)
|
||||
|
||||
validPolicy.Spec.ValidationFailureAction = kyverno.Enforce
|
||||
policyCache.Set(key, &validPolicy)
|
||||
|
||||
response = handlers.Validate(logger, request, time.Now())
|
||||
response = handlers.Validate(logger, request, "", time.Now())
|
||||
assert.Equal(t, response.Allowed, false)
|
||||
assert.Equal(t, len(response.Warnings), 0)
|
||||
|
||||
|
@ -220,7 +220,7 @@ func Test_AdmissionResponseInvalid(t *testing.T) {
|
|||
invalidPolicy.Spec.ValidationFailureAction = kyverno.Enforce
|
||||
policyCache.Set(keyInvalid, &invalidPolicy)
|
||||
|
||||
response := handlers.Validate(logger, request, time.Now())
|
||||
response := handlers.Validate(logger, request, "", time.Now())
|
||||
assert.Equal(t, response.Allowed, false)
|
||||
assert.Equal(t, len(response.Warnings), 0)
|
||||
|
||||
|
@ -228,7 +228,7 @@ func Test_AdmissionResponseInvalid(t *testing.T) {
|
|||
invalidPolicy.Spec.FailurePolicy = &ignore
|
||||
policyCache.Set(keyInvalid, &invalidPolicy)
|
||||
|
||||
response = handlers.Validate(logger, request, time.Now())
|
||||
response = handlers.Validate(logger, request, "", time.Now())
|
||||
assert.Equal(t, response.Allowed, true)
|
||||
assert.Equal(t, len(response.Warnings), 1)
|
||||
}
|
||||
|
@ -261,7 +261,7 @@ func Test_ImageVerify(t *testing.T) {
|
|||
policy.Spec.ValidationFailureAction = kyverno.Enforce
|
||||
policyCache.Set(key, &policy)
|
||||
|
||||
response := handlers.Mutate(logger, request, time.Now())
|
||||
response := handlers.Mutate(logger, request, "", time.Now())
|
||||
assert.Equal(t, response.Allowed, false)
|
||||
assert.Equal(t, len(response.Warnings), 0)
|
||||
|
||||
|
@ -269,7 +269,7 @@ func Test_ImageVerify(t *testing.T) {
|
|||
policy.Spec.FailurePolicy = &ignore
|
||||
policyCache.Set(key, &policy)
|
||||
|
||||
response = handlers.Mutate(logger, request, time.Now())
|
||||
response = handlers.Mutate(logger, request, "", time.Now())
|
||||
assert.Equal(t, response.Allowed, false)
|
||||
assert.Equal(t, len(response.Warnings), 0)
|
||||
}
|
||||
|
|
|
@ -28,13 +28,20 @@ type Server interface {
|
|||
Stop(context.Context)
|
||||
}
|
||||
|
||||
type Handlers interface {
|
||||
type PolicyHandlers interface {
|
||||
// Mutate performs the mutation of policy resources
|
||||
Mutate(logr.Logger, *admissionv1.AdmissionRequest, time.Time) *admissionv1.AdmissionResponse
|
||||
// Validate performs the validation check on policy resources
|
||||
Validate(logr.Logger, *admissionv1.AdmissionRequest, time.Time) *admissionv1.AdmissionResponse
|
||||
}
|
||||
|
||||
type ResourceHandlers interface {
|
||||
// Mutate performs the mutation of kube resources
|
||||
Mutate(logr.Logger, *admissionv1.AdmissionRequest, string, time.Time) *admissionv1.AdmissionResponse
|
||||
// Validate performs the validation check on kube resources
|
||||
Validate(logr.Logger, *admissionv1.AdmissionRequest, string, time.Time) *admissionv1.AdmissionResponse
|
||||
}
|
||||
|
||||
type server struct {
|
||||
server *http.Server
|
||||
webhookRegister *webhookconfig.Register
|
||||
|
@ -45,8 +52,8 @@ type TlsProvider func() ([]byte, []byte, error)
|
|||
|
||||
// NewServer creates new instance of server accordingly to given configuration
|
||||
func NewServer(
|
||||
policyHandlers Handlers,
|
||||
resourceHandlers Handlers,
|
||||
policyHandlers PolicyHandlers,
|
||||
resourceHandlers ResourceHandlers,
|
||||
tlsProvider TlsProvider,
|
||||
configuration config.Configuration,
|
||||
register *webhookconfig.Register,
|
||||
|
@ -57,8 +64,8 @@ func NewServer(
|
|||
resourceLogger := logger.WithName("resource")
|
||||
policyLogger := logger.WithName("policy")
|
||||
verifyLogger := logger.WithName("verify")
|
||||
mux.HandlerFunc("POST", config.MutatingWebhookServicePath, admission(resourceLogger.WithName("mutate"), monitor, filter(configuration, resourceHandlers.Mutate)))
|
||||
mux.HandlerFunc("POST", config.ValidatingWebhookServicePath, admission(resourceLogger.WithName("validate"), monitor, filter(configuration, resourceHandlers.Validate)))
|
||||
registerWebhookHandlers(resourceLogger.WithName("mutate"), mux, config.MutatingWebhookServicePath, monitor, configuration, resourceHandlers.Mutate)
|
||||
registerWebhookHandlers(resourceLogger.WithName("validate"), mux, config.ValidatingWebhookServicePath, monitor, configuration, resourceHandlers.Validate)
|
||||
mux.HandlerFunc("POST", config.PolicyMutatingWebhookServicePath, admission(policyLogger.WithName("mutate"), monitor, filter(configuration, policyHandlers.Mutate)))
|
||||
mux.HandlerFunc("POST", config.PolicyValidatingWebhookServicePath, admission(policyLogger.WithName("validate"), monitor, filter(configuration, policyHandlers.Validate)))
|
||||
mux.HandlerFunc("POST", config.VerifyMutatingWebhookServicePath, admission(verifyLogger.WithName("mutate"), monitor, handlers.Verify(monitor)))
|
||||
|
@ -153,3 +160,31 @@ func filter(configuration config.Configuration, inner handlers.AdmissionHandler)
|
|||
func admission(logger logr.Logger, monitor *webhookconfig.Monitor, inner handlers.AdmissionHandler) http.HandlerFunc {
|
||||
return handlers.Monitor(monitor, handlers.Admission(logger, protect(inner)))
|
||||
}
|
||||
|
||||
func registerWebhookHandlers(
|
||||
logger logr.Logger,
|
||||
mux *httprouter.Router,
|
||||
basePath string,
|
||||
monitor *webhookconfig.Monitor,
|
||||
configuration config.Configuration,
|
||||
handlerFunc func(logr.Logger, *admissionv1.AdmissionRequest, string, time.Time) *admissionv1.AdmissionResponse,
|
||||
) {
|
||||
mux.HandlerFunc("POST", basePath, admission(logger, monitor, filter(
|
||||
configuration,
|
||||
func(logger logr.Logger, request *admissionv1.AdmissionRequest, startTime time.Time) *admissionv1.AdmissionResponse {
|
||||
return handlerFunc(logger, request, "all", startTime)
|
||||
})),
|
||||
)
|
||||
mux.HandlerFunc("POST", basePath+"/fail", admission(logger, monitor, filter(
|
||||
configuration,
|
||||
func(logger logr.Logger, request *admissionv1.AdmissionRequest, startTime time.Time) *admissionv1.AdmissionResponse {
|
||||
return handlerFunc(logger, request, "fail", startTime)
|
||||
})),
|
||||
)
|
||||
mux.HandlerFunc("POST", basePath+"/ignore", admission(logger, monitor, filter(
|
||||
configuration,
|
||||
func(logger logr.Logger, request *admissionv1.AdmissionRequest, startTime time.Time) *admissionv1.AdmissionResponse {
|
||||
return handlerFunc(logger, request, "ignore", startTime)
|
||||
})),
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue