From e98485d216a58a5804c9cd37ed9b07bc3a7f6ea8 Mon Sep 17 00:00:00 2001 From: Mikko Ylinen Date: Tue, 26 Jul 2022 13:17:25 +0300 Subject: [PATCH] pkg/webhook: add support for reinvocationPolicy marker Mutating webhooks using controller-gen markers for generating MutatingWebhookConfigration cannot control reinvocationPolicy. This field must always be added manually afterwards should the webhook need to set its value. Add support for reinvocationPolicy marker for Mutating Webhooks. Signed-off-by: Mikko Ylinen --- pkg/webhook/parser.go | 25 ++++++++++++++++++++++- pkg/webhook/testdata/manifests.yaml | 1 + pkg/webhook/testdata/valid/manifests.yaml | 1 + pkg/webhook/testdata/valid/webhook.go | 2 +- pkg/webhook/testdata/webhook.go | 2 +- pkg/webhook/zz_generated.markerhelp.go | 4 ++++ 6 files changed, 32 insertions(+), 3 deletions(-) diff --git a/pkg/webhook/parser.go b/pkg/webhook/parser.go index 392acfc77..21e0e3d40 100644 --- a/pkg/webhook/parser.go +++ b/pkg/webhook/parser.go @@ -19,7 +19,7 @@ limitations under the License. // // The markers take the form: // -// +kubebuilder:webhook:webhookVersions=<[]string>,failurePolicy=,matchPolicy=,groups=<[]string>,resources=<[]string>,verbs=<[]string>,versions=<[]string>,name=,path=,mutating=,sideEffects=,admissionReviewVersions=<[]string> +// +kubebuilder:webhook:webhookVersions=<[]string>,failurePolicy=,matchPolicy=,groups=<[]string>,resources=<[]string>,verbs=<[]string>,versions=<[]string>,name=,path=,mutating=,sideEffects=,admissionReviewVersions=<[]string>,reinvocationPolicy= package webhook import ( @@ -111,6 +111,14 @@ type Config struct { // AdmissionReviewVersions is an ordered list of preferred `AdmissionReview` // versions the Webhook expects. AdmissionReviewVersions []string `marker:"admissionReviewVersions"` + + // ReinvocationPolicy allows mutating webhooks to request reinvocation after other mutations + // + // To allow mutating admission plugins to observe changes made by other plugins, + // built-in mutating admission plugins are re-run if a mutating webhook modifies + // an object, and mutating webhooks can specify a reinvocationPolicy to control + // whether they are reinvoked as well. + ReinvocationPolicy string `marker:"reinvocationPolicy,optional"` } // verbToAPIVariant converts a marker's verb to the proper value for the API. @@ -151,6 +159,7 @@ func (c Config) ToMutatingWebhook() (admissionregv1.MutatingWebhook, error) { ClientConfig: c.clientConfig(), SideEffects: c.sideEffects(), AdmissionReviewVersions: c.AdmissionReviewVersions, + ReinvocationPolicy: c.reinvocationPolicy(), }, nil } @@ -263,6 +272,20 @@ func (c Config) sideEffects() *admissionregv1.SideEffectClass { return &sideEffects } +// reinvocationPolicy returns the reinvocationPolicy config for a mutating webhook. +func (c Config) reinvocationPolicy() *admissionregv1.ReinvocationPolicyType { + var reinvocationPolicy admissionregv1.ReinvocationPolicyType + switch strings.ToLower(c.ReinvocationPolicy) { + case strings.ToLower(string(admissionregv1.NeverReinvocationPolicy)): + reinvocationPolicy = admissionregv1.NeverReinvocationPolicy + case strings.ToLower(string(admissionregv1.IfNeededReinvocationPolicy)): + reinvocationPolicy = admissionregv1.IfNeededReinvocationPolicy + default: + return nil + } + return &reinvocationPolicy +} + // webhookVersions returns the target API versions of the {Mutating,Validating}WebhookConfiguration objects for a webhook. func (c Config) webhookVersions() ([]string, error) { // If WebhookVersions is not specified, we default it to `v1`. diff --git a/pkg/webhook/testdata/manifests.yaml b/pkg/webhook/testdata/manifests.yaml index 059794d6d..ab4fdc85f 100644 --- a/pkg/webhook/testdata/manifests.yaml +++ b/pkg/webhook/testdata/manifests.yaml @@ -16,6 +16,7 @@ webhooks: failurePolicy: Fail matchPolicy: Equivalent name: default.cronjob.testdata.kubebuilder.io + reinvocationPolicy: Never rules: - apiGroups: - testdata.kubebuiler.io diff --git a/pkg/webhook/testdata/valid/manifests.yaml b/pkg/webhook/testdata/valid/manifests.yaml index 059794d6d..ce3836ddd 100644 --- a/pkg/webhook/testdata/valid/manifests.yaml +++ b/pkg/webhook/testdata/valid/manifests.yaml @@ -27,6 +27,7 @@ webhooks: resources: - cronjobs sideEffects: None + reinvocationPolicy: IfNeeded --- apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration diff --git a/pkg/webhook/testdata/valid/webhook.go b/pkg/webhook/testdata/valid/webhook.go index d964c493a..2ea3c31d2 100644 --- a/pkg/webhook/testdata/valid/webhook.go +++ b/pkg/webhook/testdata/valid/webhook.go @@ -29,7 +29,7 @@ func (c *CronJob) SetupWebhookWithManager(mgr ctrl.Manager) error { // +kubebuilder:webhook:webhookVersions=v1,verbs=create;update,path=/validate-testdata-kubebuilder-io-v1-cronjob,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=testdata.kubebuiler.io,resources=cronjobs,versions=v1,name=validation.cronjob.testdata.kubebuilder.io,sideEffects=None,admissionReviewVersions=v1;v1beta1 // +kubebuilder:webhook:verbs=create;update,path=/validate-testdata-kubebuilder-io-v1-cronjob,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=testdata.kubebuiler.io,resources=cronjobs,versions=v1,name=validation.cronjob.testdata.kubebuilder.io,sideEffects=NoneOnDryRun,admissionReviewVersions=v1;v1beta1 -// +kubebuilder:webhook:webhookVersions=v1,verbs=create;update,path=/mutate-testdata-kubebuilder-io-v1-cronjob,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=testdata.kubebuiler.io,resources=cronjobs,versions=v1,name=default.cronjob.testdata.kubebuilder.io,sideEffects=None,admissionReviewVersions=v1;v1beta1 +// +kubebuilder:webhook:webhookVersions=v1,verbs=create;update,path=/mutate-testdata-kubebuilder-io-v1-cronjob,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=testdata.kubebuiler.io,resources=cronjobs,versions=v1,name=default.cronjob.testdata.kubebuilder.io,sideEffects=None,admissionReviewVersions=v1;v1beta1,reinvocationPolicy=IfNeeded var _ webhook.Defaulter = &CronJob{} var _ webhook.Validator = &CronJob{} diff --git a/pkg/webhook/testdata/webhook.go b/pkg/webhook/testdata/webhook.go index d964c493a..41a69d706 100644 --- a/pkg/webhook/testdata/webhook.go +++ b/pkg/webhook/testdata/webhook.go @@ -29,7 +29,7 @@ func (c *CronJob) SetupWebhookWithManager(mgr ctrl.Manager) error { // +kubebuilder:webhook:webhookVersions=v1,verbs=create;update,path=/validate-testdata-kubebuilder-io-v1-cronjob,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=testdata.kubebuiler.io,resources=cronjobs,versions=v1,name=validation.cronjob.testdata.kubebuilder.io,sideEffects=None,admissionReviewVersions=v1;v1beta1 // +kubebuilder:webhook:verbs=create;update,path=/validate-testdata-kubebuilder-io-v1-cronjob,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=testdata.kubebuiler.io,resources=cronjobs,versions=v1,name=validation.cronjob.testdata.kubebuilder.io,sideEffects=NoneOnDryRun,admissionReviewVersions=v1;v1beta1 -// +kubebuilder:webhook:webhookVersions=v1,verbs=create;update,path=/mutate-testdata-kubebuilder-io-v1-cronjob,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=testdata.kubebuiler.io,resources=cronjobs,versions=v1,name=default.cronjob.testdata.kubebuilder.io,sideEffects=None,admissionReviewVersions=v1;v1beta1 +// +kubebuilder:webhook:webhookVersions=v1,verbs=create;update,path=/mutate-testdata-kubebuilder-io-v1-cronjob,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=testdata.kubebuiler.io,resources=cronjobs,versions=v1,name=default.cronjob.testdata.kubebuilder.io,sideEffects=None,admissionReviewVersions=v1;v1beta1,reinvocationPolicy=Never var _ webhook.Defaulter = &CronJob{} var _ webhook.Validator = &CronJob{} diff --git a/pkg/webhook/zz_generated.markerhelp.go b/pkg/webhook/zz_generated.markerhelp.go index 2a34608e8..411c58e17 100644 --- a/pkg/webhook/zz_generated.markerhelp.go +++ b/pkg/webhook/zz_generated.markerhelp.go @@ -81,6 +81,10 @@ func (Config) Help() *markers.DefinitionHelp { Summary: "is an ordered list of preferred `AdmissionReview` versions the Webhook expects.", Details: "", }, + "ReinvocationPolicy": { + Summary: "allows mutating webhooks to request reinvocation after other mutations ", + Details: "To allow mutating admission plugins to observe changes made by other plugins, built-in mutating admission plugins are re-run if a mutating webhook modifies an object, and mutating webhooks can specify a reinvocationPolicy to control whether they are reinvoked as well.", + }, }, } }