Skip to content

Commit

Permalink
feat: add implementation to generate multiversion sample with make ge…
Browse files Browse the repository at this point in the history
…nerate

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 <[email protected]>
  • Loading branch information
camilamacedo86 committed Sep 8, 2024
1 parent fa9f70c commit 83a8e08
Show file tree
Hide file tree
Showing 28 changed files with 1,305 additions and 9,759 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,11 @@ help: ## Display this help.

.PHONY: manifests
manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
# Note that the option maxDescLen=0 was added in the default scaffold in order to sort out the issue
# Too long: must have at most 262144 bytes. By using kubectl apply to create / update resources an annotation
# is created by K8s API to store the latest version of the resource ( kubectl.kubernetes.io/last-applied-configuration).
# 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.
$(CONTROLLER_GEN) rbac:roleName=manager-role crd:maxDescLen=0 webhook paths="./..." output:crd:artifacts:config=config/crd/bases

.PHONY: generate
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ resources:
path: tutorial.kubebuilder.io/project/api/v1
version: v1
webhooks:
conversion: true
defaulting: true
validation: true
webhookVersion: v1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ limitations under the License.

/*
*/

package v1

/*
*/

import (
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -126,8 +128,8 @@ type CronJobStatus struct {

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:storageversion
// +versionName=v1
// +kubebuilder:storageversion
// CronJob is the Schema for the cronjobs API.
type CronJob struct {
metav1.TypeMeta `json:",inline"`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ types implement the
interfaces, a conversion webhook will be registered.
*/

// SetupWebhookWithManager will setup the manager to manage the webhooks
// SetupWebhookWithManager will setup the manager to manage the webhooks.
func (r *CronJob) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(r).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ former, while the latter is used by the CRD generator to generate the right
metadata for the CRDs it creates from this package.
*/

// Package v1 contains API Schema definitions for the batch v1 API group
// Package v1 contains API Schema definitions for the batch v1 API group.
// +kubebuilder:object:generate=true
// +groupName=batch.tutorial.kubebuilder.io
package v1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
Expand Down Expand Up @@ -36,7 +35,7 @@ import (
/*
Our "spoke" versions need to implement the
[`Convertible`](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/conversion?tab=doc#Convertible)
interface. Namely, they'll need `ConvertTo` and `ConvertFrom` methods to convert to/from
interface. Namely, they'll need `ConvertTo()` and `ConvertFrom()` methods to convert to/from
the hub version.
*/

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Since we're in a v2 package, controller-gen will assume this is for the v2
version automatically. We could override that with the [`+versionName`
marker](/reference/markers/crd.md).
*/

package v2

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

// +kubebuilder:docs-gen:collapse=The rest of Spec

}

/*
Expand Down Expand Up @@ -160,7 +162,6 @@ type CronJobStatus struct {
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +versionName=v2

// CronJob is the Schema for the cronjobs API.
type CronJob struct {
metav1.TypeMeta `json:",inline"`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,18 @@ func (r *CronJob) SetupWebhookWithManager(mgr ctrl.Manager) error {
Complete()
}

// TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!

// +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.kb.io,admissionReviewVersions=v1

// +kubebuilder:object:generate=false
// CronJobCustomDefaulter struct is responsible for setting default values on the custom resource of the
// Kind CronJob when those are created or updated.
//
// NOTE: The +kubebuilder:object:generate=false marker prevents controller-gen from generating DeepCopy methods,
// as it is used only for temporary operations and does not need to be deeply copied.
type CronJobCustomDefaulter struct {

// Default values for various CronJob fields
DefaultConcurrencyPolicy ConcurrencyPolicy
DefaultSuspend bool
Expand All @@ -68,36 +76,30 @@ var _ webhook.CustomDefaulter = &CronJobCustomDefaulter{}
func (d *CronJobCustomDefaulter) Default(ctx context.Context, obj runtime.Object) error {
cronjob, ok := obj.(*CronJob)
if !ok {
return fmt.Errorf("expected a CronJob object but got %T", obj)
return fmt.Errorf("expected an CronJob object but got %T", obj)
}
cronjoblog.Info("Defaulting for CronJob", "name", cronjob.GetName())

// Set default values
cronjob.Default()

return nil
}

func (r *CronJob) Default() {
if r.Spec.ConcurrencyPolicy == "" {
r.Spec.ConcurrencyPolicy = AllowConcurrent
}
if r.Spec.Suspend == nil {
r.Spec.Suspend = new(bool)
}
if r.Spec.SuccessfulJobsHistoryLimit == nil {
r.Spec.SuccessfulJobsHistoryLimit = new(int32)
*r.Spec.SuccessfulJobsHistoryLimit = 3
}
if r.Spec.FailedJobsHistoryLimit == nil {
r.Spec.FailedJobsHistoryLimit = new(int32)
*r.Spec.FailedJobsHistoryLimit = 1
}
}
// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation.
// NOTE: The 'path' attribute must follow a specific pattern and should not be modified directly here.
// Modifying the path for an invalid path can cause API server errors; failing to locate the webhook.
// +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.kb.io,admissionReviewVersions=v1

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

var _ webhook.CustomValidator = &CronJobCustomValidator{}

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

return nil, cronjob.validateCronJob()
}

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

return nil, cronjob.validateCronJob()
}

Expand All @@ -128,9 +132,29 @@ func (v *CronJobCustomValidator) ValidateDelete(ctx context.Context, obj runtime
return nil, fmt.Errorf("expected a CronJob object but got %T", obj)
}
cronjoblog.Info("Validation for CronJob upon deletion", "name", cronjob.GetName())

// TODO(user): fill in your validation logic upon object deletion.

return nil, nil
}

func (r *CronJob) Default() {
if r.Spec.ConcurrencyPolicy == "" {
r.Spec.ConcurrencyPolicy = AllowConcurrent
}
if r.Spec.Suspend == nil {
r.Spec.Suspend = new(bool)
}
if r.Spec.SuccessfulJobsHistoryLimit == nil {
r.Spec.SuccessfulJobsHistoryLimit = new(int32)
*r.Spec.SuccessfulJobsHistoryLimit = 3
}
if r.Spec.FailedJobsHistoryLimit == nil {
r.Spec.FailedJobsHistoryLimit = new(int32)
*r.Spec.FailedJobsHistoryLimit = 1
}
}

func (r *CronJob) validateCronJob() error {
var allErrs field.ErrorList
if err := r.validateCronJobName(); err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,47 @@ var _ = Describe("CronJob Webhook", func() {
// TODO (user): Add any teardown logic common to all tests
})

Context("When creating CronJob under Defaulting Webhook", func() {
// TODO (user): Add logic for defaulting webhooks
// Example:
// It("Should apply defaults when a required field is empty", func() {
// By("simulating a scenario where defaults should be applied")
// obj.SomeFieldWithDefault = ""
// err := obj.Default(ctx)
// Expect(err).NotTo(HaveOccurred())
// Expect(obj.SomeFieldWithDefault).To(Equal("default_value"))
// })
})

Context("When creating or updating CronJob under Validating Webhook", func() {
// TODO (user): Add logic for validating webhooks
// Example:
// It("Should deny creation if a required field is missing", func() {
// By("simulating an invalid creation scenario")
// obj.SomeRequiredField = ""
// warnings, err := obj.ValidateCreate(ctx)
// Expect(err).To(HaveOccurred())
// Expect(warnings).To(BeNil())
// })
//
// It("Should admit creation if all required fields are present", func() {
// By("simulating an invalid creation scenario")
// obj.SomeRequiredField = "valid_value"
// warnings, err := obj.ValidateCreate(ctx)
// Expect(err).NotTo(HaveOccurred())
// Expect(warnings).To(BeNil())
// })
//
// It("Should validate updates correctly", func() {
// By("simulating a valid update scenario")
// oldObj := &Captain{SomeRequiredField: "valid_value"}
// obj.SomeRequiredField = "updated_value"
// warnings, err := obj.ValidateUpdate(ctx, oldObj)
// Expect(err).NotTo(HaveOccurred())
// Expect(warnings).To(BeNil())
// })
})

Context("When creating CronJob under Conversion Webhook", func() {
It("Should convert the object correctly", func() {
// TODO (user): Add logic to convert the object to the desired version and verify the conversion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// +kubebuilder:docs-gen:collapse=Apache License

package main

Expand Down Expand Up @@ -46,6 +47,7 @@ import (

/*
*/

var (
scheme = runtime.NewScheme()
setupLog = ctrl.Log.WithName("setup")
Expand All @@ -64,6 +66,7 @@ func init() {

/*
*/

func main() {
/*
*/
Expand Down Expand Up @@ -170,19 +173,20 @@ func main() {
/*
Our existing call to SetupWebhookWithManager registers our conversion webhooks with the manager, too.
*/

// nolint:goconst
if os.Getenv("ENABLE_WEBHOOKS") != "false" {
if err = (&batchv1.CronJob{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create webhook", "webhook", "CronJob")
os.Exit(1)
}
}
// nolint:goconst
if os.Getenv("ENABLE_WEBHOOKS") != "false" {
if err = (&batchv2.CronJob{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create webhook", "webhook", "CronJob")
os.Exit(1)
}
}

// +kubebuilder:scaffold:builder

/*
Expand Down
Loading

0 comments on commit 83a8e08

Please sign in to comment.