Skip to content

Commit 233645d

Browse files
Add Hub and Spoke for conversion webhooks
Introduces the required code to add the code implementation for the interfaces.
1 parent c331b70 commit 233645d

File tree

39 files changed

+591
-192
lines changed

39 files changed

+591
-192
lines changed

docs/book/src/multiversion-tutorial/conversion.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
# Implementing conversion
22

33
With our model for conversion in place, it's time to actually implement
4-
the conversion functions. We'll put them in a file called
5-
`cronjob_conversion.go` next to our `cronjob_types.go` file, to avoid
4+
the conversion functions. We'll create a conversion webhook
5+
for our CronJob API version `v1` (Hub) to Spoke our CronJob API version
6+
`v2` see:
7+
8+
```go
9+
kubebuilder create webhook --group batch --version v1 --kind CronJob --conversion--spoke v2
10+
```
11+
12+
The above command will generate the `cronjob_conversion.go` next to our
13+
`cronjob_types.go` file, to avoid
614
cluttering up our main types file with extra functions.
715

816
## Hub...

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ resources:
1818
path: tutorial.kubebuilder.io/project/api/v1
1919
version: v1
2020
webhooks:
21+
conversion: true
2122
defaulting: true
23+
spoke: v2
2224
validation: true
2325
webhookVersion: v1
2426
- api:
@@ -30,7 +32,6 @@ resources:
3032
path: tutorial.kubebuilder.io/project/api/v2
3133
version: v2
3234
webhooks:
33-
conversion: true
3435
defaulting: true
3536
validation: true
3637
webhookVersion: v1

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
/*
2+
Copyright 2024 The Kubernetes authors.
3+
24
Licensed under the Apache License, Version 2.0 (the "License");
35
you may not use this file except in compliance with the License.
46
You may obtain a copy of the License at

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ type CronJobStatus struct {
127127
*/
128128

129129
// +kubebuilder:object:root=true
130+
// +kubebuilder:storageversion
131+
// +kubebuilder:conversion:hub
130132
// +kubebuilder:subresource:status
131133
// +versionName=v1
132134
// +kubebuilder:storageversion

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

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
/*
2+
Copyright 2024 The Kubernetes authors.
3+
24
Licensed under the Apache License, Version 2.0 (the "License");
35
you may not use this file except in compliance with the License.
46
You may obtain a copy of the License at
@@ -21,16 +23,17 @@ For imports, we'll need the controller-runtime
2123
package, plus the API version for our hub type (v1), and finally some of the
2224
standard packages.
2325
*/
26+
2427
import (
2528
"fmt"
2629
"strings"
2730

28-
"sigs.k8s.io/controller-runtime/pkg/conversion"
31+
"log"
2932

30-
v1 "tutorial.kubebuilder.io/project/api/v1"
31-
)
33+
"sigs.k8s.io/controller-runtime/pkg/conversion"
3234

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

