Skip to content

Commit

Permalink
(go/v4): Add hub and spoke implementation for conversion webhook
Browse files Browse the repository at this point in the history
Currently, the implementation is incomplete.
It introduces the code implementation to generate the hub and spoke
  • Loading branch information
camilamacedo86 committed Nov 10, 2024
1 parent 40db2b8 commit 501e28c
Show file tree
Hide file tree
Showing 39 changed files with 869 additions and 241 deletions.
12 changes: 10 additions & 2 deletions docs/book/src/multiversion-tutorial/conversion.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
# Implementing conversion

With our model for conversion in place, it's time to actually implement
the conversion functions. We'll put them in a file called
`cronjob_conversion.go` next to our `cronjob_types.go` file, to avoid
the conversion functions. We'll create a conversion webhook
for our CronJob API version `v1` (Hub) to Spoke our CronJob API version
`v2` see:

```go
kubebuilder create webhook --group batch --version v1 --kind CronJob --conversion --spoke v2
```

The above command will generate the `cronjob_conversion.go` next to our
`cronjob_types.go` file, to avoid
cluttering up our main types file with extra functions.

## Hub...
Expand Down
5 changes: 4 additions & 1 deletion docs/book/src/multiversion-tutorial/testdata/project/PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ resources:
path: tutorial.kubebuilder.io/project/api/v1
version: v1
webhooks:
conversion: true
defaulting: true
spoke:
- v2
- v2
validation: true
webhookVersion: v1
- api:
Expand All @@ -30,7 +34,6 @@ resources:
path: tutorial.kubebuilder.io/project/api/v2
version: v2
webhooks:
conversion: true
defaulting: true
validation: true
webhookVersion: v1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/*
Copyright 2024 The Kubernetes authors.
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 @@ -127,6 +127,8 @@ type CronJobStatus struct {
*/

// +kubebuilder:object:root=true
// +kubebuilder:storageversion
// +kubebuilder:conversion:hub
// +kubebuilder:subresource:status
// +versionName=v1
// +kubebuilder:storageversion
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/*
Copyright 2024 The Kubernetes authors.
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 All @@ -21,16 +23,17 @@ For imports, we'll need the controller-runtime
package, plus the API version for our hub type (v1), and finally some of the
standard packages.
*/

import (
"fmt"
"strings"

"sigs.k8s.io/controller-runtime/pkg/conversion"
"log"

v1 "tutorial.kubebuilder.io/project/api/v1"
)
"sigs.k8s.io/controller-runtime/pkg/conversion"

// +kubebuilder:docs-gen:collapse=Imports
batchv1 "tutorial.kubebuilder.io/project/api/v1"
) // +kubebuilder:docs-gen:collapse=Imports

/*
Our "spoke" versions need to implement the
Expand All @@ -43,9 +46,13 @@ methods to convert to/from the hub version.
ConvertTo is expected to modify its argument to contain the converted object.
Most of the conversion is straightforward copying, except for converting our changed field.
*/

