Skip to content

Commit c477981

Browse files
feat: add implementation to generate multiversion sample with make generate
All our samples and documentation are automatically updated through the build process. However, the logic for handling multiversion samples was missing. This commit adds the necessary implementation to ensure multiversion samples are generated correctly using `make generate`. Co-Author: sarthaksarthak9 <sarthaknegi908@gmail.com>
1 parent 7d96796 commit c477981

28 files changed

+1380
-9787
lines changed

docs/book/src/multiversion-tutorial/testdata/generate_multiversion.sh

Lines changed: 0 additions & 65 deletions
This file was deleted.

docs/book/src/multiversion-tutorial/testdata/project/Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,11 @@ help: ## Display this help.
4545

4646
.PHONY: manifests
4747
manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
48-
$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
48+
# Note that the option maxDescLen=0 was added in the default scaffold in order to sort out the issue
49+
# Too long: must have at most 262144 bytes. By using kubectl apply to create / update resources an annotation
50+
# is created by K8s API to store the latest version of the resource ( kubectl.kubernetes.io/last-applied-configuration).
51+
# However, it has a size limit and if the CRD is too big with so many long descriptions as this one it will cause the failure.
52+
$(CONTROLLER_GEN) rbac:roleName=manager-role crd:maxDescLen=0 webhook paths="./..." output:crd:artifacts:config=config/crd/bases
4953

5054
.PHONY: generate
5155
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.

docs/book/src/multiversion-tutorial/testdata/project/PROJECT

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ resources:
1818
path: tutorial.kubebuilder.io/project/api/v1
1919
version: v1
2020
webhooks:
21-
conversion: true
2221
defaulting: true
2322
validation: true
2423
webhookVersion: v1

docs/book/src/multiversion-tutorial/testdata/project/api/v1/cronjob_conversion.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
/*
2-
32
Licensed under the Apache License, Version 2.0 (the "License");
43
you may not use this file except in compliance with the License.
54
You may obtain a copy of the License at

docs/book/src/multiversion-tutorial/testdata/project/api/v1/cronjob_types.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ limitations under the License.
1717

1818
/*
1919
*/
20+
2021
package v1
2122

