@@ -31,6 +31,8 @@ import (
3131 logf "sigs.k8s.io/controller-runtime/pkg/log"
3232 "sigs.k8s.io/controller-runtime/pkg/webhook"
3333 "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
34+
35+ batchv1 "tutorial.kubebuilder.io/project/api/v1"
3436)
3537
3638// +kubebuilder:docs-gen:collapse=Go imports
@@ -45,13 +47,12 @@ var cronjoblog = logf.Log.WithName("cronjob-resource")
4547Then, we set up the webhook with the manager.
4648*/
4749
48- // SetupWebhookWithManager will setup the manager to manage the webhooks.
49- func (r * CronJob ) SetupWebhookWithManager (mgr ctrl.Manager ) error {
50- return ctrl .NewWebhookManagedBy (mgr ).
51- For (r ).
50+ // SetupCronJobWebhookWithManager registers the webhook for CronJob in the manager.
51+ func SetupCronJobWebhookWithManager (mgr ctrl.Manager ) error {
52+ return ctrl .NewWebhookManagedBy (mgr ).For (& batchv1.CronJob {}).
5253 WithValidator (& CronJobCustomValidator {}).
5354 WithDefaulter (& CronJobCustomDefaulter {
54- DefaultConcurrencyPolicy : AllowConcurrent ,
55+ DefaultConcurrencyPolicy : batchv1 . AllowConcurrent ,
5556 DefaultSuspend : false ,
5657 DefaultSuccessfulJobsHistoryLimit : 3 ,
5758 DefaultFailedJobsHistoryLimit : 1 ,
@@ -66,7 +67,7 @@ This marker is responsible for generating a mutating webhook manifest.
6667The meaning of each marker can be found [here](/reference/markers/webhook.md).
6768*/
6869
69- // +kubebuilder:webhook:path=/mutate-batch-tutorial-kubebuilder-io-v1-cronjob,mutating=true,failurePolicy=fail,groups=batch.tutorial.kubebuilder.io,resources=cronjobs,verbs=create;update,versions=v1,name=mcronjob.kb.io,sideEffects=None,admissionReviewVersions=v1
70+ // +kubebuilder:webhook:path=/mutate-batch-tutorial-kubebuilder-io-v1-cronjob,mutating=true,failurePolicy=fail,groups=batch.tutorial.kubebuilder.io,resources=cronjobs,verbs=create;update,versions=v1,name=mcronjob-v1 .kb.io,sideEffects=None,admissionReviewVersions=v1
7071
7172/*
7273We use the `webhook.CustomDefaulter` interface to set defaults to our CRD.
@@ -86,7 +87,7 @@ The `Default` method is expected to mutate the receiver, setting the defaults.
8687type CronJobCustomDefaulter struct {
8788
8889 // Default values for various CronJob fields
89- DefaultConcurrencyPolicy ConcurrencyPolicy
90+ DefaultConcurrencyPolicy batchv1. ConcurrencyPolicy
9091 DefaultSuspend bool
9192 DefaultSuccessfulJobsHistoryLimit int32
9293 DefaultFailedJobsHistoryLimit int32
@@ -96,40 +97,42 @@ var _ webhook.CustomDefaulter = &CronJobCustomDefaulter{}
9697
9798// Default implements webhook.CustomDefaulter so a webhook will be registered for the Kind CronJob.
9899func (d * CronJobCustomDefaulter ) Default (ctx context.Context , obj runtime.Object ) error {
99- cronjob , ok := obj .(* CronJob )
100+ cronjob , ok := obj .(* batchv1.CronJob )
101+
100102 if ! ok {
101103 return fmt .Errorf ("expected an CronJob object but got %T" , obj )
102104 }
103105 cronjoblog .Info ("Defaulting for CronJob" , "name" , cronjob .GetName ())
104106
105107 // Set default values
106- cronjob .Default ()
107-
108+ d .applyDefaults (cronjob )
108109 return nil
109110}
110111
111- func (r * CronJob ) Default () {
112- if r .Spec .ConcurrencyPolicy == "" {
113- r .Spec .ConcurrencyPolicy = AllowConcurrent
112+ // applyDefaults applies default values to CronJob fields.
113+ func (d * CronJobCustomDefaulter ) applyDefaults (cronJob * batchv1.CronJob ) {
114+ if cronJob .Spec .ConcurrencyPolicy == "" {
115+ cronJob .Spec .ConcurrencyPolicy = d .DefaultConcurrencyPolicy
114116 }
115- if r .Spec .Suspend == nil {
116- r .Spec .Suspend = new (bool )
117+ if cronJob .Spec .Suspend == nil {
118+ cronJob .Spec .Suspend = new (bool )
119+ * cronJob .Spec .Suspend = d .DefaultSuspend
117120 }
118- if r .Spec .SuccessfulJobsHistoryLimit == nil {
119- r .Spec .SuccessfulJobsHistoryLimit = new (int32 )
120- * r .Spec .SuccessfulJobsHistoryLimit = 3
121+ if cronJob .Spec .SuccessfulJobsHistoryLimit == nil {
122+ cronJob .Spec .SuccessfulJobsHistoryLimit = new (int32 )
123+ * cronJob .Spec .SuccessfulJobsHistoryLimit = d . DefaultSuccessfulJobsHistoryLimit
121124 }
122- if r .Spec .FailedJobsHistoryLimit == nil {
123- r .Spec .FailedJobsHistoryLimit = new (int32 )
124- * r .Spec .FailedJobsHistoryLimit = 1
125+ if cronJob .Spec .FailedJobsHistoryLimit == nil {
126+ cronJob .Spec .FailedJobsHistoryLimit = new (int32 )
127+ * cronJob .Spec .FailedJobsHistoryLimit = d . DefaultFailedJobsHistoryLimit
125128 }
126129}
127130
128131/*
129132This marker is responsible for generating a validating webhook manifest.
130133*/
131134
132- // +kubebuilder:webhook:verbs=create;update;delete,path=/validate-batch-tutorial-kubebuilder-io-v1-cronjob,mutating=false,failurePolicy=fail,groups=batch.tutorial.kubebuilder.io,resources=cronjobs,versions=v1,name=vcronjob.kb.io,sideEffects=None,admissionReviewVersions=v1
135+ // +kubebuilder:webhook:verbs=create;update;delete,path=/validate-batch-tutorial-kubebuilder-io-v1-cronjob,mutating=false,failurePolicy=fail,groups=batch.tutorial.kubebuilder.io,resources=cronjobs,versions=v1,name=vcronjob-v1 .kb.io,sideEffects=None,admissionReviewVersions=v1
133136
134137/*
135138We can validate our CRD beyond what's possible with declarative
@@ -171,29 +174,29 @@ var _ webhook.CustomValidator = &CronJobCustomValidator{}
171174
172175// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type CronJob.
173176func (v * CronJobCustomValidator ) ValidateCreate (ctx context.Context , obj runtime.Object ) (admission.Warnings , error ) {
174- cronjob , ok := obj .(* CronJob )
177+ cronjob , ok := obj .(* batchv1. CronJob )
175178 if ! ok {
176179 return nil , fmt .Errorf ("expected a CronJob object but got %T" , obj )
177180 }
178181 cronjoblog .Info ("Validation for CronJob upon creation" , "name" , cronjob .GetName ())
179182
180- return nil , cronjob . validateCronJob ()
183+ return nil , validateCronJob (cronjob )
181184}
182185
183186// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type CronJob.
184187func (v * CronJobCustomValidator ) ValidateUpdate (ctx context.Context , oldObj , newObj runtime.Object ) (admission.Warnings , error ) {
185- cronjob , ok := newObj .(* CronJob )
188+ cronjob , ok := newObj .(* batchv1. CronJob )
186189 if ! ok {
187- return nil , fmt .Errorf ("expected a CronJob object but got %T" , newObj )
190+ return nil , fmt .Errorf ("expected a CronJob object for the newObj but got got %T" , newObj )
188191 }
189192 cronjoblog .Info ("Validation for CronJob upon update" , "name" , cronjob .GetName ())
190193
191- return nil , cronjob . validateCronJob ()
194+ return nil , validateCronJob (cronjob )
192195}
193196
194197// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type CronJob.
195198func (v * CronJobCustomValidator ) ValidateDelete (ctx context.Context , obj runtime.Object ) (admission.Warnings , error ) {
196- cronjob , ok := obj .(* CronJob )
199+ cronjob , ok := obj .(* batchv1. CronJob )
197200 if ! ok {
198201 return nil , fmt .Errorf ("expected a CronJob object but got %T" , obj )
199202 }
@@ -208,21 +211,19 @@ func (v *CronJobCustomValidator) ValidateDelete(ctx context.Context, obj runtime
208211We validate the name and the spec of the CronJob.
209212*/
210213
211- func (r * CronJob ) validateCronJob () error {
214+ // validateCronJob validates the fields of a CronJob object.
215+ func validateCronJob (cronjob * batchv1.CronJob ) error {
212216 var allErrs field.ErrorList
213- if err := r . validateCronJobName (); err != nil {
217+ if err := validateCronJobName (cronjob ); err != nil {
214218 allErrs = append (allErrs , err )
215219 }
216- if err := r . validateCronJobSpec (); err != nil {
220+ if err := validateCronJobSpec (cronjob ); err != nil {
217221 allErrs = append (allErrs , err )
218222 }
219223 if len (allErrs ) == 0 {
220224 return nil
221225 }
222-
223- return apierrors .NewInvalid (
224- schema.GroupKind {Group : "batch.tutorial.kubebuilder.io" , Kind : "CronJob" },
225- r .Name , allErrs )
226+ return apierrors .NewInvalid (schema.GroupKind {Group : "batch.tutorial.kubebuilder.io" , Kind : "CronJob" }, cronjob .Name , allErrs )
226227}
227228
228229/*
@@ -235,19 +236,17 @@ declaring validation by running `controller-gen crd -w`,
235236or [here](/reference/markers/crd-validation.md).
236237*/
237238
238- func (r * CronJob ) validateCronJobSpec () * field.Error {
239- // The field helpers from the kubernetes API machinery help us return nicely
240- // structured validation errors.
241- return validateScheduleFormat (
242- r .Spec .Schedule ,
243- field .NewPath ("spec" ).Child ("schedule" ))
239+ // validateCronJobSpec validates the schedule field of the CronJob spec.
240+ func validateCronJobSpec (cronjob * batchv1.CronJob ) * field.Error {
241+ return validateScheduleFormat (cronjob .Spec .Schedule , field .NewPath ("spec" ).Child ("schedule" ))
244242}
245243
246244/*
247245We'll need to validate the [cron](https://en.wikipedia.org/wiki/Cron) schedule
248246is well-formatted.
249247*/
250248
249+ // validateScheduleFormat validates that the schedule field follows the cron format.
251250func validateScheduleFormat (schedule string , fldPath * field.Path ) * field.Error {
252251 if _ , err := cron .ParseStandard (schedule ); err != nil {
253252 return field .Invalid (fldPath , schedule , err .Error ())
@@ -264,15 +263,10 @@ the apimachinery repo, so we can't declaratively validate it using
264263the validation schema.
265264*/
266265
267- func (r * CronJob ) validateCronJobName () * field.Error {
268- if len (r .ObjectMeta .Name ) > validationutils .DNS1035LabelMaxLength - 11 {
269- // The job name length is 63 characters like all Kubernetes objects
270- // (which must fit in a DNS subdomain). The cronjob controller appends
271- // a 11-character suffix to the cronjob (`-$TIMESTAMP`) when creating
272- // a job. The job name length limit is 63 characters. Therefore cronjob
273- // names must have length <= 63-11=52. If we don't validate this here,
274- // then job creation will fail later.
275- return field .Invalid (field .NewPath ("metadata" ).Child ("name" ), r .ObjectMeta .Name , "must be no more than 52 characters" )
266+ // validateCronJobName validates the name of the CronJob object.
267+ func validateCronJobName (cronjob * batchv1.CronJob ) * field.Error {
268+ if len (cronjob .ObjectMeta .Name ) > validationutils .DNS1035LabelMaxLength - 11 {
269+ return field .Invalid (field .NewPath ("metadata" ).Child ("name" ), cronjob .ObjectMeta .Name , "must be no more than 52 characters" )
276270 }
277271 return nil
278272}
0 commit comments