3538
/*
3639
Our "spoke" versions need to implement the
@@ -43,9 +46,11 @@ methods to convert to/from the hub version.
4346
ConvertTo is expected to modify its argument to contain the converted object.
4447
Most of the conversion is straightforward copying, except for converting our changed field.
4548
*/
49+
4650
// ConvertTo converts this CronJob to the Hub version (v1).
4751
func (src *CronJob) ConvertTo(dstRaw conversion.Hub) error {
48-
dst := dstRaw.(*v1.CronJob)
52+
dst := dstRaw.(*batchv1.CronJob)
53+
log.Printf("Converting from %T to %T", dst.APIVersion, src.APIVersion)
4954

5055
sched := src.Spec.Schedule
5156
scheduleParts := []string{"*", "*", "*", "*", "*"}
@@ -74,7 +79,7 @@ func (src *CronJob) ConvertTo(dstRaw conversion.Hub) error {
7479

7580
// Spec
7681
dst.Spec.StartingDeadlineSeconds = src.Spec.StartingDeadlineSeconds
77-
dst.Spec.ConcurrencyPolicy = v1.ConcurrencyPolicy(src.Spec.ConcurrencyPolicy)
82+
dst.Spec.ConcurrencyPolicy = batchv1.ConcurrencyPolicy(src.Spec.ConcurrencyPolicy)
7883
dst.Spec.Suspend = src.Spec.Suspend
7984
dst.Spec.JobTemplate = src.Spec.JobTemplate
8085
dst.Spec.SuccessfulJobsHistoryLimit = src.Spec.SuccessfulJobsHistoryLimit
@@ -85,6 +90,7 @@ func (src *CronJob) ConvertTo(dstRaw conversion.Hub) error {
8590
dst.Status.LastScheduleTime = src.Status.LastScheduleTime
8691

8792
// +kubebuilder:docs-gen:collapse=rote conversion
93+
8894
return nil
8995
}
9096

@@ -93,9 +99,10 @@ ConvertFrom is expected to modify its receiver to contain the converted object.
9399
Most of the conversion is straightforward copying, except for converting our changed field.
94100
*/
95101

96-
// ConvertFrom converts from the Hub version (v1) to this version.
102+
// ConvertFrom converts the Hub version (v1) to this CronJob (v2).
97103
func (dst *CronJob) ConvertFrom(srcRaw conversion.Hub) error {
98-
src := srcRaw.(*v1.CronJob)
104+
src := srcRaw.(*batchv1.CronJob)
105+
log.Printf("Converting from %T to %T", src.APIVersion, dst.APIVersion)
99106

100107
schedParts := strings.Split(src.Spec.Schedule, " ")
101108
if len(schedParts) != 5 {
@@ -133,5 +140,6 @@ func (dst *CronJob) ConvertFrom(srcRaw conversion.Hub) error {
133140
dst.Status.LastScheduleTime = src.Status.LastScheduleTime
134141

135142
// +kubebuilder:docs-gen:collapse=rote conversion
143+
136144
return nil
137145
}

docs/book/src/multiversion-tutorial/testdata/project/config/crd/kustomization.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ patches:
1010
# patches here are for enabling the conversion webhook for each CRD
1111
- path: patches/webhook_in_cronjobs.yaml
1212
- path: patches/webhook_in_cronjobs.yaml
13+
- path: patches/webhook_in_cronjobs.yaml
1314
# +kubebuilder:scaffold:crdkustomizewebhookpatch
1415

1516
# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.

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

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,7 @@ Next, we'll setup a logger for the webhooks.
4444
var cronjoblog = logf.Log.WithName("cronjob-resource")
4545

4646
/*
47-
This setup doubles as setup for our conversion webhooks: as long as our
48-
types implement the
49-
[Hub](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/conversion?tab=doc#Hub) and
50-
[Convertible](https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/conversion?tab=doc#Convertible)
51-
interfaces, a conversion webhook will be registered.
47+
Then, we set up the webhook with the manager.
5248
*/
5349

5450
// SetupCronJobWebhookWithManager registers the webhook for CronJob in the manager.

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

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,4 @@ var _ = Describe("CronJob Webhook", func() {
8484
// })
8585
})
8686

87-
Context("When creating CronJob under Conversion Webhook", func() {
88-
// TODO (user): Add logic to convert the object to the desired version and verify the conversion
89-
// Example:
90-
// It("Should convert the object correctly", func() {
91-
// convertedObj := &batchv2.CronJob{}
92-
// Expect(obj.ConvertTo(convertedObj)).To(Succeed())
93-
// Expect(convertedObj).ToNot(BeNil())
94-
// })
95-
})
96-
9787
})

docs/book/src/multiversion-tutorial/webhooks.md

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,6 @@
33
Our conversion is in place, so all that's left is to tell
44
controller-runtime about our conversion.
55

6-
Normally, we'd run
7-
8-
```shell
9-
kubebuilder create webhook --group batch --version v1 --kind CronJob --conversion
10-
```
11-
12-
to scaffold out the webhook setup. However, we've already got webhook
13-
setup, from when we built our defaulting and validating webhooks!
14-
156
## Webhook setup...
167

178
{{#literatego ./testdata/project/internal/webhook/v1/cronjob_webhook.go}}

docs/book/src/reference/project-config.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ Now let's check its layout fields definition:
150150
| `resources.core` | It is `true` when the group used is from Kubernetes API and the API resource is not defined on the project. |
151151
| `resources.external` | It is `true` when the flag `--external-api-path` was used to generated the scaffold for an [External Type][external-type]. |
152152
| `resources.webhooks` | Store the webhooks data when the sub-command `create webhook` is used. |
153+
| `resources.webhooks.spoke` | Store the API version that will act as the Spoke with the designated Hub version for conversion webhooks. |
153154
| `resources.webhooks.webhookVersion` | The Kubernetes API version (`apiVersion`) used to scaffold the webhook resource. |
154155
| `resources.webhooks.conversion` | It is `true` when the webhook was scaffold with the `--conversion` flag which means that is a conversion webhook. |
155156
| `resources.webhooks.defaulting` | It is `true` when the webhook was scaffold with the `--defaulting` flag which means that is a defaulting webhook. |

0 commit comments

Comments
 (0)