2223
/*
2324
*/
25+
2426
import (
2527
batchv1 "k8s.io/api/batch/v1"
2628
corev1 "k8s.io/api/core/v1"
@@ -126,8 +128,8 @@ type CronJobStatus struct {
126128

127129
// +kubebuilder:object:root=true
128130
// +kubebuilder:subresource:status
129-
// +kubebuilder:storageversion
130131
// +versionName=v1
132+
// +kubebuilder:storageversion
131133
// CronJob is the Schema for the cronjobs API.
132134
type CronJob struct {
133135
metav1.TypeMeta `json:",inline"`

docs/book/src/multiversion-tutorial/testdata/project/api/v1/cronjob_webhook.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ types implement the
4949
interfaces, a conversion webhook will be registered.
5050
*/
5151

52-
// SetupWebhookWithManager will setup the manager to manage the webhooks
52+
// SetupWebhookWithManager will setup the manager to manage the webhooks.
5353
func (r *CronJob) SetupWebhookWithManager(mgr ctrl.Manager) error {
5454
return ctrl.NewWebhookManagedBy(mgr).
5555
For(r).

docs/book/src/multiversion-tutorial/testdata/project/api/v1/groupversion_info.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ former, while the latter is used by the CRD generator to generate the right
2323
metadata for the CRDs it creates from this package.
2424
*/
2525

26-
// Package v1 contains API Schema definitions for the batch v1 API group
26+
// Package v1 contains API Schema definitions for the batch v1 API group.
2727
// +kubebuilder:object:generate=true
2828
// +groupName=batch.tutorial.kubebuilder.io
2929
package v1

docs/book/src/multiversion-tutorial/testdata/project/api/v2/cronjob_conversion.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
/*
2-
32
Licensed under the Apache License, Version 2.0 (the "License");
43
you may not use this file except in compliance with the License.
54
You may obtain a copy of the License at
@@ -36,7 +35,7 @@ import (
3635
/*
3736
Our "spoke" versions need to implement the
3837
[`Convertible`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/conversion?tab=doc#Convertible)
39-
interface. Namely, they'll need `ConvertTo` and `ConvertFrom` methods to convert to/from
38+
interface. Namely, they'll need `ConvertTo()` and `ConvertFrom()` methods to convert to/from
4039
the hub version.
4140
*/
4241

docs/book/src/multiversion-tutorial/testdata/project/api/v2/cronjob_types.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Since we're in a v2 package, controller-gen will assume this is for the v2
2020
version automatically. We could override that with the [`+versionName`
2121
marker](/reference/markers/crd.md).
2222
*/
23+
2324
package v2
2425

2526
/*
@@ -38,7 +39,7 @@ import (
3839
/*
3940
We'll leave our spec largely unchanged, except to change the schedule field to a new type.
4041
*/
41-
// CronJobSpec defines the desired state of CronJob
42+
// CronJobSpec defines the desired state of CronJob.
4243
type CronJobSpec struct {
4344
// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.
4445
Schedule CronSchedule `json:"schedule"`
@@ -84,6 +85,7 @@ type CronJobSpec struct {
8485
FailedJobsHistoryLimit *int32 `json:"failedJobsHistoryLimit,omitempty"`
8586

8687
// +kubebuilder:docs-gen:collapse=The rest of Spec
88+
8789
}
8890

8991
/*
@@ -160,7 +162,6 @@ type CronJobStatus struct {
160162
// +kubebuilder:object:root=true
161163
// +kubebuilder:subresource:status
162164
// +versionName=v2
163-
164165
// CronJob is the Schema for the cronjobs API.
165166
type CronJob struct {
166167
metav1.TypeMeta `json:",inline"`

docs/book/src/multiversion-tutorial/testdata/project/api/v2/cronjob_webhook.go

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,18 @@ func (r *CronJob) SetupWebhookWithManager(mgr ctrl.Manager) error {
5151
Complete()
5252
}
5353

54+
// TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
55+
56+
// +kubebuilder:webhook:path=/mutate-batch-tutorial-kubebuilder-io-v2-cronjob,mutating=true,failurePolicy=fail,sideEffects=None,groups=batch.tutorial.kubebuilder.io,resources=cronjobs,verbs=create;update,versions=v2,name=mcronjob-v2.kb.io,admissionReviewVersions=v1
57+
5458
// +kubebuilder:object:generate=false
5559
// CronJobCustomDefaulter struct is responsible for setting default values on the custom resource of the
5660
// Kind CronJob when those are created or updated.
61+
//
62+
// NOTE: The +kubebuilder:object:generate=false marker prevents controller-gen from generating DeepCopy methods,
63+
// as it is used only for temporary operations and does not need to be deeply copied.
5764
type CronJobCustomDefaulter struct {
65+
5866
// Default values for various CronJob fields
5967
DefaultConcurrencyPolicy ConcurrencyPolicy
6068
DefaultSuspend bool
@@ -68,36 +76,30 @@ var _ webhook.CustomDefaulter = &CronJobCustomDefaulter{}
6876
func (d *CronJobCustomDefaulter) Default(ctx context.Context, obj runtime.Object) error {
6977
cronjob, ok := obj.(*CronJob)
7078
if !ok {
71-
return fmt.Errorf("expected a CronJob object but got %T", obj)
79+
return fmt.Errorf("expected an CronJob object but got %T", obj)
7280
}
7381
cronjoblog.Info("Defaulting for CronJob", "name", cronjob.GetName())
7482

7583
// Set default values
7684
cronjob.Default()
85+
7786
return nil
7887
}
7988

80-
func (r *CronJob) Default() {
81-
if r.Spec.ConcurrencyPolicy == "" {
82-
r.Spec.ConcurrencyPolicy = AllowConcurrent
83-
}
84-
if r.Spec.Suspend == nil {
85-
r.Spec.Suspend = new(bool)
86-
}
87-
if r.Spec.SuccessfulJobsHistoryLimit == nil {
88-
r.Spec.SuccessfulJobsHistoryLimit = new(int32)
89-
*r.Spec.SuccessfulJobsHistoryLimit = 3
90-
}
91-
if r.Spec.FailedJobsHistoryLimit == nil {
92-
r.Spec.FailedJobsHistoryLimit = new(int32)
93-
*r.Spec.FailedJobsHistoryLimit = 1
94-
}
95-
}
89+
// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation.
90+
// NOTE: The 'path' attribute must follow a specific pattern and should not be modified directly here.
91+
// Modifying the path for an invalid path can cause API server errors; failing to locate the webhook.
92+
// +kubebuilder:webhook:path=/validate-batch-tutorial-kubebuilder-io-v2-cronjob,mutating=false,failurePolicy=fail,sideEffects=None,groups=batch.tutorial.kubebuilder.io,resources=cronjobs,verbs=create;update,versions=v2,name=vcronjob-v2.kb.io,admissionReviewVersions=v1
9693

9794
// +kubebuilder:object:generate=false
9895
// CronJobCustomValidator struct is responsible for validating the CronJob resource
9996
// when it is created, updated, or deleted.
100-
type CronJobCustomValidator struct{}
97+
//
98+
// NOTE: The +kubebuilder:object:generate=false marker prevents controller-gen from generating DeepCopy methods,
99+
// as this struct is used only for temporary operations and does not need to be deeply copied.
100+
type CronJobCustomValidator struct {
101+
//TODO(user): Add more fields as needed for validation
102+
}
101103

102104
var _ webhook.CustomValidator = &CronJobCustomValidator{}
103105

@@ -108,6 +110,7 @@ func (v *CronJobCustomValidator) ValidateCreate(ctx context.Context, obj runtime
108110
return nil, fmt.Errorf("expected a CronJob object but got %T", obj)
109111
}
110112
cronjoblog.Info("Validation for CronJob upon creation", "name", cronjob.GetName())
113+
111114
return nil, cronjob.validateCronJob()
112115
}
113116

@@ -118,6 +121,7 @@ func (v *CronJobCustomValidator) ValidateUpdate(ctx context.Context, oldObj, new
118121
return nil, fmt.Errorf("expected a CronJob object but got %T", newObj)
119122
}
120123
cronjoblog.Info("Validation for CronJob upon update", "name", cronjob.GetName())
124+
121125
return nil, cronjob.validateCronJob()
122126
}
123127

@@ -128,9 +132,29 @@ func (v *CronJobCustomValidator) ValidateDelete(ctx context.Context, obj runtime
128132
return nil, fmt.Errorf("expected a CronJob object but got %T", obj)
129133
}
130134
cronjoblog.Info("Validation for CronJob upon deletion", "name", cronjob.GetName())
135+
136+
// TODO(user): fill in your validation logic upon object deletion.
137+
131138
return nil, nil
132139
}
133140

141+
func (r *CronJob) Default() {
142+
if r.Spec.ConcurrencyPolicy == "" {
143+
r.Spec.ConcurrencyPolicy = AllowConcurrent
144+
}
145+
if r.Spec.Suspend == nil {
146+
r.Spec.Suspend = new(bool)
147+
}
148+
if r.Spec.SuccessfulJobsHistoryLimit == nil {
149+
r.Spec.SuccessfulJobsHistoryLimit = new(int32)
150+
*r.Spec.SuccessfulJobsHistoryLimit = 3
151+
}
152+
if r.Spec.FailedJobsHistoryLimit == nil {
153+
r.Spec.FailedJobsHistoryLimit = new(int32)
154+
*r.Spec.FailedJobsHistoryLimit = 1
155+
}
156+
}
157+
134158
func (r *CronJob) validateCronJob() error {
135159
var allErrs field.ErrorList
136160
if err := r.validateCronJobName(); err != nil {

docs/book/src/multiversion-tutorial/testdata/project/api/v2/cronjob_webhook_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,47 @@ var _ = Describe("CronJob Webhook", func() {
3838
// TODO (user): Add any teardown logic common to all tests
3939
})
4040

41+
Context("When creating CronJob under Defaulting Webhook", func() {
42+
// TODO (user): Add logic for defaulting webhooks
43+
// Example:
44+
// It("Should apply defaults when a required field is empty", func() {
45+
// By("simulating a scenario where defaults should be applied")
46+
// obj.SomeFieldWithDefault = ""
47+
// err := obj.Default(ctx)
48+
// Expect(err).NotTo(HaveOccurred())
49+
// Expect(obj.SomeFieldWithDefault).To(Equal("default_value"))
50+
// })
51+
})
52+
53+
Context("When creating or updating CronJob under Validating Webhook", func() {
54+
// TODO (user): Add logic for validating webhooks
55+
// Example:
56+
// It("Should deny creation if a required field is missing", func() {
57+
// By("simulating an invalid creation scenario")
58+
// obj.SomeRequiredField = ""
59+
// warnings, err := obj.ValidateCreate(ctx)
60+
// Expect(err).To(HaveOccurred())
61+
// Expect(warnings).To(BeNil())
62+
// })
63+
//
64+
// It("Should admit creation if all required fields are present", func() {
65+
// By("simulating an invalid creation scenario")
66+
// obj.SomeRequiredField = "valid_value"
67+
// warnings, err := obj.ValidateCreate(ctx)
68+
// Expect(err).NotTo(HaveOccurred())
69+
// Expect(warnings).To(BeNil())
70+
// })
71+
//
72+
// It("Should validate updates correctly", func() {
73+
// By("simulating a valid update scenario")
74+
// oldObj := &Captain{SomeRequiredField: "valid_value"}
75+
// obj.SomeRequiredField = "updated_value"
76+
// warnings, err := obj.ValidateUpdate(ctx, oldObj)
77+
// Expect(err).NotTo(HaveOccurred())
78+
// Expect(warnings).To(BeNil())
79+
// })
80+
})
81+
4182
Context("When creating CronJob under Conversion Webhook", func() {
4283
It("Should convert the object correctly", func() {
4384
// TODO (user): Add logic to convert the object to the desired version and verify the conversion

docs/book/src/multiversion-tutorial/testdata/project/cmd/main.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
16+
// +kubebuilder:docs-gen:collapse=Apache License
1617

1718
package main
1819

@@ -46,6 +47,7 @@ import (
4647

4748
/*
4849
*/
50+
4951
var (
5052
scheme = runtime.NewScheme()
5153
setupLog = ctrl.Log.WithName("setup")
@@ -64,6 +66,7 @@ func init() {
6466

6567
/*
6668
*/
69+
6770
func main() {
6871
/*
6972
*/
@@ -170,19 +173,20 @@ func main() {
170173
/*
171174
Our existing call to SetupWebhookWithManager registers our conversion webhooks with the manager, too.
172175
*/
173-
174176
// nolint:goconst
175177
if os.Getenv("ENABLE_WEBHOOKS") != "false" {
176178
if err = (&batchv1.CronJob{}).SetupWebhookWithManager(mgr); err != nil {
177179
setupLog.Error(err, "unable to create webhook", "webhook", "CronJob")
178180
os.Exit(1)
179181
}
182+
}
183+
// nolint:goconst
184+
if os.Getenv("ENABLE_WEBHOOKS") != "false" {
180185
if err = (&batchv2.CronJob{}).SetupWebhookWithManager(mgr); err != nil {
181186
setupLog.Error(err, "unable to create webhook", "webhook", "CronJob")
182187
os.Exit(1)
183188
}
184189
}
185-
186190
// +kubebuilder:scaffold:builder
187191

188192
/*

0 commit comments

Comments
 (0)