@@ -18,12 +18,15 @@ limitations under the License.
1818package v1
1919
2020import (
21+ "context"
22+ "fmt"
2123 "github.com/robfig/cron"
2224 apierrors "k8s.io/apimachinery/pkg/api/errors"
23- "k8s.io/apimachinery/pkg/runtime"
2425 "k8s.io/apimachinery/pkg/runtime/schema"
2526 validationutils "k8s.io/apimachinery/pkg/util/validation"
2627 "k8s.io/apimachinery/pkg/util/validation/field"
28+
29+ "k8s.io/apimachinery/pkg/runtime"
2730 ctrl "sigs.k8s.io/controller-runtime"
2831 logf "sigs.k8s.io/controller-runtime/pkg/log"
2932 "sigs.k8s.io/controller-runtime/pkg/webhook"
@@ -46,6 +49,13 @@ Then, we set up the webhook with the manager.
4649func (r * CronJob ) SetupWebhookWithManager (mgr ctrl.Manager ) error {
4750 return ctrl .NewWebhookManagedBy (mgr ).
4851 For (r ).
52+ WithValidator (& CronJobCustomValidator {}).
53+ WithDefaulter (& CronJobCustomDefaulter {
54+ DefaultConcurrencyPolicy : AllowConcurrent ,
55+ DefaultSuspend : false ,
56+ DefaultSuccessfulJobsHistoryLimit : 3 ,
57+ DefaultFailedJobsHistoryLimit : 1 ,
58+ }).
4959 Complete ()
5060}
5161
@@ -59,32 +69,53 @@ The meaning of each marker can be found [here](/reference/markers/webhook.md).
5969// +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
6070
6171/*
62- We use the `webhook.Defaulter ` interface to set defaults to our CRD.
72+ We use the `webhook.CustomDefaulter ` interface to set defaults to our CRD.
6373A webhook will automatically be served that calls this defaulting.
6474
6575The `Default` method is expected to mutate the receiver, setting the defaults.
6676*/
6777
68- var _ webhook.Defaulter = & CronJob {}
78+ // +kubebuilder:object:generate=false
79+ // CronJobCustomDefaulter struct is responsible for setting default values on the custom resource of the
80+ // Kind CronJob when those are created or updated.
81+ //
82+ // NOTE: The +kubebuilder:object:generate=false marker prevents controller-gen from generating DeepCopy methods,
83+ // as it is used only for temporary operations and does not need to be deeply copied.
84+ type CronJobCustomDefaulter struct {
85+
86+ // Default values for various CronJob fields
87+ DefaultConcurrencyPolicy ConcurrencyPolicy
88+ DefaultSuspend bool
89+ DefaultSuccessfulJobsHistoryLimit int32
90+ DefaultFailedJobsHistoryLimit int32
91+ }
6992
70- // Default implements webhook.Defaulter so a webhook will be registered for the type
71- func (r * CronJob ) Default () {
72- cronjoblog .Info ("default" , "name" , r .Name )
93+ var _ webhook.CustomDefaulter = & CronJobCustomDefaulter {}
7394
74- if r .Spec .ConcurrencyPolicy == "" {
75- r .Spec .ConcurrencyPolicy = AllowConcurrent
95+ // Default implements webhook.CustomDefaulter so a webhook will be registered for the Kind CronJob
96+ func (d * CronJobCustomDefaulter ) Default (ctx context.Context , obj runtime.Object ) error {
97+ cronjob , ok := obj .(* CronJob )
98+ if ! ok {
99+ return fmt .Errorf ("expected an CronJob object but got %T" , obj )
76100 }
77- if r .Spec .Suspend == nil {
78- r .Spec .Suspend = new (bool )
101+ cronjoblog .Info ("Defaulting for CronJob" , "name" , cronjob .GetName ())
102+
103+ if cronjob .Spec .ConcurrencyPolicy == "" {
104+ cronjob .Spec .ConcurrencyPolicy = AllowConcurrent
105+ }
106+ if cronjob .Spec .Suspend == nil {
107+ cronjob .Spec .Suspend = new (bool )
79108 }
80- if r .Spec .SuccessfulJobsHistoryLimit == nil {
81- r .Spec .SuccessfulJobsHistoryLimit = new (int32 )
82- * r .Spec .SuccessfulJobsHistoryLimit = 3
109+ if cronjob .Spec .SuccessfulJobsHistoryLimit == nil {
110+ cronjob .Spec .SuccessfulJobsHistoryLimit = new (int32 )
111+ * cronjob .Spec .SuccessfulJobsHistoryLimit = 3
83112 }
84- if r .Spec .FailedJobsHistoryLimit == nil {
85- r .Spec .FailedJobsHistoryLimit = new (int32 )
86- * r .Spec .FailedJobsHistoryLimit = 1
113+ if cronjob .Spec .FailedJobsHistoryLimit == nil {
114+ cronjob .Spec .FailedJobsHistoryLimit = new (int32 )
115+ * cronjob .Spec .FailedJobsHistoryLimit = 1
87116 }
117+
118+ return nil
88119}
89120
90121/*
@@ -101,7 +132,7 @@ sometimes more advanced use cases call for complex validation.
101132For instance, we'll see below that we use this to validate a well-formed cron
102133schedule without making up a long regular expression.
103134
104- If `webhook.Validator ` interface is implemented, a webhook will automatically be
135+ If `webhook.CustomValidator ` interface is implemented, a webhook will automatically be
105136served that calls the validation.
106137
107138The `ValidateCreate`, `ValidateUpdate` and `ValidateDelete` methods are expected
@@ -118,27 +149,50 @@ validate anything on deletion.
118149// NOTE: The 'path' attribute must follow a specific pattern and should not be modified directly here.
119150// Modifying the path for an invalid path can cause API server errors; failing to locate the webhook.
120151
121- var _ webhook.Validator = & CronJob {}
152+ // +kubebuilder:object:generate=false
153+ // CronJobCustomValidator struct is responsible for validating the CronJob resource
154+ // when it is created, updated, or deleted.
155+ //
156+ // NOTE: The +kubebuilder:object:generate=false marker prevents controller-gen from generating DeepCopy methods,
157+ // as this struct is used only for temporary operations and does not need to be deeply copied.
158+ type CronJobCustomValidator struct {
159+ //TODO(user): Add more fields as needed for validation
160+ }
161+
162+ var _ webhook.CustomValidator = & CronJobCustomValidator {}
122163
123- // ValidateCreate implements webhook.Validator so a webhook will be registered for the type
124- func (r * CronJob ) ValidateCreate () (admission.Warnings , error ) {
125- cronjoblog .Info ("validate create" , "name" , r .Name )
164+ // ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type CronJob
165+ func (v * CronJobCustomValidator ) ValidateCreate (ctx context.Context , obj runtime.Object ) (admission.Warnings , error ) {
166+ cronjob , ok := obj .(* CronJob )
167+ if ! ok {
168+ return nil , fmt .Errorf ("expected a CronJob object but got %T" , obj )
169+ }
170+ cronjoblog .Info ("Validation for CronJob upon creation" , "name" , cronjob .GetName ())
126171
127- return nil , r .validateCronJob ()
172+ return nil , cronjob .validateCronJob ()
128173}
129174
130- // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
131- func (r * CronJob ) ValidateUpdate (old runtime.Object ) (admission.Warnings , error ) {
132- cronjoblog .Info ("validate update" , "name" , r .Name )
175+ // ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type CronJob
176+ func (v * CronJobCustomValidator ) ValidateUpdate (ctx context.Context , oldObj , newObj runtime.Object ) (admission.Warnings , error ) {
177+ cronjob , ok := newObj .(* CronJob )
178+ if ! ok {
179+ return nil , fmt .Errorf ("expected a CronJob object but got %T" , newObj )
180+ }
181+ cronjoblog .Info ("Validation for CronJob upon update" , "name" , cronjob .GetName ())
133182
134- return nil , r .validateCronJob ()
183+ return nil , cronjob .validateCronJob ()
135184}
136185
137- // ValidateDelete implements webhook.Validator so a webhook will be registered for the type
138- func (r * CronJob ) ValidateDelete () (admission.Warnings , error ) {
139- cronjoblog .Info ("validate delete" , "name" , r .Name )
186+ // ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type CronJob
187+ func (v * CronJobCustomValidator ) ValidateDelete (ctx context.Context , obj runtime.Object ) (admission.Warnings , error ) {
188+ cronjob , ok := obj .(* CronJob )
189+ if ! ok {
190+ return nil , fmt .Errorf ("expected a CronJob object but got %T" , obj )
191+ }
192+ cronjoblog .Info ("Validation for CronJob upon deletion" , "name" , cronjob .GetName ())
140193
141194 // TODO(user): fill in your validation logic upon object deletion.
195+
142196 return nil , nil
143197}
144198
@@ -204,13 +258,13 @@ the validation schema.
204258
205259func (r * CronJob ) validateCronJobName () * field.Error {
206260 if len (r .ObjectMeta .Name ) > validationutils .DNS1035LabelMaxLength - 11 {
207- // The job name length is 63 character like all Kubernetes objects
261+ // The job name length is 63 characters like all Kubernetes objects
208262 // (which must fit in a DNS subdomain). The cronjob controller appends
209263 // a 11-character suffix to the cronjob (`-$TIMESTAMP`) when creating
210264 // a job. The job name length limit is 63 characters. Therefore cronjob
211265 // names must have length <= 63-11=52. If we don't validate this here,
212266 // then job creation will fail later.
213- return field .Invalid (field .NewPath ("metadata" ).Child ("name" ), r .Name , "must be no more than 52 characters" )
267+ return field .Invalid (field .NewPath ("metadata" ).Child ("name" ), r .ObjectMeta . Name , "must be no more than 52 characters" )
214268 }
215269 return nil
216270}
0 commit comments