// ConvertTo converts this CronJob to the Hub version (v1).
func (src *CronJob) ConvertTo(dstRaw conversion.Hub) error {
dst := dstRaw.(*v1.CronJob)
dst := dstRaw.(*batchv1.CronJob)
log.Printf("ConvertTo: converts this CronJob to the Hub version (v1);"+
"source: %s/%s and target: %s/%s",
src.Namespace, src.Name, dst.Namespace, dst.Name)

sched := src.Spec.Schedule
scheduleParts := []string{"*", "*", "*", "*", "*"}
Expand Down Expand Up @@ -74,7 +81,7 @@ func (src *CronJob) ConvertTo(dstRaw conversion.Hub) error {

// Spec
dst.Spec.StartingDeadlineSeconds = src.Spec.StartingDeadlineSeconds
dst.Spec.ConcurrencyPolicy = v1.ConcurrencyPolicy(src.Spec.ConcurrencyPolicy)
dst.Spec.ConcurrencyPolicy = batchv1.ConcurrencyPolicy(src.Spec.ConcurrencyPolicy)
dst.Spec.Suspend = src.Spec.Suspend
dst.Spec.JobTemplate = src.Spec.JobTemplate
dst.Spec.SuccessfulJobsHistoryLimit = src.Spec.SuccessfulJobsHistoryLimit
Expand All @@ -85,6 +92,7 @@ func (src *CronJob) ConvertTo(dstRaw conversion.Hub) error {
dst.Status.LastScheduleTime = src.Status.LastScheduleTime

// +kubebuilder:docs-gen:collapse=rote conversion

return nil
}

Expand All @@ -93,9 +101,13 @@ ConvertFrom is expected to modify its receiver to contain the converted object.
Most of the conversion is straightforward copying, except for converting our changed field.
*/

// ConvertFrom converts from the Hub version (v1) to this version.
// ConvertFrom converts the Hub version (v1) to this CronJob (v2).
func (dst *CronJob) ConvertFrom(srcRaw conversion.Hub) error {
src := srcRaw.(*v1.CronJob)
src := srcRaw.(*batchv1.CronJob)
log.Printf("ConvertFrom: converts the Hub version (v1) to this"+
"CronJob (v2);"+
"source: %s/%s and target: %s/%s",
src.Namespace, src.Name, dst.Namespace, dst.Name)

schedParts := strings.Split(src.Spec.Schedule, " ")
if len(schedParts) != 5 {
Expand Down Expand Up @@ -133,5 +145,6 @@ func (dst *CronJob) ConvertFrom(srcRaw conversion.Hub) error {
dst.Status.LastScheduleTime = src.Status.LastScheduleTime

// +kubebuilder:docs-gen:collapse=rote conversion

return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ types implement the
[Hub](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/conversion?tab=doc#Hub) and
[Convertible](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/conversion?tab=doc#Convertible)
interfaces, a conversion webhook will be registered.
*/

// SetupCronJobWebhookWithManager registers the webhook for CronJob in the manager.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,14 @@ var _ = Describe("CronJob Webhook", func() {
})
})

Context("When creating CronJob under Conversion Webhook", func() {
// TODO (user): Add logic to convert the object to the desired version and verify the conversion
// Example:
// It("Should convert the object correctly", func() {
// convertedObj := &batchv1.CronJob{}
// Expect(obj.ConvertTo(convertedObj)).To(Succeed())
// Expect(convertedObj).ToNot(BeNil())
// })
})

})
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,4 @@ var _ = Describe("CronJob Webhook", func() {
// })
})

Context("When creating CronJob under Conversion Webhook", func() {
// TODO (user): Add logic to convert the object to the desired version and verify the conversion
// Example:
// It("Should convert the object correctly", func() {
// convertedObj := &batchv2.CronJob{}
// Expect(obj.ConvertTo(convertedObj)).To(Succeed())
// Expect(convertedObj).ToNot(BeNil())
// })
})

})
9 changes: 0 additions & 9 deletions docs/book/src/multiversion-tutorial/webhooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,6 @@
Our conversion is in place, so all that's left is to tell
controller-runtime about our conversion.

Normally, we'd run

```shell
kubebuilder create webhook --group batch --version v1 --kind CronJob --conversion
```

to scaffold out the webhook setup. However, we've already got webhook
setup, from when we built our defaulting and validating webhooks!

## Webhook setup...

{{#literatego ./testdata/project/internal/webhook/v1/cronjob_webhook.go}}
Expand Down
1 change: 1 addition & 0 deletions docs/book/src/reference/project-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ Now let's check its layout fields definition:
| `resources.core` | It is `true` when the group used is from Kubernetes API and the API resource is not defined on the project. |
| `resources.external` | It is `true` when the flag `--external-api-path` was used to generated the scaffold for an [External Type][external-type]. |
| `resources.webhooks` | Store the webhooks data when the sub-command `create webhook` is used. |
| `resources.webhooks.spoke` | Store the API version that will act as the Spoke with the designated Hub version for conversion webhooks. |
| `resources.webhooks.webhookVersion` | The Kubernetes API version (`apiVersion`) used to scaffold the webhook resource. |
| `resources.webhooks.conversion` | It is `true` when the webhook was scaffold with the `--conversion` flag which means that is a conversion webhook. |
| `resources.webhooks.defaulting` | It is `true` when the webhook was scaffold with the `--defaulting` flag which means that is a defaulting webhook. |
Expand Down
Loading

0 comments on commit 501e28c

Please sign in to comment.