diff --git a/.github/workflows/test-e2e-samples.yml b/.github/workflows/test-e2e-samples.yml
index 3865f8624ca..f287e64cc75 100644
--- a/.github/workflows/test-e2e-samples.yml
+++ b/.github/workflows/test-e2e-samples.yml
@@ -41,7 +41,9 @@ jobs:
run: |
KUSTOMIZATION_FILE_PATH="testdata/project-v4/config/default/kustomization.yaml"
sed -i '25s/^#//' $KUSTOMIZATION_FILE_PATH
- sed -i '50,177s/^#//' $KUSTOMIZATION_FILE_PATH
+ # Uncomment all cert-manager injections
+ sed -i '50,172s/^#//' $KUSTOMIZATION_FILE_PATH
+ sed -i '174,198s/^#//' $KUSTOMIZATION_FILE_PATH
cd testdata/project-v4/
go mod tidy
@@ -81,9 +83,12 @@ jobs:
KUSTOMIZATION_FILE_PATH="testdata/project-v4-with-plugins/config/default/kustomization.yaml"
sed -i '25s/^#//' $KUSTOMIZATION_FILE_PATH
# Uncomment only ValidatingWebhookConfiguration
- # from cert-manager replaces
- sed -i '50,116s/^#//' $KUSTOMIZATION_FILE_PATH
- sed -i '148,177s/^#//' $KUSTOMIZATION_FILE_PATH
+ # from cert-manager replaces; we are leaving defaulting uncommented
+ # since this sample has no defaulting webhooks
+ sed -i '50,155s/^#//' $KUSTOMIZATION_FILE_PATH
+ # Uncomment only --conversion webhooks CA injection
+ sed -i '144,163s/^#//' $KUSTOMIZATION_FILE_PATH
+ sed -i '165,180s/^#//' $KUSTOMIZATION_FILE_PATH
cd testdata/project-v4-with-plugins/
go mod tidy
diff --git a/docs/book/src/cronjob-tutorial/testdata/project/config/crd/kustomization.yaml b/docs/book/src/cronjob-tutorial/testdata/project/config/crd/kustomization.yaml
index ce4e7415d87..3c9f8a16601 100644
--- a/docs/book/src/cronjob-tutorial/testdata/project/config/crd/kustomization.yaml
+++ b/docs/book/src/cronjob-tutorial/testdata/project/config/crd/kustomization.yaml
@@ -6,15 +6,11 @@ resources:
# +kubebuilder:scaffold:crdkustomizeresource
patches:
-# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.
+# [WEBHOOK] To enable webhooks, uncomment all the sections with [WEBHOOK] prefix.
# patches here are for enabling the conversion webhook for each CRD
# +kubebuilder:scaffold:crdkustomizewebhookpatch
-# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.
-# patches here are for enabling the CA injection for each CRD
-# +kubebuilder:scaffold:crdkustomizecainjectionpatch
-
# [WEBHOOK] To enable webhook, uncomment the following section
# the following config is for teaching kustomize how to do kustomization for CRDs.
-#configurations:
-#- kustomizeconfig.yaml
+configurations:
+- kustomizeconfig.yaml
diff --git a/docs/book/src/cronjob-tutorial/testdata/project/config/default/kustomization.yaml b/docs/book/src/cronjob-tutorial/testdata/project/config/default/kustomization.yaml
index 8778c1a5150..0406f1b9f5b 100644
--- a/docs/book/src/cronjob-tutorial/testdata/project/config/default/kustomization.yaml
+++ b/docs/book/src/cronjob-tutorial/testdata/project/config/default/kustomization.yaml
@@ -151,27 +151,13 @@ replacements:
# version: v1
# name: serving-cert # This name should match the one in certificate.yaml
# fieldPath: .metadata.namespace # Namespace of the certificate CR
-# targets:
-# - select:
-# kind: CustomResourceDefinition
-# fieldPaths:
-# - .metadata.annotations.[cert-manager.io/inject-ca-from]
-# options:
-# delimiter: '/'
-# index: 0
-# create: true
+# targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.
+# +kubebuilder:scaffold:crdkustomizecainjectionns
# - source:
# kind: Certificate
# group: cert-manager.io
# version: v1
# name: serving-cert # This name should match the one in certificate.yaml
# fieldPath: .metadata.name
-# targets:
-# - select:
-# kind: CustomResourceDefinition
-# fieldPaths:
-# - .metadata.annotations.[cert-manager.io/inject-ca-from]
-# options:
-# delimiter: '/'
-# index: 1
-# create: true
+# targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.
+# +kubebuilder:scaffold:crdkustomizecainjectionname
diff --git a/docs/book/src/getting-started/testdata/project/config/crd/kustomization.yaml b/docs/book/src/getting-started/testdata/project/config/crd/kustomization.yaml
index 217b2175494..ec76d28507d 100644
--- a/docs/book/src/getting-started/testdata/project/config/crd/kustomization.yaml
+++ b/docs/book/src/getting-started/testdata/project/config/crd/kustomization.yaml
@@ -6,15 +6,11 @@ resources:
# +kubebuilder:scaffold:crdkustomizeresource
patches:
-# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.
+# [WEBHOOK] To enable webhooks, uncomment all the sections with [WEBHOOK] prefix.
# patches here are for enabling the conversion webhook for each CRD
# +kubebuilder:scaffold:crdkustomizewebhookpatch
-# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.
-# patches here are for enabling the CA injection for each CRD
-# +kubebuilder:scaffold:crdkustomizecainjectionpatch
-
# [WEBHOOK] To enable webhook, uncomment the following section
# the following config is for teaching kustomize how to do kustomization for CRDs.
-#configurations:
-#- kustomizeconfig.yaml
+configurations:
+- kustomizeconfig.yaml
diff --git a/docs/book/src/getting-started/testdata/project/config/default/kustomization.yaml b/docs/book/src/getting-started/testdata/project/config/default/kustomization.yaml
index 8922567ea88..439cc5be0b7 100644
--- a/docs/book/src/getting-started/testdata/project/config/default/kustomization.yaml
+++ b/docs/book/src/getting-started/testdata/project/config/default/kustomization.yaml
@@ -151,27 +151,13 @@ patches:
# version: v1
# name: serving-cert # This name should match the one in certificate.yaml
# fieldPath: .metadata.namespace # Namespace of the certificate CR
-# targets:
-# - select:
-# kind: CustomResourceDefinition
-# fieldPaths:
-# - .metadata.annotations.[cert-manager.io/inject-ca-from]
-# options:
-# delimiter: '/'
-# index: 0
-# create: true
+# targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.
+# +kubebuilder:scaffold:crdkustomizecainjectionns
# - source:
# kind: Certificate
# group: cert-manager.io
# version: v1
# name: serving-cert # This name should match the one in certificate.yaml
# fieldPath: .metadata.name
-# targets:
-# - select:
-# kind: CustomResourceDefinition
-# fieldPaths:
-# - .metadata.annotations.[cert-manager.io/inject-ca-from]
-# options:
-# delimiter: '/'
-# index: 1
-# create: true
+# targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.
+# +kubebuilder:scaffold:crdkustomizecainjectionname
diff --git a/docs/book/src/multiversion-tutorial/testdata/project/config/crd/kustomization.yaml b/docs/book/src/multiversion-tutorial/testdata/project/config/crd/kustomization.yaml
index 4cae15b8d87..5759d0fa6f5 100644
--- a/docs/book/src/multiversion-tutorial/testdata/project/config/crd/kustomization.yaml
+++ b/docs/book/src/multiversion-tutorial/testdata/project/config/crd/kustomization.yaml
@@ -6,16 +6,11 @@ resources:
# +kubebuilder:scaffold:crdkustomizeresource
patches:
-# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.
+# [WEBHOOK] To enable webhooks, uncomment all the sections with [WEBHOOK] prefix.
# patches here are for enabling the conversion webhook for each CRD
- path: patches/webhook_in_cronjobs.yaml
# +kubebuilder:scaffold:crdkustomizewebhookpatch
-# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.
-# patches here are for enabling the CA injection for each CRD
-#- path: patches/cainjection_in_cronjobs.yaml
-# +kubebuilder:scaffold:crdkustomizecainjectionpatch
-
# [WEBHOOK] To enable webhook, uncomment the following section
# the following config is for teaching kustomize how to do kustomization for CRDs.
configurations:
diff --git a/docs/book/src/multiversion-tutorial/testdata/project/config/crd/patches/cainjection_in_cronjobs.yaml b/docs/book/src/multiversion-tutorial/testdata/project/config/crd/patches/cainjection_in_cronjobs.yaml
deleted file mode 100644
index 752fa9ac6a0..00000000000
--- a/docs/book/src/multiversion-tutorial/testdata/project/config/crd/patches/cainjection_in_cronjobs.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-# The following patch adds a directive for certmanager to inject CA into the CRD
-apiVersion: apiextensions.k8s.io/v1
-kind: CustomResourceDefinition
-metadata:
- annotations:
- cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME
- name: cronjobs.batch.tutorial.kubebuilder.io
diff --git a/docs/book/src/multiversion-tutorial/testdata/project/config/default/kustomization.yaml b/docs/book/src/multiversion-tutorial/testdata/project/config/default/kustomization.yaml
index 094f86a8cec..309e25c061b 100644
--- a/docs/book/src/multiversion-tutorial/testdata/project/config/default/kustomization.yaml
+++ b/docs/book/src/multiversion-tutorial/testdata/project/config/default/kustomization.yaml
@@ -144,34 +144,38 @@ replacements:
delimiter: '/'
index: 1
create: true
-
+#
- source: # Uncomment the following block if you have a ConversionWebhook (--conversion)
kind: Certificate
group: cert-manager.io
version: v1
name: serving-cert # This name should match the one in certificate.yaml
fieldPath: .metadata.namespace # Namespace of the certificate CR
- targets:
+ targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.
- select:
kind: CustomResourceDefinition
+ name: cronjobs.batch.tutorial.kubebuilder.io
fieldPaths:
- .metadata.annotations.[cert-manager.io/inject-ca-from]
options:
delimiter: '/'
index: 0
create: true
+# +kubebuilder:scaffold:crdkustomizecainjectionns
- source:
kind: Certificate
group: cert-manager.io
version: v1
name: serving-cert # This name should match the one in certificate.yaml
fieldPath: .metadata.name
- targets:
+ targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.
- select:
kind: CustomResourceDefinition
+ name: cronjobs.batch.tutorial.kubebuilder.io
fieldPaths:
- .metadata.annotations.[cert-manager.io/inject-ca-from]
options:
delimiter: '/'
index: 1
create: true
+# +kubebuilder:scaffold:crdkustomizecainjectionname
diff --git a/docs/book/src/reference/markers/scaffold.md b/docs/book/src/reference/markers/scaffold.md
index 48d18fa88bf..5d3cca2c62c 100644
--- a/docs/book/src/reference/markers/scaffold.md
+++ b/docs/book/src/reference/markers/scaffold.md
@@ -95,17 +95,74 @@ properly registered with the manager, so that the controller can reconcile the r
## List of `+kubebuilder:scaffold` Markers
-| Marker | Usual Location | Function |
-|--------------------------------------------|------------------------------|---------------------------------------------------------------------------------|
-| `+kubebuilder:scaffold:imports` | `main.go` | Marks where imports for new controllers, webhooks, or APIs should be injected. |
-| `+kubebuilder:scaffold:scheme` | `init()` in `main.go` | Used to add API versions to the scheme for runtime. |
-| `+kubebuilder:scaffold:builder` | `main.go` | Marks where new controllers should be registered with the manager. |
-| `+kubebuilder:scaffold:webhook` | `webhooks suite tests` files | Marks where webhook setup functions are added. |
-| `+kubebuilder:scaffold:crdkustomizeresource`| `config/crd` | Marks where CRD custom resource patches are added. |
-| `+kubebuilder:scaffold:crdkustomizewebhookpatch` | `config/crd` | Marks where CRD webhook patches are added. |
-| `+kubebuilder:scaffold:crdkustomizecainjectionpatch` | `config/crd` | Marks where CA injection patches are added for the webhook. |
-| `+kubebuilder:scaffold:manifestskustomizesamples` | `config/samples` | Marks where Kustomize sample manifests are injected. |
-| `+kubebuilder:scaffold:e2e-webhooks-checks` | `test/e2e` | Adds e2e checks for webhooks depending on the types of webhooks scaffolded. |
+| Marker | Usual Location | Function |
+|--------------------------------------------------------------------------------|------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `+kubebuilder:scaffold:imports` | `main.go` | Marks where imports for new controllers, webhooks, or APIs should be injected. |
+| `+kubebuilder:scaffold:scheme` | `init()` in `main.go` | Used to add API versions to the scheme for runtime. |
+| `+kubebuilder:scaffold:builder` | `main.go` | Marks where new controllers should be registered with the manager. |
+| `+kubebuilder:scaffold:webhook` | `webhooks suite tests` files | Marks where webhook setup functions are added. |
+| `+kubebuilder:scaffold:crdkustomizeresource` | `config/crd` | Marks where CRD custom resource patches are added. |
+| `+kubebuilder:scaffold:crdkustomizewebhookpatch` | `config/crd` | Marks where CRD webhook patches are added. |
+| `+kubebuilder:scaffold:crdkustomizecainjectionns` | `config/default` | Marks where CA injection patches are added for the conversion webhooks. |
+| `+kubebuilder:scaffold:crdkustomizecainjectioname` | `config/default` | Marks where CA injection patches are added for the conversion webhooks. |
+| `+kubebuilder:scaffold:manifestskustomizesamples` | `config/samples` | Marks where Kustomize sample manifests are injected. |
+| `+kubebuilder:scaffold:e2e-webhooks-checks` | `test/e2e` | Adds e2e checks for webhooks depending on the types of webhooks scaffolded. |
+| **(No longer supported)** `+kubebuilder:scaffold:crdkustomizecainjectionpatch` | `config/crd` | Marks where CA injection patches are added for the webhooks. Replaced by `+kubebuilder:scaffold:crdkustomizecainjectionns` and `+kubebuilder:scaffold:crdkustomizecainjectioname` |
+
+
+ **(No longer supported)** `+kubebuilder:scaffold:crdkustomizecainjectionpatch`
+
+If you find this marker in your code please:
+
+1. **Remove the CERTMANAGER Section from `config/crd/kustomization.yaml`:**
+
+ Delete the `CERTMANAGER` section to prevent unintended CA injection patches for CRDs. Ensure the following lines are removed or commented out:
+
+ ```yaml
+ # [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.
+ # patches here are for enabling the CA injection for each CRD
+ #- path: patches/cainjection_in_firstmates.yaml
+ # +kubebuilder:scaffold:crdkustomizecainjectionpatch
+ ```
+
+2. **Ensure CA Injection Configuration in `config/default/kustomization.yaml`:**
+
+ Under the `[CERTMANAGER]` replacement in `config/default/kustomization.yaml`, add the following code for proper CA injection generation:
+
+ **NOTE:** You must ensure that the code contains the following target markers:
+ - `+kubebuilder:scaffold:crdkustomizecainjectionns`
+ - `+kubebuilder:scaffold:crdkustomizecainjectioname`
+
+ ```yaml
+ # - source: # Uncomment the following block if you have a ConversionWebhook (--conversion)
+ # kind: Certificate
+ # group: cert-manager.io
+ # version: v1
+ # name: serving-cert # This name should match the one in certificate.yaml
+ # fieldPath: .metadata.namespace # Namespace of the certificate CR
+ # targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.
+ # +kubebuilder:scaffold:crdkustomizecainjectionns
+ # - source:
+ # kind: Certificate
+ # group: cert-manager.io
+ # version: v1
+ # name: serving-cert # This name should match the one in certificate.yaml
+ # fieldPath: .metadata.name
+ # targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.
+ # +kubebuilder:scaffold:crdkustomizecainjectioname
+ ```
+
+3. **Ensure Only Conversion Webhook Patches in `config/crd/patches`:**
+
+ The `config/crd/patches` directory and the corresponding entries in `config/crd/kustomization.yaml` should only contain files for conversion webhooks. Previously, a bug caused the patch file to be generated for any webhook, but only patches for webhooks scaffolded with the `--conversion` option should be included.
+
+For further guidance, you can refer to examples in the `testdata/` directory in the Kubebuilder repository.
+
+> **Alternatively**: You can use the [`alpha generate`](./../rescaffold.md) command to re-generate the project from scratch
+> using the latest release available. Afterward, you can re-add only your code implementation on top to ensure your project
+> includes all the latest bug fixes and enhancements.
+
+
Creating Your Own Markers
diff --git a/hack/docs/internal/multiversion-tutorial/generate_multiversion.go b/hack/docs/internal/multiversion-tutorial/generate_multiversion.go
index 9c7c4c5e576..1c1dcf50824 100644
--- a/hack/docs/internal/multiversion-tutorial/generate_multiversion.go
+++ b/hack/docs/internal/multiversion-tutorial/generate_multiversion.go
@@ -87,7 +87,13 @@ func (sp *Sample) updateDefaultKustomize() {
// Enable CA for Conversion Webhook
err := pluginutil.UncommentCode(
filepath.Join(sp.ctx.Dir, "config/default/kustomization.yaml"),
- caConversionCRDDefaultKustomize, `#`)
+ caInjectionNamespace, `#`)
+ hackutils.CheckError("fixing default/kustomization", err)
+
+ // Enable CA for Conversion Webhook
+ err = pluginutil.UncommentCode(
+ filepath.Join(sp.ctx.Dir, "config/default/kustomization.yaml"),
+ caInjectionCert, `#`)
hackutils.CheckError("fixing default/kustomization", err)
}
diff --git a/hack/docs/internal/multiversion-tutorial/kustomize.go b/hack/docs/internal/multiversion-tutorial/kustomize.go
index 4ca0f2a226c..fe2a0ce506e 100644
--- a/hack/docs/internal/multiversion-tutorial/kustomize.go
+++ b/hack/docs/internal/multiversion-tutorial/kustomize.go
@@ -16,31 +16,33 @@ limitations under the License.
package multiversion
-const caConversionCRDDefaultKustomize = `#
-# - source: # Uncomment the following block if you have a ConversionWebhook (--conversion)
+const caInjectionNamespace = `# - source: # Uncomment the following block if you have a ConversionWebhook (--conversion)
# kind: Certificate
# group: cert-manager.io
# version: v1
# name: serving-cert # This name should match the one in certificate.yaml
# fieldPath: .metadata.namespace # Namespace of the certificate CR
-# targets:
+# targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.
# - select:
# kind: CustomResourceDefinition
+# name: cronjobs.batch.tutorial.kubebuilder.io
# fieldPaths:
# - .metadata.annotations.[cert-manager.io/inject-ca-from]
# options:
# delimiter: '/'
# index: 0
-# create: true
-# - source:
+# create: true`
+
+const caInjectionCert = `# - source:
# kind: Certificate
# group: cert-manager.io
# version: v1
# name: serving-cert # This name should match the one in certificate.yaml
# fieldPath: .metadata.name
-# targets:
+# targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.
# - select:
# kind: CustomResourceDefinition
+# name: cronjobs.batch.tutorial.kubebuilder.io
# fieldPaths:
# - .metadata.annotations.[cert-manager.io/inject-ca-from]
# options:
diff --git a/pkg/plugins/common/kustomize/v2/scaffolds/api.go b/pkg/plugins/common/kustomize/v2/scaffolds/api.go
index a5b82a3ca53..b753c8b1813 100644
--- a/pkg/plugins/common/kustomize/v2/scaffolds/api.go
+++ b/pkg/plugins/common/kustomize/v2/scaffolds/api.go
@@ -90,6 +90,7 @@ func (s *apiScaffolder) Scaffold() error {
}
}
+ // nolint:goconst
kustomizeFilePath := "config/default/kustomization.yaml"
err := pluginutil.UncommentCode(kustomizeFilePath, "#- ../crd", `#`)
if err != nil {
diff --git a/pkg/plugins/common/kustomize/v2/scaffolds/internal/templates/config/crd/kustomization.go b/pkg/plugins/common/kustomize/v2/scaffolds/internal/templates/config/crd/kustomization.go
index fe982d7b8af..3b1926f078c 100644
--- a/pkg/plugins/common/kustomize/v2/scaffolds/internal/templates/config/crd/kustomization.go
+++ b/pkg/plugins/common/kustomize/v2/scaffolds/internal/templates/config/crd/kustomization.go
@@ -45,7 +45,6 @@ func (f *Kustomization) SetTemplateDefaults() error {
f.TemplateBody = fmt.Sprintf(kustomizationTemplate,
machinery.NewMarkerFor(f.Path, resourceMarker),
machinery.NewMarkerFor(f.Path, webhookPatchMarker),
- machinery.NewMarkerFor(f.Path, caInjectionPatchMarker),
)
return nil
@@ -53,9 +52,8 @@ func (f *Kustomization) SetTemplateDefaults() error {
//nolint:gosec to ignore false complain G101: Potential hardcoded credentials (gosec)
const (
- resourceMarker = "crdkustomizeresource"
- webhookPatchMarker = "crdkustomizewebhookpatch"
- caInjectionPatchMarker = "crdkustomizecainjectionpatch"
+ resourceMarker = "crdkustomizeresource"
+ webhookPatchMarker = "crdkustomizewebhookpatch"
)
// GetMarkers implements file.Inserter
@@ -63,7 +61,6 @@ func (f *Kustomization) GetMarkers() []machinery.Marker {
return []machinery.Marker{
machinery.NewMarkerFor(f.Path, resourceMarker),
machinery.NewMarkerFor(f.Path, webhookPatchMarker),
- machinery.NewMarkerFor(f.Path, caInjectionPatchMarker),
}
}
@@ -71,14 +68,12 @@ const (
resourceCodeFragment = `- bases/%s_%s.yaml
`
webhookPatchCodeFragment = `- path: patches/webhook_in_%s.yaml
-`
- caInjectionPatchCodeFragment = `#- path: patches/cainjection_in_%s.yaml
`
)
// GetCodeFragments implements file.Inserter
func (f *Kustomization) GetCodeFragments() machinery.CodeFragmentsMap {
- fragments := make(machinery.CodeFragmentsMap, 3)
+ fragments := make(machinery.CodeFragmentsMap, 2)
// Generate resource code fragments
res := make([]string, 0)
@@ -98,21 +93,11 @@ func (f *Kustomization) GetCodeFragments() machinery.CodeFragmentsMap {
}
}
- // Generate resource code fragments
- caInjectionPatch := make([]string, 0)
- if !f.Resource.Webhooks.IsEmpty() && f.Resource.Webhooks.Conversion {
- caInjectionPatch = append(caInjectionPatch, fmt.Sprintf(caInjectionPatchCodeFragment, suffix))
- }
-
// Only store code fragments in the map if the slices are non-empty
if len(res) != 0 {
fragments[machinery.NewMarkerFor(f.Path, resourceMarker)] = res
}
- if len(caInjectionPatch) != 0 {
- fragments[machinery.NewMarkerFor(f.Path, caInjectionPatchMarker)] = caInjectionPatch
- }
-
return fragments
}
@@ -123,16 +108,12 @@ resources:
%s
patches:
-# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.
+# [WEBHOOK] To enable webhooks, uncomment all the sections with [WEBHOOK] prefix.
# patches here are for enabling the conversion webhook for each CRD
%s
-# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.
-# patches here are for enabling the CA injection for each CRD
-%s
-
# [WEBHOOK] To enable webhook, uncomment the following section
# the following config is for teaching kustomize how to do kustomization for CRDs.
-#configurations:
-#- kustomizeconfig.yaml
+configurations:
+- kustomizeconfig.yaml
`
diff --git a/pkg/plugins/common/kustomize/v2/scaffolds/internal/templates/config/crd/patches/enablecainjection_patch.go b/pkg/plugins/common/kustomize/v2/scaffolds/internal/templates/config/crd/patches/enablecainjection_patch.go
deleted file mode 100644
index 0ef72c50046..00000000000
--- a/pkg/plugins/common/kustomize/v2/scaffolds/internal/templates/config/crd/patches/enablecainjection_patch.go
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-Copyright 2020 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
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-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.
-*/
-
-package patches
-
-import (
- "path/filepath"
-
- "sigs.k8s.io/kubebuilder/v4/pkg/machinery"
-)
-
-var _ machinery.Template = &EnableCAInjectionPatch{}
-
-// EnableCAInjectionPatch scaffolds a file that defines the patch that injects CA into the CRD
-type EnableCAInjectionPatch struct {
- machinery.TemplateMixin
- machinery.MultiGroupMixin
- machinery.ResourceMixin
-}
-
-// SetTemplateDefaults implements file.Template
-func (f *EnableCAInjectionPatch) SetTemplateDefaults() error {
- if f.Path == "" {
- if f.MultiGroup && f.Resource.Group != "" {
- f.Path = filepath.Join("config", "crd", "patches", "cainjection_in_%[group]_%[plural].yaml")
- } else {
- f.Path = filepath.Join("config", "crd", "patches", "cainjection_in_%[plural].yaml")
- }
- }
- f.Path = f.Resource.Replacer().Replace(f.Path)
-
- f.TemplateBody = enableCAInjectionPatchTemplate
-
- return nil
-}
-
-//nolint:lll
-const enableCAInjectionPatchTemplate = `# The following patch adds a directive for certmanager to inject CA into the CRD
-apiVersion: apiextensions.k8s.io/v1
-kind: CustomResourceDefinition
-metadata:
- annotations:
- cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME
- name: {{ .Resource.Plural }}.{{ .Resource.QualifiedGroup }}
-`
diff --git a/pkg/plugins/common/kustomize/v2/scaffolds/internal/templates/config/kdefault/kustomization.go b/pkg/plugins/common/kustomize/v2/scaffolds/internal/templates/config/kdefault/kustomization.go
index bc82de3ffcf..6ef3f087275 100644
--- a/pkg/plugins/common/kustomize/v2/scaffolds/internal/templates/config/kdefault/kustomization.go
+++ b/pkg/plugins/common/kustomize/v2/scaffolds/internal/templates/config/kdefault/kustomization.go
@@ -196,28 +196,14 @@ patches:
# version: v1
# name: serving-cert # This name should match the one in certificate.yaml
# fieldPath: .metadata.namespace # Namespace of the certificate CR
-# targets:
-# - select:
-# kind: CustomResourceDefinition
-# fieldPaths:
-# - .metadata.annotations.[cert-manager.io/inject-ca-from]
-# options:
-# delimiter: '/'
-# index: 0
-# create: true
+# targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.
+# +kubebuilder:scaffold:crdkustomizecainjectionns
# - source:
# kind: Certificate
# group: cert-manager.io
# version: v1
# name: serving-cert # This name should match the one in certificate.yaml
# fieldPath: .metadata.name
-# targets:
-# - select:
-# kind: CustomResourceDefinition
-# fieldPaths:
-# - .metadata.annotations.[cert-manager.io/inject-ca-from]
-# options:
-# delimiter: '/'
-# index: 1
-# create: true
+# targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.
+# +kubebuilder:scaffold:crdkustomizecainjectionname
`
diff --git a/pkg/plugins/common/kustomize/v2/scaffolds/internal/templates/config/kdefault/kustomization_conversion_updater.go b/pkg/plugins/common/kustomize/v2/scaffolds/internal/templates/config/kdefault/kustomization_conversion_updater.go
new file mode 100644
index 00000000000..0330fefcc13
--- /dev/null
+++ b/pkg/plugins/common/kustomize/v2/scaffolds/internal/templates/config/kdefault/kustomization_conversion_updater.go
@@ -0,0 +1,83 @@
+package kdefault
+
+import (
+ "fmt"
+ "path/filepath"
+
+ "sigs.k8s.io/kubebuilder/v4/pkg/machinery"
+)
+
+const caNamespace = "crdkustomizecainjectionns"
+const caName = "crdkustomizecainjectionname"
+
+// KustomizationCAConversionUpdater appends CA injection targets for CRDs with --conversion
+type KustomizationCAConversionUpdater struct {
+ machinery.TemplateMixin
+ machinery.ResourceMixin
+}
+
+// SetTemplateDefaults defines the file path and behavior for existing files
+func (f *KustomizationCAConversionUpdater) SetTemplateDefaults() error {
+ if f.Path == "" {
+ f.Path = filepath.Join("config", "default", "kustomization.yaml")
+ }
+ f.IfExistsAction = machinery.SkipFile // Only append to the existing file, don’t overwrite it
+ return nil
+}
+
+// GetMarkers provides the markers where the CA injection targets will be appended
+func (f *KustomizationCAConversionUpdater) GetMarkers() []machinery.Marker {
+
+ return []machinery.Marker{
+ machinery.NewMarkerFor(f.Path, caNamespace),
+ machinery.NewMarkerFor(f.Path, caName),
+ }
+}
+
+// GetCodeFragments appends CA injection targets for the CRD with --conversion as comments
+func (f *KustomizationCAConversionUpdater) GetCodeFragments() machinery.CodeFragmentsMap {
+ fragments := make(machinery.CodeFragmentsMap)
+
+ // Obtain the formatted CRD name as Plural.Group.Domain (e.g., cronjobs.batch.tutorial.kubebuilder.io)
+ crdName := fmt.Sprintf("%s.%s", f.Resource.Plural, f.Resource.QualifiedGroup())
+
+ if !f.Resource.Webhooks.IsEmpty() && f.Resource.Webhooks.Conversion {
+ // Commented CA injection configuration for the namespace part
+ caInjectionNamespace := fmt.Sprintf(`# - select:
+# kind: CustomResourceDefinition
+# name: %s
+# fieldPaths:
+# - .metadata.annotations.[cert-manager.io/inject-ca-from]
+# options:
+# delimiter: '/'
+# index: 0
+# create: true
+`, crdName)
+
+ // Commented CA injection configuration for the name part
+ caInjectionName := fmt.Sprintf(`# - select:
+# kind: CustomResourceDefinition
+# name: %s
+# fieldPaths:
+# - .metadata.annotations.[cert-manager.io/inject-ca-from]
+# options:
+# delimiter: '/'
+# index: 1
+# create: true
+`, crdName)
+
+ // Append to the correct markers to prevent duplication
+ namespaceMarker := machinery.NewMarkerFor(f.Path, caNamespace)
+ certificateMarker := machinery.NewMarkerFor(f.Path, caName)
+
+ // Check if the fragments already exist before adding them
+ if _, exists := fragments[namespaceMarker]; !exists {
+ fragments[namespaceMarker] = []string{caInjectionNamespace}
+ }
+ if _, exists := fragments[certificateMarker]; !exists {
+ fragments[certificateMarker] = []string{caInjectionName}
+ }
+ }
+
+ return fragments
+}
diff --git a/pkg/plugins/common/kustomize/v2/scaffolds/webhook.go b/pkg/plugins/common/kustomize/v2/scaffolds/webhook.go
index fd871ecffef..b279b9a2464 100644
--- a/pkg/plugins/common/kustomize/v2/scaffolds/webhook.go
+++ b/pkg/plugins/common/kustomize/v2/scaffolds/webhook.go
@@ -63,6 +63,12 @@ func (s *webhookScaffolder) InjectFS(fs machinery.Filesystem) { s.fs = fs }
func (s *webhookScaffolder) Scaffold() error {
log.Println("Writing kustomize manifests for you to edit...")
+ // Will validate the scaffold
+ // Users that scaffolded the project previously
+ // with the bugs will receive a message to help
+ // them out fix their scaffold.
+ validateScaffoldedProject()
+
// Initialize the machinery.Scaffold that will write the files to disk
scaffold := machinery.NewScaffold(s.fs,
machinery.WithConfig(s.config),
@@ -87,7 +93,7 @@ func (s *webhookScaffolder) Scaffold() error {
// Only scaffold the following patches if is a conversion webhook
if s.resource.Webhooks.Conversion {
buildScaffold = append(buildScaffold, &patches.EnableWebhookPatch{})
- buildScaffold = append(buildScaffold, &patches.EnableCAInjectionPatch{})
+ buildScaffold = append(buildScaffold, &kdefault.KustomizationCAConversionUpdater{})
}
if !s.resource.External && !s.resource.Core {
@@ -106,6 +112,7 @@ func (s *webhookScaffolder) Scaffold() error {
"%s to allow webhook traffic.", policyKustomizeFilePath)
}
+ // nolint:goconst
kustomizeFilePath := "config/default/kustomization.yaml"
err = pluginutil.UncommentCode(kustomizeFilePath, "#- ../webhook", `#`)
if err != nil {
@@ -151,5 +158,66 @@ func (s *webhookScaffolder) Scaffold() error {
return nil
}
+// Deprecated: remove it when go/v4 and/or kustomize/v2 be removed
+// validateScaffoldedProject will output a message to help users fix their scaffold
+func validateScaffoldedProject() {
+ // nolint:goconst
+ kustomizeFilePath := "config/default/kustomization.yaml"
+ hasCertManagerPatch, err := pluginutil.HasFileContentWith(kustomizeFilePath, "[CERTMANAGER]")
+ if hasCertManagerPatch && err == nil {
+
+ log.Warning(`
+1. **Remove the CERTMANAGER Section from config/crd/kustomization.yaml:**
+
+ Delete the CERTMANAGER section to prevent unintended CA injection patches for CRDs.
+ Ensure the following lines are removed or commented out:
+
+ # [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.
+ # patches here are for enabling the CA injection for each CRD
+ #- path: patches/cainjection_in_firstmates.yaml
+ # +kubebuilder:scaffold:crdkustomizecainjectionpatch
+
+2. **Ensure CA Injection Configuration in config/default/kustomization.yaml:**
+
+ Under the [CERTMANAGER] replacement in config/default/kustomization.yaml,
+ add the following code for proper CA injection generation:
+
+ **NOTE:** You must ensure that the code contains the following target markers:
+ - +kubebuilder:scaffold:crdkustomizecainjectionns
+ - +kubebuilder:scaffold:crdkustomizecainjectioname
+
+ # - source: # Uncomment the following block if you have a ConversionWebhook (--conversion)
+ # kind: Certificate
+ # group: cert-manager.io
+ # version: v1
+ # name: serving-cert # This name should match the one in certificate.yaml
+ # fieldPath: .metadata.namespace # Namespace of the certificate CR
+ # targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.
+ # +kubebuilder:scaffold:crdkustomizecainjectionns
+ # - source:
+ # kind: Certificate
+ # group: cert-manager.io
+ # version: v1
+ # name: serving-cert # This name should match the one in certificate.yaml
+ # fieldPath: .metadata.name
+ # targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.
+ # +kubebuilder:scaffold:crdkustomizecainjectioname
+
+3. **Ensure Only Conversion Webhook Patches in config/crd/patches:**
+
+ The config/crd/patches directory and the corresponding entries in config/crd/kustomization.yaml should only
+ contain files for conversion webhooks. Previously, a bug caused the patch file to be generated for any webhook,
+ but only patches for webhooks created with the --conversion option should be included.
+
+For further guidance, you can refer to examples in the testdata/ directory in the Kubebuilder repository.
+
+**Alternatively**: You can use the 'alpha generate' command to re-generate the project from scratch using the latest
+release available. Afterward, you can re-add only your code implementation on top to ensure your project includes all
+the latest bug fixes and enhancements.
+`)
+
+ }
+}
+
const allowWebhookTrafficFragment = `
- allow-webhook-traffic.yaml`
diff --git a/test/testdata/generate.sh b/test/testdata/generate.sh
index e445bdc7f5c..9ca7122bb8b 100755
--- a/test/testdata/generate.sh
+++ b/test/testdata/generate.sh
@@ -50,7 +50,16 @@ function scaffold_test_project {
# TODO: Remove it when we have the hub and spoke scaffolded by Kubebuilder
# Apply the sed command based on project type
insert_kubebuilder_annotations "api/v1/firstmate_types.go"
-
+
+ # Create API to test conversion from v1 to v2 and multi CA covertion in the kustomize
+ $kb create api --group crew --version v1 --kind SecondMate --controller=true --resource=true --make=false
+ $kb create api --group crew --version v2 --kind SecondMate --controller=false --resource=true --make=false
+ $kb create webhook --group crew --version v1 --kind SecondMate --conversion --make=false
+
+ # TODO: Remove it when we have the hub and spoke scaffolded by Kubebuilder
+ # Apply the sed command based on project type
+ insert_kubebuilder_annotations "api/v1/secondmate_types.go"
+
$kb create api --group crew --version v1 --kind Admiral --plural=admirales --controller=true --resource=true --namespaced=false --make=false
$kb create webhook --group crew --version v1 --kind Admiral --plural=admirales --defaulting
# Controller for External types
diff --git a/testdata/project-v4-multigroup/config/crd/kustomization.yaml b/testdata/project-v4-multigroup/config/crd/kustomization.yaml
index 5797248847e..4970660a604 100644
--- a/testdata/project-v4-multigroup/config/crd/kustomization.yaml
+++ b/testdata/project-v4-multigroup/config/crd/kustomization.yaml
@@ -17,16 +17,11 @@ resources:
# +kubebuilder:scaffold:crdkustomizeresource
patches:
-# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.
+# [WEBHOOK] To enable webhooks, uncomment all the sections with [WEBHOOK] prefix.
# patches here are for enabling the conversion webhook for each CRD
- path: patches/webhook_in_example.com_wordpresses.yaml
# +kubebuilder:scaffold:crdkustomizewebhookpatch
-# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.
-# patches here are for enabling the CA injection for each CRD
-#- path: patches/cainjection_in_example.com_wordpresses.yaml
-# +kubebuilder:scaffold:crdkustomizecainjectionpatch
-
# [WEBHOOK] To enable webhook, uncomment the following section
# the following config is for teaching kustomize how to do kustomization for CRDs.
configurations:
diff --git a/testdata/project-v4-multigroup/config/crd/patches/cainjection_in_example.com_wordpresses.yaml b/testdata/project-v4-multigroup/config/crd/patches/cainjection_in_example.com_wordpresses.yaml
deleted file mode 100644
index 94469071ccf..00000000000
--- a/testdata/project-v4-multigroup/config/crd/patches/cainjection_in_example.com_wordpresses.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-# The following patch adds a directive for certmanager to inject CA into the CRD
-apiVersion: apiextensions.k8s.io/v1
-kind: CustomResourceDefinition
-metadata:
- annotations:
- cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME
- name: wordpresses.example.com.testproject.org
diff --git a/testdata/project-v4-multigroup/config/default/kustomization.yaml b/testdata/project-v4-multigroup/config/default/kustomization.yaml
index 42805e76152..3353159c5ee 100644
--- a/testdata/project-v4-multigroup/config/default/kustomization.yaml
+++ b/testdata/project-v4-multigroup/config/default/kustomization.yaml
@@ -151,27 +151,31 @@ patches:
# version: v1
# name: serving-cert # This name should match the one in certificate.yaml
# fieldPath: .metadata.namespace # Namespace of the certificate CR
-# targets:
+# targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.
# - select:
# kind: CustomResourceDefinition
+# name: wordpresses.example.com.testproject.org
# fieldPaths:
# - .metadata.annotations.[cert-manager.io/inject-ca-from]
# options:
# delimiter: '/'
# index: 0
# create: true
+# +kubebuilder:scaffold:crdkustomizecainjectionns
# - source:
# kind: Certificate
# group: cert-manager.io
# version: v1
# name: serving-cert # This name should match the one in certificate.yaml
# fieldPath: .metadata.name
-# targets:
+# targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.
# - select:
# kind: CustomResourceDefinition
+# name: wordpresses.example.com.testproject.org
# fieldPaths:
# - .metadata.annotations.[cert-manager.io/inject-ca-from]
# options:
# delimiter: '/'
# index: 1
# create: true
+# +kubebuilder:scaffold:crdkustomizecainjectionname
diff --git a/testdata/project-v4-with-plugins/config/crd/kustomization.yaml b/testdata/project-v4-with-plugins/config/crd/kustomization.yaml
index f33d8f1c5b2..387b85bcc3a 100644
--- a/testdata/project-v4-with-plugins/config/crd/kustomization.yaml
+++ b/testdata/project-v4-with-plugins/config/crd/kustomization.yaml
@@ -8,16 +8,11 @@ resources:
# +kubebuilder:scaffold:crdkustomizeresource
patches:
-# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.
+# [WEBHOOK] To enable webhooks, uncomment all the sections with [WEBHOOK] prefix.
# patches here are for enabling the conversion webhook for each CRD
- path: patches/webhook_in_wordpresses.yaml
# +kubebuilder:scaffold:crdkustomizewebhookpatch
-# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.
-# patches here are for enabling the CA injection for each CRD
-#- path: patches/cainjection_in_wordpresses.yaml
-# +kubebuilder:scaffold:crdkustomizecainjectionpatch
-
# [WEBHOOK] To enable webhook, uncomment the following section
# the following config is for teaching kustomize how to do kustomization for CRDs.
configurations:
diff --git a/testdata/project-v4-with-plugins/config/crd/patches/cainjection_in_wordpresses.yaml b/testdata/project-v4-with-plugins/config/crd/patches/cainjection_in_wordpresses.yaml
deleted file mode 100644
index 94469071ccf..00000000000
--- a/testdata/project-v4-with-plugins/config/crd/patches/cainjection_in_wordpresses.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-# The following patch adds a directive for certmanager to inject CA into the CRD
-apiVersion: apiextensions.k8s.io/v1
-kind: CustomResourceDefinition
-metadata:
- annotations:
- cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME
- name: wordpresses.example.com.testproject.org
diff --git a/testdata/project-v4-with-plugins/config/default/kustomization.yaml b/testdata/project-v4-with-plugins/config/default/kustomization.yaml
index 3ae7a46eb9d..6220768504a 100644
--- a/testdata/project-v4-with-plugins/config/default/kustomization.yaml
+++ b/testdata/project-v4-with-plugins/config/default/kustomization.yaml
@@ -151,27 +151,31 @@ patches:
# version: v1
# name: serving-cert # This name should match the one in certificate.yaml
# fieldPath: .metadata.namespace # Namespace of the certificate CR
-# targets:
+# targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.
# - select:
# kind: CustomResourceDefinition
+# name: wordpresses.example.com.testproject.org
# fieldPaths:
# - .metadata.annotations.[cert-manager.io/inject-ca-from]
# options:
# delimiter: '/'
# index: 0
# create: true
+# +kubebuilder:scaffold:crdkustomizecainjectionns
# - source:
# kind: Certificate
# group: cert-manager.io
# version: v1
# name: serving-cert # This name should match the one in certificate.yaml
# fieldPath: .metadata.name
-# targets:
+# targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.
# - select:
# kind: CustomResourceDefinition
+# name: wordpresses.example.com.testproject.org
# fieldPaths:
# - .metadata.annotations.[cert-manager.io/inject-ca-from]
# options:
# delimiter: '/'
# index: 1
# create: true
+# +kubebuilder:scaffold:crdkustomizecainjectionname
diff --git a/testdata/project-v4/PROJECT b/testdata/project-v4/PROJECT
index de92e3145d7..af39d546ce6 100644
--- a/testdata/project-v4/PROJECT
+++ b/testdata/project-v4/PROJECT
@@ -41,6 +41,26 @@ resources:
kind: FirstMate
path: sigs.k8s.io/kubebuilder/testdata/project-v4/api/v2
version: v2
+- api:
+ crdVersion: v1
+ namespaced: true
+ controller: true
+ domain: testproject.org
+ group: crew
+ kind: SecondMate
+ path: sigs.k8s.io/kubebuilder/testdata/project-v4/api/v1
+ version: v1
+ webhooks:
+ conversion: true
+ webhookVersion: v1
+- api:
+ crdVersion: v1
+ namespaced: true
+ domain: testproject.org
+ group: crew
+ kind: SecondMate
+ path: sigs.k8s.io/kubebuilder/testdata/project-v4/api/v2
+ version: v2
- api:
crdVersion: v1
controller: true
diff --git a/testdata/project-v4/api/v1/secondmate_types.go b/testdata/project-v4/api/v1/secondmate_types.go
new file mode 100644
index 00000000000..8e3ee21063a
--- /dev/null
+++ b/testdata/project-v4/api/v1/secondmate_types.go
@@ -0,0 +1,66 @@
+/*
+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
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+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.
+*/
+
+package v1
+
+import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
+// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
+
+// SecondMateSpec defines the desired state of SecondMate.
+type SecondMateSpec struct {
+ // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
+ // Important: Run "make" to regenerate code after modifying this file
+
+ // Foo is an example field of SecondMate. Edit secondmate_types.go to remove/update
+ Foo string `json:"foo,omitempty"`
+}
+
+// SecondMateStatus defines the observed state of SecondMate.
+type SecondMateStatus struct {
+ // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
+ // Important: Run "make" to regenerate code after modifying this file
+}
+
+// +kubebuilder:object:root=true
+// +kubebuilder:subresource:status
+// +kubebuilder:storageversion
+// +kubebuilder:conversion:hub
+
+// SecondMate is the Schema for the secondmates API.
+type SecondMate struct {
+ metav1.TypeMeta `json:",inline"`
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ Spec SecondMateSpec `json:"spec,omitempty"`
+ Status SecondMateStatus `json:"status,omitempty"`
+}
+
+// +kubebuilder:object:root=true
+
+// SecondMateList contains a list of SecondMate.
+type SecondMateList struct {
+ metav1.TypeMeta `json:",inline"`
+ metav1.ListMeta `json:"metadata,omitempty"`
+ Items []SecondMate `json:"items"`
+}
+
+func init() {
+ SchemeBuilder.Register(&SecondMate{}, &SecondMateList{})
+}
diff --git a/testdata/project-v4/api/v1/zz_generated.deepcopy.go b/testdata/project-v4/api/v1/zz_generated.deepcopy.go
index 24fb3a25515..62e739c216e 100644
--- a/testdata/project-v4/api/v1/zz_generated.deepcopy.go
+++ b/testdata/project-v4/api/v1/zz_generated.deepcopy.go
@@ -290,3 +290,92 @@ func (in *FirstMateStatus) DeepCopy() *FirstMateStatus {
in.DeepCopyInto(out)
return out
}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SecondMate) DeepCopyInto(out *SecondMate) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+ out.Spec = in.Spec
+ out.Status = in.Status
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecondMate.
+func (in *SecondMate) DeepCopy() *SecondMate {
+ if in == nil {
+ return nil
+ }
+ out := new(SecondMate)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *SecondMate) DeepCopyObject() runtime.Object {
+ if c := in.DeepCopy(); c != nil {
+ return c
+ }
+ return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SecondMateList) DeepCopyInto(out *SecondMateList) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ListMeta.DeepCopyInto(&out.ListMeta)
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]SecondMate, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecondMateList.
+func (in *SecondMateList) DeepCopy() *SecondMateList {
+ if in == nil {
+ return nil
+ }
+ out := new(SecondMateList)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *SecondMateList) DeepCopyObject() runtime.Object {
+ if c := in.DeepCopy(); c != nil {
+ return c
+ }
+ return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SecondMateSpec) DeepCopyInto(out *SecondMateSpec) {
+ *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecondMateSpec.
+func (in *SecondMateSpec) DeepCopy() *SecondMateSpec {
+ if in == nil {
+ return nil
+ }
+ out := new(SecondMateSpec)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SecondMateStatus) DeepCopyInto(out *SecondMateStatus) {
+ *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecondMateStatus.
+func (in *SecondMateStatus) DeepCopy() *SecondMateStatus {
+ if in == nil {
+ return nil
+ }
+ out := new(SecondMateStatus)
+ in.DeepCopyInto(out)
+ return out
+}
diff --git a/testdata/project-v4/api/v2/secondmate_types.go b/testdata/project-v4/api/v2/secondmate_types.go
new file mode 100644
index 00000000000..5b9cdda1da9
--- /dev/null
+++ b/testdata/project-v4/api/v2/secondmate_types.go
@@ -0,0 +1,64 @@
+/*
+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
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+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.
+*/
+
+package v2
+
+import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
+// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
+
+// SecondMateSpec defines the desired state of SecondMate.
+type SecondMateSpec struct {
+ // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
+ // Important: Run "make" to regenerate code after modifying this file
+
+ // Foo is an example field of SecondMate. Edit secondmate_types.go to remove/update
+ Foo string `json:"foo,omitempty"`
+}
+
+// SecondMateStatus defines the observed state of SecondMate.
+type SecondMateStatus struct {
+ // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
+ // Important: Run "make" to regenerate code after modifying this file
+}
+
+// +kubebuilder:object:root=true
+// +kubebuilder:subresource:status
+
+// SecondMate is the Schema for the secondmates API.
+type SecondMate struct {
+ metav1.TypeMeta `json:",inline"`
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ Spec SecondMateSpec `json:"spec,omitempty"`
+ Status SecondMateStatus `json:"status,omitempty"`
+}
+
+// +kubebuilder:object:root=true
+
+// SecondMateList contains a list of SecondMate.
+type SecondMateList struct {
+ metav1.TypeMeta `json:",inline"`
+ metav1.ListMeta `json:"metadata,omitempty"`
+ Items []SecondMate `json:"items"`
+}
+
+func init() {
+ SchemeBuilder.Register(&SecondMate{}, &SecondMateList{})
+}
diff --git a/testdata/project-v4/api/v2/zz_generated.deepcopy.go b/testdata/project-v4/api/v2/zz_generated.deepcopy.go
index db8e6aded83..b3314ebe5c4 100644
--- a/testdata/project-v4/api/v2/zz_generated.deepcopy.go
+++ b/testdata/project-v4/api/v2/zz_generated.deepcopy.go
@@ -112,3 +112,92 @@ func (in *FirstMateStatus) DeepCopy() *FirstMateStatus {
in.DeepCopyInto(out)
return out
}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SecondMate) DeepCopyInto(out *SecondMate) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+ out.Spec = in.Spec
+ out.Status = in.Status
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecondMate.
+func (in *SecondMate) DeepCopy() *SecondMate {
+ if in == nil {
+ return nil
+ }
+ out := new(SecondMate)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *SecondMate) DeepCopyObject() runtime.Object {
+ if c := in.DeepCopy(); c != nil {
+ return c
+ }
+ return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SecondMateList) DeepCopyInto(out *SecondMateList) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ListMeta.DeepCopyInto(&out.ListMeta)
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]SecondMate, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecondMateList.
+func (in *SecondMateList) DeepCopy() *SecondMateList {
+ if in == nil {
+ return nil
+ }
+ out := new(SecondMateList)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *SecondMateList) DeepCopyObject() runtime.Object {
+ if c := in.DeepCopy(); c != nil {
+ return c
+ }
+ return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SecondMateSpec) DeepCopyInto(out *SecondMateSpec) {
+ *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecondMateSpec.
+func (in *SecondMateSpec) DeepCopy() *SecondMateSpec {
+ if in == nil {
+ return nil
+ }
+ out := new(SecondMateSpec)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SecondMateStatus) DeepCopyInto(out *SecondMateStatus) {
+ *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecondMateStatus.
+func (in *SecondMateStatus) DeepCopy() *SecondMateStatus {
+ if in == nil {
+ return nil
+ }
+ out := new(SecondMateStatus)
+ in.DeepCopyInto(out)
+ return out
+}
diff --git a/testdata/project-v4/cmd/main.go b/testdata/project-v4/cmd/main.go
index e7b186138dd..3636feee7c5 100644
--- a/testdata/project-v4/cmd/main.go
+++ b/testdata/project-v4/cmd/main.go
@@ -178,6 +178,20 @@ func main() {
os.Exit(1)
}
}
+ if err = (&controller.SecondMateReconciler{
+ Client: mgr.GetClient(),
+ Scheme: mgr.GetScheme(),
+ }).SetupWithManager(mgr); err != nil {
+ setupLog.Error(err, "unable to create controller", "controller", "SecondMate")
+ os.Exit(1)
+ }
+ // nolint:goconst
+ if os.Getenv("ENABLE_WEBHOOKS") != "false" {
+ if err = webhookcrewv1.SetupSecondMateWebhookWithManager(mgr); err != nil {
+ setupLog.Error(err, "unable to create webhook", "webhook", "SecondMate")
+ os.Exit(1)
+ }
+ }
if err = (&controller.AdmiralReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
diff --git a/testdata/project-v4/config/crd/bases/crew.testproject.org_secondmates.yaml b/testdata/project-v4/config/crd/bases/crew.testproject.org_secondmates.yaml
new file mode 100644
index 00000000000..977b2ae301c
--- /dev/null
+++ b/testdata/project-v4/config/crd/bases/crew.testproject.org_secondmates.yaml
@@ -0,0 +1,92 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.16.4
+ name: secondmates.crew.testproject.org
+spec:
+ group: crew.testproject.org
+ names:
+ kind: SecondMate
+ listKind: SecondMateList
+ plural: secondmates
+ singular: secondmate
+ scope: Namespaced
+ versions:
+ - name: v1
+ schema:
+ openAPIV3Schema:
+ description: SecondMate is the Schema for the secondmates API.
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: SecondMateSpec defines the desired state of SecondMate.
+ properties:
+ foo:
+ description: Foo is an example field of SecondMate. Edit secondmate_types.go
+ to remove/update
+ type: string
+ type: object
+ status:
+ description: SecondMateStatus defines the observed state of SecondMate.
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
+ - name: v2
+ schema:
+ openAPIV3Schema:
+ description: SecondMate is the Schema for the secondmates API.
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: SecondMateSpec defines the desired state of SecondMate.
+ properties:
+ foo:
+ description: Foo is an example field of SecondMate. Edit secondmate_types.go
+ to remove/update
+ type: string
+ type: object
+ status:
+ description: SecondMateStatus defines the observed state of SecondMate.
+ type: object
+ type: object
+ served: true
+ storage: false
+ subresources:
+ status: {}
diff --git a/testdata/project-v4/config/crd/kustomization.yaml b/testdata/project-v4/config/crd/kustomization.yaml
index ee1e6daefc4..828e1cdf634 100644
--- a/testdata/project-v4/config/crd/kustomization.yaml
+++ b/testdata/project-v4/config/crd/kustomization.yaml
@@ -4,20 +4,17 @@
resources:
- bases/crew.testproject.org_captains.yaml
- bases/crew.testproject.org_firstmates.yaml
+- bases/crew.testproject.org_secondmates.yaml
- bases/crew.testproject.org_admirales.yaml
# +kubebuilder:scaffold:crdkustomizeresource
patches:
-# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.
+# [WEBHOOK] To enable webhooks, uncomment all the sections with [WEBHOOK] prefix.
# patches here are for enabling the conversion webhook for each CRD
- path: patches/webhook_in_firstmates.yaml
+- path: patches/webhook_in_secondmates.yaml
# +kubebuilder:scaffold:crdkustomizewebhookpatch
-# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.
-# patches here are for enabling the CA injection for each CRD
-#- path: patches/cainjection_in_firstmates.yaml
-# +kubebuilder:scaffold:crdkustomizecainjectionpatch
-
# [WEBHOOK] To enable webhook, uncomment the following section
# the following config is for teaching kustomize how to do kustomization for CRDs.
configurations:
diff --git a/testdata/project-v4/config/crd/patches/cainjection_in_firstmates.yaml b/testdata/project-v4/config/crd/patches/cainjection_in_firstmates.yaml
deleted file mode 100644
index 69292458eb5..00000000000
--- a/testdata/project-v4/config/crd/patches/cainjection_in_firstmates.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-# The following patch adds a directive for certmanager to inject CA into the CRD
-apiVersion: apiextensions.k8s.io/v1
-kind: CustomResourceDefinition
-metadata:
- annotations:
- cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME
- name: firstmates.crew.testproject.org
diff --git a/testdata/project-v4/config/crd/patches/webhook_in_secondmates.yaml b/testdata/project-v4/config/crd/patches/webhook_in_secondmates.yaml
new file mode 100644
index 00000000000..3770bb6b81b
--- /dev/null
+++ b/testdata/project-v4/config/crd/patches/webhook_in_secondmates.yaml
@@ -0,0 +1,16 @@
+# The following patch enables a conversion webhook for the CRD
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ name: secondmates.crew.testproject.org
+spec:
+ conversion:
+ strategy: Webhook
+ webhook:
+ clientConfig:
+ service:
+ namespace: system
+ name: webhook-service
+ path: /convert
+ conversionReviewVersions:
+ - v1
diff --git a/testdata/project-v4/config/default/kustomization.yaml b/testdata/project-v4/config/default/kustomization.yaml
index abb243b2308..1a4cf738acc 100644
--- a/testdata/project-v4/config/default/kustomization.yaml
+++ b/testdata/project-v4/config/default/kustomization.yaml
@@ -151,27 +151,49 @@ patches:
# version: v1
# name: serving-cert # This name should match the one in certificate.yaml
# fieldPath: .metadata.namespace # Namespace of the certificate CR
-# targets:
+# targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.
+# - select:
+# kind: CustomResourceDefinition
+# name: firstmates.crew.testproject.org
+# fieldPaths:
+# - .metadata.annotations.[cert-manager.io/inject-ca-from]
+# options:
+# delimiter: '/'
+# index: 0
+# create: true
# - select:
# kind: CustomResourceDefinition
+# name: secondmates.crew.testproject.org
# fieldPaths:
# - .metadata.annotations.[cert-manager.io/inject-ca-from]
# options:
# delimiter: '/'
# index: 0
# create: true
+# +kubebuilder:scaffold:crdkustomizecainjectionns
# - source:
# kind: Certificate
# group: cert-manager.io
# version: v1
# name: serving-cert # This name should match the one in certificate.yaml
# fieldPath: .metadata.name
-# targets:
+# targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.
+# - select:
+# kind: CustomResourceDefinition
+# name: firstmates.crew.testproject.org
+# fieldPaths:
+# - .metadata.annotations.[cert-manager.io/inject-ca-from]
+# options:
+# delimiter: '/'
+# index: 1
+# create: true
# - select:
# kind: CustomResourceDefinition
+# name: secondmates.crew.testproject.org
# fieldPaths:
# - .metadata.annotations.[cert-manager.io/inject-ca-from]
# options:
# delimiter: '/'
# index: 1
# create: true
+# +kubebuilder:scaffold:crdkustomizecainjectionname
diff --git a/testdata/project-v4/config/rbac/kustomization.yaml b/testdata/project-v4/config/rbac/kustomization.yaml
index b6ac31fc556..78a26b2026a 100644
--- a/testdata/project-v4/config/rbac/kustomization.yaml
+++ b/testdata/project-v4/config/rbac/kustomization.yaml
@@ -24,6 +24,8 @@ resources:
# if you do not want those helpers be installed with your Project.
- admiral_editor_role.yaml
- admiral_viewer_role.yaml
+- secondmate_editor_role.yaml
+- secondmate_viewer_role.yaml
- firstmate_editor_role.yaml
- firstmate_viewer_role.yaml
- captain_editor_role.yaml
diff --git a/testdata/project-v4/config/rbac/role.yaml b/testdata/project-v4/config/rbac/role.yaml
index dfa4ad22cab..e220986523b 100644
--- a/testdata/project-v4/config/rbac/role.yaml
+++ b/testdata/project-v4/config/rbac/role.yaml
@@ -36,6 +36,7 @@ rules:
- admirales
- captains
- firstmates
+ - secondmates
verbs:
- create
- delete
@@ -50,6 +51,7 @@ rules:
- admirales/finalizers
- captains/finalizers
- firstmates/finalizers
+ - secondmates/finalizers
verbs:
- update
- apiGroups:
@@ -58,6 +60,7 @@ rules:
- admirales/status
- captains/status
- firstmates/status
+ - secondmates/status
verbs:
- get
- patch
diff --git a/testdata/project-v4/config/rbac/secondmate_editor_role.yaml b/testdata/project-v4/config/rbac/secondmate_editor_role.yaml
new file mode 100644
index 00000000000..bb272d1b185
--- /dev/null
+++ b/testdata/project-v4/config/rbac/secondmate_editor_role.yaml
@@ -0,0 +1,27 @@
+# permissions for end users to edit secondmates.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ labels:
+ app.kubernetes.io/name: project-v4
+ app.kubernetes.io/managed-by: kustomize
+ name: secondmate-editor-role
+rules:
+- apiGroups:
+ - crew.testproject.org
+ resources:
+ - secondmates
+ verbs:
+ - create
+ - delete
+ - get
+ - list
+ - patch
+ - update
+ - watch
+- apiGroups:
+ - crew.testproject.org
+ resources:
+ - secondmates/status
+ verbs:
+ - get
diff --git a/testdata/project-v4/config/rbac/secondmate_viewer_role.yaml b/testdata/project-v4/config/rbac/secondmate_viewer_role.yaml
new file mode 100644
index 00000000000..893c05625a6
--- /dev/null
+++ b/testdata/project-v4/config/rbac/secondmate_viewer_role.yaml
@@ -0,0 +1,23 @@
+# permissions for end users to view secondmates.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ labels:
+ app.kubernetes.io/name: project-v4
+ app.kubernetes.io/managed-by: kustomize
+ name: secondmate-viewer-role
+rules:
+- apiGroups:
+ - crew.testproject.org
+ resources:
+ - secondmates
+ verbs:
+ - get
+ - list
+ - watch
+- apiGroups:
+ - crew.testproject.org
+ resources:
+ - secondmates/status
+ verbs:
+ - get
diff --git a/testdata/project-v4/config/samples/crew_v1_secondmate.yaml b/testdata/project-v4/config/samples/crew_v1_secondmate.yaml
new file mode 100644
index 00000000000..cba6de34b3d
--- /dev/null
+++ b/testdata/project-v4/config/samples/crew_v1_secondmate.yaml
@@ -0,0 +1,9 @@
+apiVersion: crew.testproject.org/v1
+kind: SecondMate
+metadata:
+ labels:
+ app.kubernetes.io/name: project-v4
+ app.kubernetes.io/managed-by: kustomize
+ name: secondmate-sample
+spec:
+ # TODO(user): Add fields here
diff --git a/testdata/project-v4/config/samples/crew_v2_secondmate.yaml b/testdata/project-v4/config/samples/crew_v2_secondmate.yaml
new file mode 100644
index 00000000000..548e7a9c9d5
--- /dev/null
+++ b/testdata/project-v4/config/samples/crew_v2_secondmate.yaml
@@ -0,0 +1,9 @@
+apiVersion: crew.testproject.org/v2
+kind: SecondMate
+metadata:
+ labels:
+ app.kubernetes.io/name: project-v4
+ app.kubernetes.io/managed-by: kustomize
+ name: secondmate-sample
+spec:
+ # TODO(user): Add fields here
diff --git a/testdata/project-v4/config/samples/kustomization.yaml b/testdata/project-v4/config/samples/kustomization.yaml
index ce83fd55d0c..cec4be3afa0 100644
--- a/testdata/project-v4/config/samples/kustomization.yaml
+++ b/testdata/project-v4/config/samples/kustomization.yaml
@@ -3,5 +3,7 @@ resources:
- crew_v1_captain.yaml
- crew_v1_firstmate.yaml
- crew_v2_firstmate.yaml
+- crew_v1_secondmate.yaml
+- crew_v2_secondmate.yaml
- crew_v1_admiral.yaml
# +kubebuilder:scaffold:manifestskustomizesamples
diff --git a/testdata/project-v4/dist/install.yaml b/testdata/project-v4/dist/install.yaml
index 9b1821f4e6b..babd3531a13 100644
--- a/testdata/project-v4/dist/install.yaml
+++ b/testdata/project-v4/dist/install.yaml
@@ -217,6 +217,108 @@ spec:
subresources:
status: {}
---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.16.4
+ name: secondmates.crew.testproject.org
+spec:
+ conversion:
+ strategy: Webhook
+ webhook:
+ clientConfig:
+ service:
+ name: project-v4-webhook-service
+ namespace: project-v4-system
+ path: /convert
+ conversionReviewVersions:
+ - v1
+ group: crew.testproject.org
+ names:
+ kind: SecondMate
+ listKind: SecondMateList
+ plural: secondmates
+ singular: secondmate
+ scope: Namespaced
+ versions:
+ - name: v1
+ schema:
+ openAPIV3Schema:
+ description: SecondMate is the Schema for the secondmates API.
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: SecondMateSpec defines the desired state of SecondMate.
+ properties:
+ foo:
+ description: Foo is an example field of SecondMate. Edit secondmate_types.go
+ to remove/update
+ type: string
+ type: object
+ status:
+ description: SecondMateStatus defines the observed state of SecondMate.
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
+ - name: v2
+ schema:
+ openAPIV3Schema:
+ description: SecondMate is the Schema for the secondmates API.
+ properties:
+ apiVersion:
+ description: |-
+ APIVersion defines the versioned schema of this representation of an object.
+ Servers should convert recognized schemas to the latest internal value, and
+ may reject unrecognized values.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
+ type: string
+ kind:
+ description: |-
+ Kind is a string value representing the REST resource this object represents.
+ Servers may infer this from the endpoint the client submits requests to.
+ Cannot be updated.
+ In CamelCase.
+ More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
+ type: string
+ metadata:
+ type: object
+ spec:
+ description: SecondMateSpec defines the desired state of SecondMate.
+ properties:
+ foo:
+ description: Foo is an example field of SecondMate. Edit secondmate_types.go
+ to remove/update
+ type: string
+ type: object
+ status:
+ description: SecondMateStatus defines the observed state of SecondMate.
+ type: object
+ type: object
+ served: true
+ storage: false
+ subresources:
+ status: {}
+---
apiVersion: v1
kind: ServiceAccount
metadata:
@@ -454,6 +556,7 @@ rules:
- admirales
- captains
- firstmates
+ - secondmates
verbs:
- create
- delete
@@ -468,6 +571,7 @@ rules:
- admirales/finalizers
- captains/finalizers
- firstmates/finalizers
+ - secondmates/finalizers
verbs:
- update
- apiGroups:
@@ -476,6 +580,7 @@ rules:
- admirales/status
- captains/status
- firstmates/status
+ - secondmates/status
verbs:
- get
- patch
@@ -510,6 +615,56 @@ rules:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ labels:
+ app.kubernetes.io/managed-by: kustomize
+ app.kubernetes.io/name: project-v4
+ name: project-v4-secondmate-editor-role
+rules:
+- apiGroups:
+ - crew.testproject.org
+ resources:
+ - secondmates
+ verbs:
+ - create
+ - delete
+ - get
+ - list
+ - patch
+ - update
+ - watch
+- apiGroups:
+ - crew.testproject.org
+ resources:
+ - secondmates/status
+ verbs:
+ - get
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ labels:
+ app.kubernetes.io/managed-by: kustomize
+ app.kubernetes.io/name: project-v4
+ name: project-v4-secondmate-viewer-role
+rules:
+- apiGroups:
+ - crew.testproject.org
+ resources:
+ - secondmates
+ verbs:
+ - get
+ - list
+ - watch
+- apiGroups:
+ - crew.testproject.org
+ resources:
+ - secondmates/status
+ verbs:
+ - get
+---
+apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
diff --git a/testdata/project-v4/internal/controller/secondmate_controller.go b/testdata/project-v4/internal/controller/secondmate_controller.go
new file mode 100644
index 00000000000..b7af850aa0e
--- /dev/null
+++ b/testdata/project-v4/internal/controller/secondmate_controller.go
@@ -0,0 +1,63 @@
+/*
+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
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+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.
+*/
+
+package controller
+
+import (
+ "context"
+
+ "k8s.io/apimachinery/pkg/runtime"
+ ctrl "sigs.k8s.io/controller-runtime"
+ "sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/controller-runtime/pkg/log"
+
+ crewv1 "sigs.k8s.io/kubebuilder/testdata/project-v4/api/v1"
+)
+
+// SecondMateReconciler reconciles a SecondMate object
+type SecondMateReconciler struct {
+ client.Client
+ Scheme *runtime.Scheme
+}
+
+// +kubebuilder:rbac:groups=crew.testproject.org,resources=secondmates,verbs=get;list;watch;create;update;patch;delete
+// +kubebuilder:rbac:groups=crew.testproject.org,resources=secondmates/status,verbs=get;update;patch
+// +kubebuilder:rbac:groups=crew.testproject.org,resources=secondmates/finalizers,verbs=update
+
+// Reconcile is part of the main kubernetes reconciliation loop which aims to
+// move the current state of the cluster closer to the desired state.
+// TODO(user): Modify the Reconcile function to compare the state specified by
+// the SecondMate object against the actual cluster state, and then
+// perform operations to make the cluster state reflect the state specified by
+// the user.
+//
+// For more details, check Reconcile and its Result here:
+// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.19.1/pkg/reconcile
+func (r *SecondMateReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
+ _ = log.FromContext(ctx)
+
+ // TODO(user): your logic here
+
+ return ctrl.Result{}, nil
+}
+
+// SetupWithManager sets up the controller with the Manager.
+func (r *SecondMateReconciler) SetupWithManager(mgr ctrl.Manager) error {
+ return ctrl.NewControllerManagedBy(mgr).
+ For(&crewv1.SecondMate{}).
+ Named("secondmate").
+ Complete(r)
+}
diff --git a/testdata/project-v4/internal/controller/secondmate_controller_test.go b/testdata/project-v4/internal/controller/secondmate_controller_test.go
new file mode 100644
index 00000000000..333945fe610
--- /dev/null
+++ b/testdata/project-v4/internal/controller/secondmate_controller_test.go
@@ -0,0 +1,84 @@
+/*
+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
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+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.
+*/
+
+package controller
+
+import (
+ "context"
+
+ . "github.com/onsi/ginkgo/v2"
+ . "github.com/onsi/gomega"
+ "k8s.io/apimachinery/pkg/api/errors"
+ "k8s.io/apimachinery/pkg/types"
+ "sigs.k8s.io/controller-runtime/pkg/reconcile"
+
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+ crewv1 "sigs.k8s.io/kubebuilder/testdata/project-v4/api/v1"
+)
+
+var _ = Describe("SecondMate Controller", func() {
+ Context("When reconciling a resource", func() {
+ const resourceName = "test-resource"
+
+ ctx := context.Background()
+
+ typeNamespacedName := types.NamespacedName{
+ Name: resourceName,
+ Namespace: "default", // TODO(user):Modify as needed
+ }
+ secondmate := &crewv1.SecondMate{}
+
+ BeforeEach(func() {
+ By("creating the custom resource for the Kind SecondMate")
+ err := k8sClient.Get(ctx, typeNamespacedName, secondmate)
+ if err != nil && errors.IsNotFound(err) {
+ resource := &crewv1.SecondMate{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: resourceName,
+ Namespace: "default",
+ },
+ // TODO(user): Specify other spec details if needed.
+ }
+ Expect(k8sClient.Create(ctx, resource)).To(Succeed())
+ }
+ })
+
+ AfterEach(func() {
+ // TODO(user): Cleanup logic after each test, like removing the resource instance.
+ resource := &crewv1.SecondMate{}
+ err := k8sClient.Get(ctx, typeNamespacedName, resource)
+ Expect(err).NotTo(HaveOccurred())
+
+ By("Cleanup the specific resource instance SecondMate")
+ Expect(k8sClient.Delete(ctx, resource)).To(Succeed())
+ })
+ It("should successfully reconcile the resource", func() {
+ By("Reconciling the created resource")
+ controllerReconciler := &SecondMateReconciler{
+ Client: k8sClient,
+ Scheme: k8sClient.Scheme(),
+ }
+
+ _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{
+ NamespacedName: typeNamespacedName,
+ })
+ Expect(err).NotTo(HaveOccurred())
+ // TODO(user): Add more specific assertions depending on your controller's reconciliation logic.
+ // Example: If you expect a certain status condition after reconciliation, verify it here.
+ })
+ })
+})
diff --git a/testdata/project-v4/internal/webhook/v1/secondmate_webhook.go b/testdata/project-v4/internal/webhook/v1/secondmate_webhook.go
new file mode 100644
index 00000000000..1947cbfbb17
--- /dev/null
+++ b/testdata/project-v4/internal/webhook/v1/secondmate_webhook.go
@@ -0,0 +1,36 @@
+/*
+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
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+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.
+*/
+
+package v1
+
+import (
+ ctrl "sigs.k8s.io/controller-runtime"
+ logf "sigs.k8s.io/controller-runtime/pkg/log"
+
+ crewv1 "sigs.k8s.io/kubebuilder/testdata/project-v4/api/v1"
+)
+
+// nolint:unused
+// log is for logging in this package.
+var secondmatelog = logf.Log.WithName("secondmate-resource")
+
+// SetupSecondMateWebhookWithManager registers the webhook for SecondMate in the manager.
+func SetupSecondMateWebhookWithManager(mgr ctrl.Manager) error {
+ return ctrl.NewWebhookManagedBy(mgr).For(&crewv1.SecondMate{}).
+ Complete()
+}
+
+// TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
diff --git a/testdata/project-v4/internal/webhook/v1/secondmate_webhook_test.go b/testdata/project-v4/internal/webhook/v1/secondmate_webhook_test.go
new file mode 100644
index 00000000000..f62e8062582
--- /dev/null
+++ b/testdata/project-v4/internal/webhook/v1/secondmate_webhook_test.go
@@ -0,0 +1,55 @@
+/*
+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
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+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.
+*/
+
+package v1
+
+import (
+ . "github.com/onsi/ginkgo/v2"
+ . "github.com/onsi/gomega"
+
+ crewv1 "sigs.k8s.io/kubebuilder/testdata/project-v4/api/v1"
+ // TODO (user): Add any additional imports if needed
+)
+
+var _ = Describe("SecondMate Webhook", func() {
+ var (
+ obj *crewv1.SecondMate
+ oldObj *crewv1.SecondMate
+ )
+
+ BeforeEach(func() {
+ obj = &crewv1.SecondMate{}
+ oldObj = &crewv1.SecondMate{}
+ Expect(oldObj).NotTo(BeNil(), "Expected oldObj to be initialized")
+ Expect(obj).NotTo(BeNil(), "Expected obj to be initialized")
+ // TODO (user): Add any setup logic common to all tests
+ })
+
+ AfterEach(func() {
+ // TODO (user): Add any teardown logic common to all tests
+ })
+
+ Context("When creating SecondMate 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 := &crewv1.SecondMate{}
+ // Expect(obj.ConvertTo(convertedObj)).To(Succeed())
+ // Expect(convertedObj).ToNot(BeNil())
+ // })
+ })
+
+})