From 8f86fbae565eeda4273bb8528710bfd6ef16cfcf Mon Sep 17 00:00:00 2001 From: Camila Macedo <camilamacedo86@gmail.com> Date: Thu, 31 Oct 2024 11:38:13 +0000 Subject: [PATCH] fix: optimize and improve testdata scaffolding for webhook conversion - Set for all steps to speed up project generation - Adjust mock data to include webhook conversion scenarios NOTE: This update addresses bug fixes and enhancements requiring these mock datasets, including future support for hub-and-spoke webhook scaffolding and Helm plugin compatibility. Ensuring comprehensive coverage in testdata helps validate these scenarios effectively. --- test/testdata/generate.sh | 48 ++++- testdata/project-v4-multigroup/PROJECT | 23 ++- .../api/example.com/v1/groupversion_info.go | 36 ++++ .../api/example.com/v1/wordpress_types.go | 65 +++++++ .../example.com/v1/zz_generated.deepcopy.go | 114 ++++++++++++ .../api/example.com/v2/groupversion_info.go | 36 ++++ .../api/example.com/v2/wordpress_types.go | 64 +++++++ .../example.com/v2/zz_generated.deepcopy.go | 114 ++++++++++++ testdata/project-v4-multigroup/cmd/main.go | 27 ++- ...ample.com.testproject.org_wordpresses.yaml | 92 ++++++++++ .../config/crd/kustomization.yaml | 4 +- ...injection_in_example.com_wordpresses.yaml} | 2 +- ...> webhook_in_example.com_wordpresses.yaml} | 2 +- .../example.com_wordpress_editor_role.yaml | 27 +++ .../example.com_wordpress_viewer_role.yaml | 23 +++ .../config/rbac/kustomization.yaml | 2 + .../config/rbac/role.yaml | 3 + .../samples/example.com_v1_wordpress.yaml | 9 + .../samples/example.com_v2_wordpress.yaml | 9 + .../config/samples/kustomization.yaml | 2 + .../project-v4-multigroup/dist/install.yaml | 165 ++++++++++++++++-- .../controller/example.com/suite_test.go | 4 + .../example.com/wordpress_controller.go | 63 +++++++ .../example.com/wordpress_controller_test.go | 84 +++++++++ .../example.com/v1/wordpress_webhook.go | 36 ++++ .../example.com/v1/wordpress_webhook_test.go | 55 ++++++ testdata/project-v4-with-plugins/PROJECT | 20 +++ .../api/v1/groupversion_info.go | 36 ++++ .../api/v1/wordpress_types.go | 65 +++++++ .../api/v1/zz_generated.deepcopy.go | 114 ++++++++++++ .../api/v2/groupversion_info.go | 36 ++++ .../api/v2/wordpress_types.go | 64 +++++++ .../api/v2/zz_generated.deepcopy.go | 114 ++++++++++++ testdata/project-v4-with-plugins/cmd/main.go | 19 ++ ...ample.com.testproject.org_wordpresses.yaml | 92 ++++++++++ .../config/crd/kustomization.yaml | 3 + .../patches/cainjection_in_wordpresses.yaml | 7 + .../crd/patches/webhook_in_wordpresses.yaml | 16 ++ .../config/rbac/kustomization.yaml | 2 + .../config/rbac/role.yaml | 3 + .../config/rbac/wordpress_editor_role.yaml | 27 +++ .../config/rbac/wordpress_viewer_role.yaml | 23 +++ .../samples/example.com_v1_wordpress.yaml | 9 + .../samples/example.com_v2_wordpress.yaml | 9 + .../config/samples/kustomization.yaml | 2 + .../project-v4-with-plugins/dist/install.yaml | 155 ++++++++++++++++ .../internal/controller/suite_test.go | 4 + .../controller/wordpress_controller.go | 63 +++++++ .../controller/wordpress_controller_test.go | 84 +++++++++ .../internal/webhook/v1/wordpress_webhook.go} | 12 +- .../webhook/v1/wordpress_webhook_test.go} | 18 +- testdata/project-v4/PROJECT | 8 + testdata/project-v4/api/v1/firstmate_types.go | 3 +- testdata/project-v4/api/v2/firstmate_types.go | 64 +++++++ .../project-v4/api/v2/groupversion_info.go | 36 ++++ .../api/v2/zz_generated.deepcopy.go | 114 ++++++++++++ testdata/project-v4/cmd/main.go | 2 + .../crew.testproject.org_firstmates.yaml | 38 ++++ .../config/samples/crew_v2_firstmate.yaml | 9 + .../config/samples/kustomization.yaml | 1 + testdata/project-v4/dist/install.yaml | 38 ++++ 61 files changed, 2371 insertions(+), 48 deletions(-) create mode 100644 testdata/project-v4-multigroup/api/example.com/v1/groupversion_info.go create mode 100644 testdata/project-v4-multigroup/api/example.com/v1/wordpress_types.go create mode 100644 testdata/project-v4-multigroup/api/example.com/v1/zz_generated.deepcopy.go create mode 100644 testdata/project-v4-multigroup/api/example.com/v2/groupversion_info.go create mode 100644 testdata/project-v4-multigroup/api/example.com/v2/wordpress_types.go create mode 100644 testdata/project-v4-multigroup/api/example.com/v2/zz_generated.deepcopy.go create mode 100644 testdata/project-v4-multigroup/config/crd/bases/example.com.testproject.org_wordpresses.yaml rename testdata/project-v4-multigroup/config/crd/patches/{cainjection_in_ship_frigates.yaml => cainjection_in_example.com_wordpresses.yaml} (83%) rename testdata/project-v4-multigroup/config/crd/patches/{webhook_in_ship_frigates.yaml => webhook_in_example.com_wordpresses.yaml} (88%) create mode 100644 testdata/project-v4-multigroup/config/rbac/example.com_wordpress_editor_role.yaml create mode 100644 testdata/project-v4-multigroup/config/rbac/example.com_wordpress_viewer_role.yaml create mode 100644 testdata/project-v4-multigroup/config/samples/example.com_v1_wordpress.yaml create mode 100644 testdata/project-v4-multigroup/config/samples/example.com_v2_wordpress.yaml create mode 100644 testdata/project-v4-multigroup/internal/controller/example.com/wordpress_controller.go create mode 100644 testdata/project-v4-multigroup/internal/controller/example.com/wordpress_controller_test.go create mode 100644 testdata/project-v4-multigroup/internal/webhook/example.com/v1/wordpress_webhook.go create mode 100644 testdata/project-v4-multigroup/internal/webhook/example.com/v1/wordpress_webhook_test.go create mode 100644 testdata/project-v4-with-plugins/api/v1/groupversion_info.go create mode 100644 testdata/project-v4-with-plugins/api/v1/wordpress_types.go create mode 100644 testdata/project-v4-with-plugins/api/v1/zz_generated.deepcopy.go create mode 100644 testdata/project-v4-with-plugins/api/v2/groupversion_info.go create mode 100644 testdata/project-v4-with-plugins/api/v2/wordpress_types.go create mode 100644 testdata/project-v4-with-plugins/api/v2/zz_generated.deepcopy.go create mode 100644 testdata/project-v4-with-plugins/config/crd/bases/example.com.testproject.org_wordpresses.yaml create mode 100644 testdata/project-v4-with-plugins/config/crd/patches/cainjection_in_wordpresses.yaml create mode 100644 testdata/project-v4-with-plugins/config/crd/patches/webhook_in_wordpresses.yaml create mode 100644 testdata/project-v4-with-plugins/config/rbac/wordpress_editor_role.yaml create mode 100644 testdata/project-v4-with-plugins/config/rbac/wordpress_viewer_role.yaml create mode 100644 testdata/project-v4-with-plugins/config/samples/example.com_v1_wordpress.yaml create mode 100644 testdata/project-v4-with-plugins/config/samples/example.com_v2_wordpress.yaml create mode 100644 testdata/project-v4-with-plugins/internal/controller/wordpress_controller.go create mode 100644 testdata/project-v4-with-plugins/internal/controller/wordpress_controller_test.go rename testdata/{project-v4-multigroup/internal/webhook/ship/v1beta1/frigate_webhook.go => project-v4-with-plugins/internal/webhook/v1/wordpress_webhook.go} (68%) rename testdata/{project-v4-multigroup/internal/webhook/ship/v1beta1/frigate_webhook_test.go => project-v4-with-plugins/internal/webhook/v1/wordpress_webhook_test.go} (76%) create mode 100644 testdata/project-v4/api/v2/firstmate_types.go create mode 100644 testdata/project-v4/api/v2/groupversion_info.go create mode 100644 testdata/project-v4/api/v2/zz_generated.deepcopy.go create mode 100644 testdata/project-v4/config/samples/crew_v2_firstmate.yaml diff --git a/test/testdata/generate.sh b/test/testdata/generate.sh index 4d96fb2abc9..e0c4c754855 100755 --- a/test/testdata/generate.sh +++ b/test/testdata/generate.sh @@ -31,6 +31,17 @@ function scaffold_test_project { rm -rf $testdata_dir/$project/* pushd $testdata_dir/$project + # Define the sed command based on the OS + if [[ "$OSTYPE" == "darwin"* ]]; then + # macOS sed syntax + sed_storage_version="sed -i '' '43i\\ + // +kubebuilder:storageversion\\ + // +kubebuilder:conversion:hub'" + else + # Linux sed syntax + sed_storage_version="sed -i '43i // +kubebuilder:storageversion\n// +kubebuilder:conversion:hub'" + fi + header_text "Generating project ${project} with flags: ${init_flags}" go mod init sigs.k8s.io/kubebuilder/testdata/$project # our repo autodetection will traverse up to the kb module if we don't do this header_text "Initializing project ..." @@ -40,9 +51,16 @@ function scaffold_test_project { header_text 'Creating APIs ...' $kb create api --group crew --version v1 --kind Captain --controller=true --resource=true --make=false $kb create api --group crew --version v1 --kind Captain --controller=true --resource=true --make=false --force - $kb create webhook --group crew --version v1 --kind Captain --defaulting --programmatic-validation + $kb create webhook --group crew --version v1 --kind Captain --defaulting --programmatic-validation --make=false + + # Create API to test conversion from v1 to v2 $kb create api --group crew --version v1 --kind FirstMate --controller=true --resource=true --make=false - $kb create webhook --group crew --version v1 --kind FirstMate --conversion + $kb create api --group crew --version v2 --kind FirstMate --controller=false --resource=true --make=false + $kb create webhook --group crew --version v1 --kind FirstMate --conversion --make=false + # TODO: Remove it when we have the hub and spoke scaffolded by Kubebuilder + # Apply the sed command based on project type + eval "$sed_storage_version api/v1/firstmate_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 @@ -59,14 +77,13 @@ function scaffold_test_project { header_text 'Creating APIs ...' $kb create api --group crew --version v1 --kind Captain --controller=true --resource=true --make=false - $kb create webhook --group crew --version v1 --kind Captain --defaulting --programmatic-validation + $kb create webhook --group crew --version v1 --kind Captain --defaulting --programmatic-validation --make=false $kb create api --group ship --version v1beta1 --kind Frigate --controller=true --resource=true --make=false - $kb create webhook --group ship --version v1beta1 --kind Frigate --conversion $kb create api --group ship --version v1 --kind Destroyer --controller=true --resource=true --namespaced=false --make=false - $kb create webhook --group ship --version v1 --kind Destroyer --defaulting + $kb create webhook --group ship --version v1 --kind Destroyer --defaulting --make=false $kb create api --group ship --version v2alpha1 --kind Cruiser --controller=true --resource=true --namespaced=false --make=false - $kb create webhook --group ship --version v2alpha1 --kind Cruiser --programmatic-validation + $kb create webhook --group ship --version v2alpha1 --kind Cruiser --programmatic-validation --make=false $kb create api --group sea-creatures --version v1beta1 --kind Kraken --controller=true --resource=true --make=false $kb create api --group sea-creatures --version v1beta2 --kind Leviathan --controller=true --resource=true --make=false @@ -80,7 +97,7 @@ function scaffold_test_project { # Webhook for External types $kb create webhook --group "cert-manager" --version v1 --kind Issuer --defaulting --external-api-path=github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1 --external-api-domain=io # Webhook for Core type - $kb create webhook --group core --version v1 --kind Pod --programmatic-validation + $kb create webhook --group core --version v1 --kind Pod --programmatic-validation --make=false fi if [[ $project =~ multigroup ]] || [[ $project =~ with-plugins ]] ; then @@ -88,7 +105,22 @@ function scaffold_test_project { header_text 'Creating APIs with deploy-image plugin ...' $kb create api --group example.com --version v1alpha1 --kind Memcached --image=memcached:1.6.26-alpine3.19 --image-container-command="memcached,--memory-limit=64,-o,modern,-v" --image-container-port="11211" --run-as-user="1001" --plugins="deploy-image/v1-alpha" --make=false $kb create api --group example.com --version v1alpha1 --kind Busybox --image=busybox:1.36.1 --plugins="deploy-image/v1-alpha" --make=false - $kb create webhook --group example.com --version v1alpha1 --kind Memcached --programmatic-validation + # Create only validation webhook for Memcached + $kb create webhook --group example.com --version v1alpha1 --kind Memcached --programmatic-validation --make=false + # Create API to check webhook --conversion from v1 to v2 + $kb create api --group example.com --version v1 --kind Wordpress --controller=true --resource=true --make=false + $kb create api --group example.com --version v2 --kind Wordpress --controller=false --resource=true --make=false + $kb create webhook --group example.com --version v1 --kind Wordpress --conversion --make=false + + # TODO: Remove it when we have the hub and spoke scaffolded by Kubebuilder + # Apply the sed command based on project type + if [[ $project =~ multigroup ]]; then + eval "$sed_storage_version api/example.com/v1/wordpress_types.go" + fi + if [[ $project =~ with-plugins ]]; then + eval "$sed_storage_version api/v1/wordpress_types.go" + fi + header_text 'Editing project with Grafana plugin ...' $kb edit --plugins=grafana.kubebuilder.io/v1-alpha fi diff --git a/testdata/project-v4-multigroup/PROJECT b/testdata/project-v4-multigroup/PROJECT index 9a93ab257f1..54359febb7b 100644 --- a/testdata/project-v4-multigroup/PROJECT +++ b/testdata/project-v4-multigroup/PROJECT @@ -50,9 +50,6 @@ resources: kind: Frigate path: sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/api/ship/v1beta1 version: v1beta1 - webhooks: - conversion: true - webhookVersion: v1 - api: crdVersion: v1 controller: true @@ -171,4 +168,24 @@ resources: kind: Busybox path: sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/api/example.com/v1alpha1 version: v1alpha1 +- api: + crdVersion: v1 + namespaced: true + controller: true + domain: testproject.org + group: example.com + kind: Wordpress + path: sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/api/example.com/v1 + version: v1 + webhooks: + conversion: true + webhookVersion: v1 +- api: + crdVersion: v1 + namespaced: true + domain: testproject.org + group: example.com + kind: Wordpress + path: sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/api/example.com/v2 + version: v2 version: "3" diff --git a/testdata/project-v4-multigroup/api/example.com/v1/groupversion_info.go b/testdata/project-v4-multigroup/api/example.com/v1/groupversion_info.go new file mode 100644 index 00000000000..f6ea9c38602 --- /dev/null +++ b/testdata/project-v4-multigroup/api/example.com/v1/groupversion_info.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 contains API Schema definitions for the example.com v1 API group. +// +kubebuilder:object:generate=true +// +groupName=example.com.testproject.org +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects. + GroupVersion = schema.GroupVersion{Group: "example.com.testproject.org", Version: "v1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme. + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/testdata/project-v4-multigroup/api/example.com/v1/wordpress_types.go b/testdata/project-v4-multigroup/api/example.com/v1/wordpress_types.go new file mode 100644 index 00000000000..0304ca8b4cf --- /dev/null +++ b/testdata/project-v4-multigroup/api/example.com/v1/wordpress_types.go @@ -0,0 +1,65 @@ +/* +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. + +// WordpressSpec defines the desired state of Wordpress. +type WordpressSpec 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 Wordpress. Edit wordpress_types.go to remove/update + Foo string `json:"foo,omitempty"` +} + +// WordpressStatus defines the observed state of Wordpress. +type WordpressStatus 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 +// Wordpress is the Schema for the wordpresses API. +type Wordpress struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec WordpressSpec `json:"spec,omitempty"` + Status WordpressStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// WordpressList contains a list of Wordpress. +type WordpressList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Wordpress `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Wordpress{}, &WordpressList{}) +} diff --git a/testdata/project-v4-multigroup/api/example.com/v1/zz_generated.deepcopy.go b/testdata/project-v4-multigroup/api/example.com/v1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..8ef996e16d1 --- /dev/null +++ b/testdata/project-v4-multigroup/api/example.com/v1/zz_generated.deepcopy.go @@ -0,0 +1,114 @@ +//go:build !ignore_autogenerated + +/* +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Wordpress) DeepCopyInto(out *Wordpress) { + *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 Wordpress. +func (in *Wordpress) DeepCopy() *Wordpress { + if in == nil { + return nil + } + out := new(Wordpress) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Wordpress) 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 *WordpressList) DeepCopyInto(out *WordpressList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Wordpress, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WordpressList. +func (in *WordpressList) DeepCopy() *WordpressList { + if in == nil { + return nil + } + out := new(WordpressList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *WordpressList) 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 *WordpressSpec) DeepCopyInto(out *WordpressSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WordpressSpec. +func (in *WordpressSpec) DeepCopy() *WordpressSpec { + if in == nil { + return nil + } + out := new(WordpressSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WordpressStatus) DeepCopyInto(out *WordpressStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WordpressStatus. +func (in *WordpressStatus) DeepCopy() *WordpressStatus { + if in == nil { + return nil + } + out := new(WordpressStatus) + in.DeepCopyInto(out) + return out +} diff --git a/testdata/project-v4-multigroup/api/example.com/v2/groupversion_info.go b/testdata/project-v4-multigroup/api/example.com/v2/groupversion_info.go new file mode 100644 index 00000000000..fbb9302bda5 --- /dev/null +++ b/testdata/project-v4-multigroup/api/example.com/v2/groupversion_info.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 v2 contains API Schema definitions for the example.com v2 API group. +// +kubebuilder:object:generate=true +// +groupName=example.com.testproject.org +package v2 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects. + GroupVersion = schema.GroupVersion{Group: "example.com.testproject.org", Version: "v2"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme. + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/testdata/project-v4-multigroup/api/example.com/v2/wordpress_types.go b/testdata/project-v4-multigroup/api/example.com/v2/wordpress_types.go new file mode 100644 index 00000000000..5a1d1ba6a68 --- /dev/null +++ b/testdata/project-v4-multigroup/api/example.com/v2/wordpress_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. + +// WordpressSpec defines the desired state of Wordpress. +type WordpressSpec 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 Wordpress. Edit wordpress_types.go to remove/update + Foo string `json:"foo,omitempty"` +} + +// WordpressStatus defines the observed state of Wordpress. +type WordpressStatus 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 + +// Wordpress is the Schema for the wordpresses API. +type Wordpress struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec WordpressSpec `json:"spec,omitempty"` + Status WordpressStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// WordpressList contains a list of Wordpress. +type WordpressList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Wordpress `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Wordpress{}, &WordpressList{}) +} diff --git a/testdata/project-v4-multigroup/api/example.com/v2/zz_generated.deepcopy.go b/testdata/project-v4-multigroup/api/example.com/v2/zz_generated.deepcopy.go new file mode 100644 index 00000000000..069e5cfd811 --- /dev/null +++ b/testdata/project-v4-multigroup/api/example.com/v2/zz_generated.deepcopy.go @@ -0,0 +1,114 @@ +//go:build !ignore_autogenerated + +/* +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v2 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Wordpress) DeepCopyInto(out *Wordpress) { + *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 Wordpress. +func (in *Wordpress) DeepCopy() *Wordpress { + if in == nil { + return nil + } + out := new(Wordpress) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Wordpress) 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 *WordpressList) DeepCopyInto(out *WordpressList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Wordpress, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WordpressList. +func (in *WordpressList) DeepCopy() *WordpressList { + if in == nil { + return nil + } + out := new(WordpressList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *WordpressList) 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 *WordpressSpec) DeepCopyInto(out *WordpressSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WordpressSpec. +func (in *WordpressSpec) DeepCopy() *WordpressSpec { + if in == nil { + return nil + } + out := new(WordpressSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WordpressStatus) DeepCopyInto(out *WordpressStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WordpressStatus. +func (in *WordpressStatus) DeepCopy() *WordpressStatus { + if in == nil { + return nil + } + out := new(WordpressStatus) + in.DeepCopyInto(out) + return out +} diff --git a/testdata/project-v4-multigroup/cmd/main.go b/testdata/project-v4-multigroup/cmd/main.go index 0fe9c4afead..9444e6e0db6 100644 --- a/testdata/project-v4-multigroup/cmd/main.go +++ b/testdata/project-v4-multigroup/cmd/main.go @@ -38,7 +38,9 @@ import ( certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" crewv1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/api/crew/v1" + examplecomv1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/api/example.com/v1" examplecomv1alpha1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/api/example.com/v1alpha1" + examplecomv2 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/api/example.com/v2" fizv1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/api/fiz/v1" foopolicyv1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/api/foo.policy/v1" foov1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/api/foo/v1" @@ -59,9 +61,9 @@ import ( webhookcertmanagerv1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/internal/webhook/cert-manager/v1" webhookcorev1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/internal/webhook/core/v1" webhookcrewv1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/internal/webhook/crew/v1" + webhookexamplecomv1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/internal/webhook/example.com/v1" webhookexamplecomv1alpha1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/internal/webhook/example.com/v1alpha1" webhookshipv1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/internal/webhook/ship/v1" - webhookshipv1beta1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/internal/webhook/ship/v1beta1" webhookshipv2alpha1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/internal/webhook/ship/v2alpha1" // +kubebuilder:scaffold:imports ) @@ -85,6 +87,8 @@ func init() { utilruntime.Must(fizv1.AddToScheme(scheme)) utilruntime.Must(certmanagerv1.AddToScheme(scheme)) utilruntime.Must(examplecomv1alpha1.AddToScheme(scheme)) + utilruntime.Must(examplecomv1.AddToScheme(scheme)) + utilruntime.Must(examplecomv2.AddToScheme(scheme)) // +kubebuilder:scaffold:scheme } @@ -199,13 +203,6 @@ func main() { setupLog.Error(err, "unable to create controller", "controller", "Frigate") os.Exit(1) } - // nolint:goconst - if os.Getenv("ENABLE_WEBHOOKS") != "false" { - if err = webhookshipv1beta1.SetupFrigateWebhookWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create webhook", "webhook", "Frigate") - os.Exit(1) - } - } if err = (&shipcontroller.DestroyerReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), @@ -320,6 +317,20 @@ func main() { os.Exit(1) } } + if err = (&examplecomcontroller.WordpressReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "Wordpress") + os.Exit(1) + } + // nolint:goconst + if os.Getenv("ENABLE_WEBHOOKS") != "false" { + if err = webhookexamplecomv1.SetupWordpressWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "Wordpress") + os.Exit(1) + } + } // +kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { diff --git a/testdata/project-v4-multigroup/config/crd/bases/example.com.testproject.org_wordpresses.yaml b/testdata/project-v4-multigroup/config/crd/bases/example.com.testproject.org_wordpresses.yaml new file mode 100644 index 00000000000..0e059f9cc26 --- /dev/null +++ b/testdata/project-v4-multigroup/config/crd/bases/example.com.testproject.org_wordpresses.yaml @@ -0,0 +1,92 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.4 + name: wordpresses.example.com.testproject.org +spec: + group: example.com.testproject.org + names: + kind: Wordpress + listKind: WordpressList + plural: wordpresses + singular: wordpress + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: Wordpress is the Schema for the wordpresses 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: WordpressSpec defines the desired state of Wordpress. + properties: + foo: + description: Foo is an example field of Wordpress. Edit wordpress_types.go + to remove/update + type: string + type: object + status: + description: WordpressStatus defines the observed state of Wordpress. + type: object + type: object + served: true + storage: true + subresources: + status: {} + - name: v2 + schema: + openAPIV3Schema: + description: Wordpress is the Schema for the wordpresses 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: WordpressSpec defines the desired state of Wordpress. + properties: + foo: + description: Foo is an example field of Wordpress. Edit wordpress_types.go + to remove/update + type: string + type: object + status: + description: WordpressStatus defines the observed state of Wordpress. + type: object + type: object + served: true + storage: false + subresources: + status: {} diff --git a/testdata/project-v4-multigroup/config/crd/kustomization.yaml b/testdata/project-v4-multigroup/config/crd/kustomization.yaml index 6b362727dd7..193cb75cbfb 100644 --- a/testdata/project-v4-multigroup/config/crd/kustomization.yaml +++ b/testdata/project-v4-multigroup/config/crd/kustomization.yaml @@ -13,16 +13,17 @@ resources: - bases/fiz.testproject.org_bars.yaml - bases/example.com.testproject.org_memcacheds.yaml - bases/example.com.testproject.org_busyboxes.yaml +- bases/example.com.testproject.org_wordpresses.yaml # +kubebuilder:scaffold:crdkustomizeresource patches: # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. # patches here are for enabling the conversion webhook for each CRD - path: patches/webhook_in_crew_captains.yaml -- path: patches/webhook_in_ship_frigates.yaml - path: patches/webhook_in_ship_destroyers.yaml - path: patches/webhook_in_ship_cruisers.yaml - path: patches/webhook_in_example.com_memcacheds.yaml +- path: patches/webhook_in_example.com_wordpresses.yaml # +kubebuilder:scaffold:crdkustomizewebhookpatch # [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix. @@ -38,6 +39,7 @@ patches: #- path: patches/cainjection_in_fiz_bars.yaml #- path: patches/cainjection_in_example.com_memcacheds.yaml #- path: patches/cainjection_in_example.com_busyboxes.yaml +#- path: patches/cainjection_in_example.com_wordpresses.yaml # +kubebuilder:scaffold:crdkustomizecainjectionpatch # [WEBHOOK] To enable webhook, uncomment the following section diff --git a/testdata/project-v4-multigroup/config/crd/patches/cainjection_in_ship_frigates.yaml b/testdata/project-v4-multigroup/config/crd/patches/cainjection_in_example.com_wordpresses.yaml similarity index 83% rename from testdata/project-v4-multigroup/config/crd/patches/cainjection_in_ship_frigates.yaml rename to testdata/project-v4-multigroup/config/crd/patches/cainjection_in_example.com_wordpresses.yaml index d4acb9d24c1..94469071ccf 100644 --- a/testdata/project-v4-multigroup/config/crd/patches/cainjection_in_ship_frigates.yaml +++ b/testdata/project-v4-multigroup/config/crd/patches/cainjection_in_example.com_wordpresses.yaml @@ -4,4 +4,4 @@ kind: CustomResourceDefinition metadata: annotations: cert-manager.io/inject-ca-from: CERTIFICATE_NAMESPACE/CERTIFICATE_NAME - name: frigates.ship.testproject.org + name: wordpresses.example.com.testproject.org diff --git a/testdata/project-v4-multigroup/config/crd/patches/webhook_in_ship_frigates.yaml b/testdata/project-v4-multigroup/config/crd/patches/webhook_in_example.com_wordpresses.yaml similarity index 88% rename from testdata/project-v4-multigroup/config/crd/patches/webhook_in_ship_frigates.yaml rename to testdata/project-v4-multigroup/config/crd/patches/webhook_in_example.com_wordpresses.yaml index cdc5078ae71..e335002e320 100644 --- a/testdata/project-v4-multigroup/config/crd/patches/webhook_in_ship_frigates.yaml +++ b/testdata/project-v4-multigroup/config/crd/patches/webhook_in_example.com_wordpresses.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: - name: frigates.ship.testproject.org + name: wordpresses.example.com.testproject.org spec: conversion: strategy: Webhook diff --git a/testdata/project-v4-multigroup/config/rbac/example.com_wordpress_editor_role.yaml b/testdata/project-v4-multigroup/config/rbac/example.com_wordpress_editor_role.yaml new file mode 100644 index 00000000000..952b9f79f16 --- /dev/null +++ b/testdata/project-v4-multigroup/config/rbac/example.com_wordpress_editor_role.yaml @@ -0,0 +1,27 @@ +# permissions for end users to edit wordpresses. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: project-v4-multigroup + app.kubernetes.io/managed-by: kustomize + name: example.com-wordpress-editor-role +rules: +- apiGroups: + - example.com.testproject.org + resources: + - wordpresses + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - example.com.testproject.org + resources: + - wordpresses/status + verbs: + - get diff --git a/testdata/project-v4-multigroup/config/rbac/example.com_wordpress_viewer_role.yaml b/testdata/project-v4-multigroup/config/rbac/example.com_wordpress_viewer_role.yaml new file mode 100644 index 00000000000..bfc87af1aff --- /dev/null +++ b/testdata/project-v4-multigroup/config/rbac/example.com_wordpress_viewer_role.yaml @@ -0,0 +1,23 @@ +# permissions for end users to view wordpresses. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: project-v4-multigroup + app.kubernetes.io/managed-by: kustomize + name: example.com-wordpress-viewer-role +rules: +- apiGroups: + - example.com.testproject.org + resources: + - wordpresses + verbs: + - get + - list + - watch +- apiGroups: + - example.com.testproject.org + resources: + - wordpresses/status + verbs: + - get diff --git a/testdata/project-v4-multigroup/config/rbac/kustomization.yaml b/testdata/project-v4-multigroup/config/rbac/kustomization.yaml index bbf5c747bb5..bea2c901ef8 100644 --- a/testdata/project-v4-multigroup/config/rbac/kustomization.yaml +++ b/testdata/project-v4-multigroup/config/rbac/kustomization.yaml @@ -22,6 +22,8 @@ resources: # default, aiding admins in cluster management. Those roles are # not used by the Project itself. You can comment the following lines # if you do not want those helpers be installed with your Project. +- example.com_wordpress_editor_role.yaml +- example.com_wordpress_viewer_role.yaml - example.com_busybox_editor_role.yaml - example.com_busybox_viewer_role.yaml - example.com_memcached_editor_role.yaml diff --git a/testdata/project-v4-multigroup/config/rbac/role.yaml b/testdata/project-v4-multigroup/config/rbac/role.yaml index f8e24f77f46..a5c1f7ef0bd 100644 --- a/testdata/project-v4-multigroup/config/rbac/role.yaml +++ b/testdata/project-v4-multigroup/config/rbac/role.yaml @@ -102,6 +102,7 @@ rules: resources: - busyboxes - memcacheds + - wordpresses verbs: - create - delete @@ -115,6 +116,7 @@ rules: resources: - busyboxes/finalizers - memcacheds/finalizers + - wordpresses/finalizers verbs: - update - apiGroups: @@ -122,6 +124,7 @@ rules: resources: - busyboxes/status - memcacheds/status + - wordpresses/status verbs: - get - patch diff --git a/testdata/project-v4-multigroup/config/samples/example.com_v1_wordpress.yaml b/testdata/project-v4-multigroup/config/samples/example.com_v1_wordpress.yaml new file mode 100644 index 00000000000..33c5dc34ccd --- /dev/null +++ b/testdata/project-v4-multigroup/config/samples/example.com_v1_wordpress.yaml @@ -0,0 +1,9 @@ +apiVersion: example.com.testproject.org/v1 +kind: Wordpress +metadata: + labels: + app.kubernetes.io/name: project-v4-multigroup + app.kubernetes.io/managed-by: kustomize + name: wordpress-sample +spec: + # TODO(user): Add fields here diff --git a/testdata/project-v4-multigroup/config/samples/example.com_v2_wordpress.yaml b/testdata/project-v4-multigroup/config/samples/example.com_v2_wordpress.yaml new file mode 100644 index 00000000000..7b97dc151fc --- /dev/null +++ b/testdata/project-v4-multigroup/config/samples/example.com_v2_wordpress.yaml @@ -0,0 +1,9 @@ +apiVersion: example.com.testproject.org/v2 +kind: Wordpress +metadata: + labels: + app.kubernetes.io/name: project-v4-multigroup + app.kubernetes.io/managed-by: kustomize + name: wordpress-sample +spec: + # TODO(user): Add fields here diff --git a/testdata/project-v4-multigroup/config/samples/kustomization.yaml b/testdata/project-v4-multigroup/config/samples/kustomization.yaml index cffe4bc820a..703c10a4a61 100644 --- a/testdata/project-v4-multigroup/config/samples/kustomization.yaml +++ b/testdata/project-v4-multigroup/config/samples/kustomization.yaml @@ -11,4 +11,6 @@ resources: - fiz_v1_bar.yaml - example.com_v1alpha1_memcached.yaml - example.com_v1alpha1_busybox.yaml +- example.com_v1_wordpress.yaml +- example.com_v2_wordpress.yaml # +kubebuilder:scaffold:manifestskustomizesamples diff --git a/testdata/project-v4-multigroup/dist/install.yaml b/testdata/project-v4-multigroup/dist/install.yaml index b6f36443784..44294bdc330 100644 --- a/testdata/project-v4-multigroup/dist/install.yaml +++ b/testdata/project-v4-multigroup/dist/install.yaml @@ -430,16 +430,6 @@ metadata: controller-gen.kubebuilder.io/version: v0.16.4 name: frigates.ship.testproject.org spec: - conversion: - strategy: Webhook - webhook: - clientConfig: - service: - name: project-v4-multigroup-webhook-service - namespace: project-v4-multigroup-system - path: /convert - conversionReviewVersions: - - v1 group: ship.testproject.org names: kind: Frigate @@ -780,6 +770,108 @@ spec: subresources: status: {} --- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.4 + name: wordpresses.example.com.testproject.org +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + name: project-v4-multigroup-webhook-service + namespace: project-v4-multigroup-system + path: /convert + conversionReviewVersions: + - v1 + group: example.com.testproject.org + names: + kind: Wordpress + listKind: WordpressList + plural: wordpresses + singular: wordpress + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: Wordpress is the Schema for the wordpresses 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: WordpressSpec defines the desired state of Wordpress. + properties: + foo: + description: Foo is an example field of Wordpress. Edit wordpress_types.go + to remove/update + type: string + type: object + status: + description: WordpressStatus defines the observed state of Wordpress. + type: object + type: object + served: true + storage: true + subresources: + status: {} + - name: v2 + schema: + openAPIV3Schema: + description: Wordpress is the Schema for the wordpresses 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: WordpressSpec defines the desired state of Wordpress. + properties: + foo: + description: Foo is an example field of Wordpress. Edit wordpress_types.go + to remove/update + type: string + type: object + status: + description: WordpressStatus defines the observed state of Wordpress. + type: object + type: object + served: true + storage: false + subresources: + status: {} +--- apiVersion: v1 kind: ServiceAccount metadata: @@ -982,6 +1074,56 @@ rules: --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole +metadata: + labels: + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: project-v4-multigroup + name: project-v4-multigroup-example.com-wordpress-editor-role +rules: +- apiGroups: + - example.com.testproject.org + resources: + - wordpresses + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - example.com.testproject.org + resources: + - wordpresses/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-multigroup + name: project-v4-multigroup-example.com-wordpress-viewer-role +rules: +- apiGroups: + - example.com.testproject.org + resources: + - wordpresses + verbs: + - get + - list + - watch +- apiGroups: + - example.com.testproject.org + resources: + - wordpresses/status + verbs: + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole metadata: labels: app.kubernetes.io/managed-by: kustomize @@ -1233,6 +1375,7 @@ rules: resources: - busyboxes - memcacheds + - wordpresses verbs: - create - delete @@ -1246,6 +1389,7 @@ rules: resources: - busyboxes/finalizers - memcacheds/finalizers + - wordpresses/finalizers verbs: - update - apiGroups: @@ -1253,6 +1397,7 @@ rules: resources: - busyboxes/status - memcacheds/status + - wordpresses/status verbs: - get - patch diff --git a/testdata/project-v4-multigroup/internal/controller/example.com/suite_test.go b/testdata/project-v4-multigroup/internal/controller/example.com/suite_test.go index 316975ca415..4aae9289791 100644 --- a/testdata/project-v4-multigroup/internal/controller/example.com/suite_test.go +++ b/testdata/project-v4-multigroup/internal/controller/example.com/suite_test.go @@ -33,6 +33,7 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" + examplecomv1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/api/example.com/v1" examplecomv1alpha1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/api/example.com/v1alpha1" // +kubebuilder:scaffold:imports ) @@ -80,6 +81,9 @@ var _ = BeforeSuite(func() { err = examplecomv1alpha1.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) + err = examplecomv1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + // +kubebuilder:scaffold:scheme k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) diff --git a/testdata/project-v4-multigroup/internal/controller/example.com/wordpress_controller.go b/testdata/project-v4-multigroup/internal/controller/example.com/wordpress_controller.go new file mode 100644 index 00000000000..3a91e610903 --- /dev/null +++ b/testdata/project-v4-multigroup/internal/controller/example.com/wordpress_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 examplecom + +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" + + examplecomv1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/api/example.com/v1" +) + +// WordpressReconciler reconciles a Wordpress object +type WordpressReconciler struct { + client.Client + Scheme *runtime.Scheme +} + +// +kubebuilder:rbac:groups=example.com.testproject.org,resources=wordpresses,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=example.com.testproject.org,resources=wordpresses/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=example.com.testproject.org,resources=wordpresses/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 Wordpress 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 *WordpressReconciler) 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 *WordpressReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&examplecomv1.Wordpress{}). + Named("example.com-wordpress"). + Complete(r) +} diff --git a/testdata/project-v4-multigroup/internal/controller/example.com/wordpress_controller_test.go b/testdata/project-v4-multigroup/internal/controller/example.com/wordpress_controller_test.go new file mode 100644 index 00000000000..16278c90d4a --- /dev/null +++ b/testdata/project-v4-multigroup/internal/controller/example.com/wordpress_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 examplecom + +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" + + examplecomv1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/api/example.com/v1" +) + +var _ = Describe("Wordpress 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 + } + wordpress := &examplecomv1.Wordpress{} + + BeforeEach(func() { + By("creating the custom resource for the Kind Wordpress") + err := k8sClient.Get(ctx, typeNamespacedName, wordpress) + if err != nil && errors.IsNotFound(err) { + resource := &examplecomv1.Wordpress{ + 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 := &examplecomv1.Wordpress{} + err := k8sClient.Get(ctx, typeNamespacedName, resource) + Expect(err).NotTo(HaveOccurred()) + + By("Cleanup the specific resource instance Wordpress") + Expect(k8sClient.Delete(ctx, resource)).To(Succeed()) + }) + It("should successfully reconcile the resource", func() { + By("Reconciling the created resource") + controllerReconciler := &WordpressReconciler{ + 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-multigroup/internal/webhook/example.com/v1/wordpress_webhook.go b/testdata/project-v4-multigroup/internal/webhook/example.com/v1/wordpress_webhook.go new file mode 100644 index 00000000000..9598aacdaef --- /dev/null +++ b/testdata/project-v4-multigroup/internal/webhook/example.com/v1/wordpress_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" + + examplecomv1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/api/example.com/v1" +) + +// nolint:unused +// log is for logging in this package. +var wordpresslog = logf.Log.WithName("wordpress-resource") + +// SetupWordpressWebhookWithManager registers the webhook for Wordpress in the manager. +func SetupWordpressWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr).For(&examplecomv1.Wordpress{}). + Complete() +} + +// TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! diff --git a/testdata/project-v4-multigroup/internal/webhook/example.com/v1/wordpress_webhook_test.go b/testdata/project-v4-multigroup/internal/webhook/example.com/v1/wordpress_webhook_test.go new file mode 100644 index 00000000000..d83c7847bf0 --- /dev/null +++ b/testdata/project-v4-multigroup/internal/webhook/example.com/v1/wordpress_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" + + examplecomv1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/api/example.com/v1" + // TODO (user): Add any additional imports if needed +) + +var _ = Describe("Wordpress Webhook", func() { + var ( + obj *examplecomv1.Wordpress + oldObj *examplecomv1.Wordpress + ) + + BeforeEach(func() { + obj = &examplecomv1.Wordpress{} + oldObj = &examplecomv1.Wordpress{} + 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 Wordpress 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 := &examplecomv1.Wordpress{} + // Expect(obj.ConvertTo(convertedObj)).To(Succeed()) + // Expect(convertedObj).ToNot(BeNil()) + // }) + }) + +}) diff --git a/testdata/project-v4-with-plugins/PROJECT b/testdata/project-v4-with-plugins/PROJECT index 0e0eccc4eb2..d71a9425376 100644 --- a/testdata/project-v4-with-plugins/PROJECT +++ b/testdata/project-v4-with-plugins/PROJECT @@ -48,4 +48,24 @@ resources: kind: Busybox path: sigs.k8s.io/kubebuilder/testdata/project-v4-with-plugins/api/v1alpha1 version: v1alpha1 +- api: + crdVersion: v1 + namespaced: true + controller: true + domain: testproject.org + group: example.com + kind: Wordpress + path: sigs.k8s.io/kubebuilder/testdata/project-v4-with-plugins/api/v1 + version: v1 + webhooks: + conversion: true + webhookVersion: v1 +- api: + crdVersion: v1 + namespaced: true + domain: testproject.org + group: example.com + kind: Wordpress + path: sigs.k8s.io/kubebuilder/testdata/project-v4-with-plugins/api/v2 + version: v2 version: "3" diff --git a/testdata/project-v4-with-plugins/api/v1/groupversion_info.go b/testdata/project-v4-with-plugins/api/v1/groupversion_info.go new file mode 100644 index 00000000000..f6ea9c38602 --- /dev/null +++ b/testdata/project-v4-with-plugins/api/v1/groupversion_info.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 contains API Schema definitions for the example.com v1 API group. +// +kubebuilder:object:generate=true +// +groupName=example.com.testproject.org +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects. + GroupVersion = schema.GroupVersion{Group: "example.com.testproject.org", Version: "v1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme. + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/testdata/project-v4-with-plugins/api/v1/wordpress_types.go b/testdata/project-v4-with-plugins/api/v1/wordpress_types.go new file mode 100644 index 00000000000..0304ca8b4cf --- /dev/null +++ b/testdata/project-v4-with-plugins/api/v1/wordpress_types.go @@ -0,0 +1,65 @@ +/* +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. + +// WordpressSpec defines the desired state of Wordpress. +type WordpressSpec 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 Wordpress. Edit wordpress_types.go to remove/update + Foo string `json:"foo,omitempty"` +} + +// WordpressStatus defines the observed state of Wordpress. +type WordpressStatus 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 +// Wordpress is the Schema for the wordpresses API. +type Wordpress struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec WordpressSpec `json:"spec,omitempty"` + Status WordpressStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// WordpressList contains a list of Wordpress. +type WordpressList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Wordpress `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Wordpress{}, &WordpressList{}) +} diff --git a/testdata/project-v4-with-plugins/api/v1/zz_generated.deepcopy.go b/testdata/project-v4-with-plugins/api/v1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..8ef996e16d1 --- /dev/null +++ b/testdata/project-v4-with-plugins/api/v1/zz_generated.deepcopy.go @@ -0,0 +1,114 @@ +//go:build !ignore_autogenerated + +/* +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Wordpress) DeepCopyInto(out *Wordpress) { + *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 Wordpress. +func (in *Wordpress) DeepCopy() *Wordpress { + if in == nil { + return nil + } + out := new(Wordpress) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Wordpress) 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 *WordpressList) DeepCopyInto(out *WordpressList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Wordpress, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WordpressList. +func (in *WordpressList) DeepCopy() *WordpressList { + if in == nil { + return nil + } + out := new(WordpressList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *WordpressList) 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 *WordpressSpec) DeepCopyInto(out *WordpressSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WordpressSpec. +func (in *WordpressSpec) DeepCopy() *WordpressSpec { + if in == nil { + return nil + } + out := new(WordpressSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WordpressStatus) DeepCopyInto(out *WordpressStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WordpressStatus. +func (in *WordpressStatus) DeepCopy() *WordpressStatus { + if in == nil { + return nil + } + out := new(WordpressStatus) + in.DeepCopyInto(out) + return out +} diff --git a/testdata/project-v4-with-plugins/api/v2/groupversion_info.go b/testdata/project-v4-with-plugins/api/v2/groupversion_info.go new file mode 100644 index 00000000000..fbb9302bda5 --- /dev/null +++ b/testdata/project-v4-with-plugins/api/v2/groupversion_info.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 v2 contains API Schema definitions for the example.com v2 API group. +// +kubebuilder:object:generate=true +// +groupName=example.com.testproject.org +package v2 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects. + GroupVersion = schema.GroupVersion{Group: "example.com.testproject.org", Version: "v2"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme. + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/testdata/project-v4-with-plugins/api/v2/wordpress_types.go b/testdata/project-v4-with-plugins/api/v2/wordpress_types.go new file mode 100644 index 00000000000..5a1d1ba6a68 --- /dev/null +++ b/testdata/project-v4-with-plugins/api/v2/wordpress_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. + +// WordpressSpec defines the desired state of Wordpress. +type WordpressSpec 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 Wordpress. Edit wordpress_types.go to remove/update + Foo string `json:"foo,omitempty"` +} + +// WordpressStatus defines the observed state of Wordpress. +type WordpressStatus 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 + +// Wordpress is the Schema for the wordpresses API. +type Wordpress struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec WordpressSpec `json:"spec,omitempty"` + Status WordpressStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// WordpressList contains a list of Wordpress. +type WordpressList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Wordpress `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Wordpress{}, &WordpressList{}) +} diff --git a/testdata/project-v4-with-plugins/api/v2/zz_generated.deepcopy.go b/testdata/project-v4-with-plugins/api/v2/zz_generated.deepcopy.go new file mode 100644 index 00000000000..069e5cfd811 --- /dev/null +++ b/testdata/project-v4-with-plugins/api/v2/zz_generated.deepcopy.go @@ -0,0 +1,114 @@ +//go:build !ignore_autogenerated + +/* +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v2 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Wordpress) DeepCopyInto(out *Wordpress) { + *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 Wordpress. +func (in *Wordpress) DeepCopy() *Wordpress { + if in == nil { + return nil + } + out := new(Wordpress) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Wordpress) 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 *WordpressList) DeepCopyInto(out *WordpressList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Wordpress, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WordpressList. +func (in *WordpressList) DeepCopy() *WordpressList { + if in == nil { + return nil + } + out := new(WordpressList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *WordpressList) 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 *WordpressSpec) DeepCopyInto(out *WordpressSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WordpressSpec. +func (in *WordpressSpec) DeepCopy() *WordpressSpec { + if in == nil { + return nil + } + out := new(WordpressSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WordpressStatus) DeepCopyInto(out *WordpressStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WordpressStatus. +func (in *WordpressStatus) DeepCopy() *WordpressStatus { + if in == nil { + return nil + } + out := new(WordpressStatus) + in.DeepCopyInto(out) + return out +} diff --git a/testdata/project-v4-with-plugins/cmd/main.go b/testdata/project-v4-with-plugins/cmd/main.go index cf093e59d6c..11f1914fb79 100644 --- a/testdata/project-v4-with-plugins/cmd/main.go +++ b/testdata/project-v4-with-plugins/cmd/main.go @@ -35,8 +35,11 @@ import ( metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" "sigs.k8s.io/controller-runtime/pkg/webhook" + examplecomv1 "sigs.k8s.io/kubebuilder/testdata/project-v4-with-plugins/api/v1" examplecomv1alpha1 "sigs.k8s.io/kubebuilder/testdata/project-v4-with-plugins/api/v1alpha1" + examplecomv2 "sigs.k8s.io/kubebuilder/testdata/project-v4-with-plugins/api/v2" "sigs.k8s.io/kubebuilder/testdata/project-v4-with-plugins/internal/controller" + webhookexamplecomv1 "sigs.k8s.io/kubebuilder/testdata/project-v4-with-plugins/internal/webhook/v1" webhookexamplecomv1alpha1 "sigs.k8s.io/kubebuilder/testdata/project-v4-with-plugins/internal/webhook/v1alpha1" // +kubebuilder:scaffold:imports ) @@ -50,6 +53,8 @@ func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) utilruntime.Must(examplecomv1alpha1.AddToScheme(scheme)) + utilruntime.Must(examplecomv1.AddToScheme(scheme)) + utilruntime.Must(examplecomv2.AddToScheme(scheme)) // +kubebuilder:scaffold:scheme } @@ -166,6 +171,20 @@ func main() { os.Exit(1) } } + if err = (&controller.WordpressReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "Wordpress") + os.Exit(1) + } + // nolint:goconst + if os.Getenv("ENABLE_WEBHOOKS") != "false" { + if err = webhookexamplecomv1.SetupWordpressWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "Wordpress") + os.Exit(1) + } + } // +kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { diff --git a/testdata/project-v4-with-plugins/config/crd/bases/example.com.testproject.org_wordpresses.yaml b/testdata/project-v4-with-plugins/config/crd/bases/example.com.testproject.org_wordpresses.yaml new file mode 100644 index 00000000000..0e059f9cc26 --- /dev/null +++ b/testdata/project-v4-with-plugins/config/crd/bases/example.com.testproject.org_wordpresses.yaml @@ -0,0 +1,92 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.4 + name: wordpresses.example.com.testproject.org +spec: + group: example.com.testproject.org + names: + kind: Wordpress + listKind: WordpressList + plural: wordpresses + singular: wordpress + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: Wordpress is the Schema for the wordpresses 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: WordpressSpec defines the desired state of Wordpress. + properties: + foo: + description: Foo is an example field of Wordpress. Edit wordpress_types.go + to remove/update + type: string + type: object + status: + description: WordpressStatus defines the observed state of Wordpress. + type: object + type: object + served: true + storage: true + subresources: + status: {} + - name: v2 + schema: + openAPIV3Schema: + description: Wordpress is the Schema for the wordpresses 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: WordpressSpec defines the desired state of Wordpress. + properties: + foo: + description: Foo is an example field of Wordpress. Edit wordpress_types.go + to remove/update + type: string + type: object + status: + description: WordpressStatus defines the observed state of Wordpress. + type: object + type: object + served: true + storage: false + subresources: + status: {} diff --git a/testdata/project-v4-with-plugins/config/crd/kustomization.yaml b/testdata/project-v4-with-plugins/config/crd/kustomization.yaml index 7b2aba4eb3c..d00fe0769fc 100644 --- a/testdata/project-v4-with-plugins/config/crd/kustomization.yaml +++ b/testdata/project-v4-with-plugins/config/crd/kustomization.yaml @@ -4,18 +4,21 @@ resources: - bases/example.com.testproject.org_memcacheds.yaml - bases/example.com.testproject.org_busyboxes.yaml +- bases/example.com.testproject.org_wordpresses.yaml # +kubebuilder:scaffold:crdkustomizeresource patches: # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. # patches here are for enabling the conversion webhook for each CRD - path: patches/webhook_in_memcacheds.yaml +- 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_memcacheds.yaml #- path: patches/cainjection_in_busyboxes.yaml +#- path: patches/cainjection_in_wordpresses.yaml # +kubebuilder:scaffold:crdkustomizecainjectionpatch # [WEBHOOK] To enable webhook, uncomment the following section 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 new file mode 100644 index 00000000000..94469071ccf --- /dev/null +++ b/testdata/project-v4-with-plugins/config/crd/patches/cainjection_in_wordpresses.yaml @@ -0,0 +1,7 @@ +# 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/crd/patches/webhook_in_wordpresses.yaml b/testdata/project-v4-with-plugins/config/crd/patches/webhook_in_wordpresses.yaml new file mode 100644 index 00000000000..e335002e320 --- /dev/null +++ b/testdata/project-v4-with-plugins/config/crd/patches/webhook_in_wordpresses.yaml @@ -0,0 +1,16 @@ +# The following patch enables a conversion webhook for the CRD +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: wordpresses.example.com.testproject.org +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + namespace: system + name: webhook-service + path: /convert + conversionReviewVersions: + - v1 diff --git a/testdata/project-v4-with-plugins/config/rbac/kustomization.yaml b/testdata/project-v4-with-plugins/config/rbac/kustomization.yaml index 60653a8cf59..db14c45b3f7 100644 --- a/testdata/project-v4-with-plugins/config/rbac/kustomization.yaml +++ b/testdata/project-v4-with-plugins/config/rbac/kustomization.yaml @@ -22,6 +22,8 @@ resources: # default, aiding admins in cluster management. Those roles are # not used by the Project itself. You can comment the following lines # if you do not want those helpers be installed with your Project. +- wordpress_editor_role.yaml +- wordpress_viewer_role.yaml - busybox_editor_role.yaml - busybox_viewer_role.yaml - memcached_editor_role.yaml diff --git a/testdata/project-v4-with-plugins/config/rbac/role.yaml b/testdata/project-v4-with-plugins/config/rbac/role.yaml index a2db0d25cca..18dc265ac24 100644 --- a/testdata/project-v4-with-plugins/config/rbac/role.yaml +++ b/testdata/project-v4-with-plugins/config/rbac/role.yaml @@ -36,6 +36,7 @@ rules: resources: - busyboxes - memcacheds + - wordpresses verbs: - create - delete @@ -49,6 +50,7 @@ rules: resources: - busyboxes/finalizers - memcacheds/finalizers + - wordpresses/finalizers verbs: - update - apiGroups: @@ -56,6 +58,7 @@ rules: resources: - busyboxes/status - memcacheds/status + - wordpresses/status verbs: - get - patch diff --git a/testdata/project-v4-with-plugins/config/rbac/wordpress_editor_role.yaml b/testdata/project-v4-with-plugins/config/rbac/wordpress_editor_role.yaml new file mode 100644 index 00000000000..8054f6a57d8 --- /dev/null +++ b/testdata/project-v4-with-plugins/config/rbac/wordpress_editor_role.yaml @@ -0,0 +1,27 @@ +# permissions for end users to edit wordpresses. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: project-v4-with-plugins + app.kubernetes.io/managed-by: kustomize + name: wordpress-editor-role +rules: +- apiGroups: + - example.com.testproject.org + resources: + - wordpresses + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - example.com.testproject.org + resources: + - wordpresses/status + verbs: + - get diff --git a/testdata/project-v4-with-plugins/config/rbac/wordpress_viewer_role.yaml b/testdata/project-v4-with-plugins/config/rbac/wordpress_viewer_role.yaml new file mode 100644 index 00000000000..deca0bd8593 --- /dev/null +++ b/testdata/project-v4-with-plugins/config/rbac/wordpress_viewer_role.yaml @@ -0,0 +1,23 @@ +# permissions for end users to view wordpresses. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: project-v4-with-plugins + app.kubernetes.io/managed-by: kustomize + name: wordpress-viewer-role +rules: +- apiGroups: + - example.com.testproject.org + resources: + - wordpresses + verbs: + - get + - list + - watch +- apiGroups: + - example.com.testproject.org + resources: + - wordpresses/status + verbs: + - get diff --git a/testdata/project-v4-with-plugins/config/samples/example.com_v1_wordpress.yaml b/testdata/project-v4-with-plugins/config/samples/example.com_v1_wordpress.yaml new file mode 100644 index 00000000000..88c91cd29b1 --- /dev/null +++ b/testdata/project-v4-with-plugins/config/samples/example.com_v1_wordpress.yaml @@ -0,0 +1,9 @@ +apiVersion: example.com.testproject.org/v1 +kind: Wordpress +metadata: + labels: + app.kubernetes.io/name: project-v4-with-plugins + app.kubernetes.io/managed-by: kustomize + name: wordpress-sample +spec: + # TODO(user): Add fields here diff --git a/testdata/project-v4-with-plugins/config/samples/example.com_v2_wordpress.yaml b/testdata/project-v4-with-plugins/config/samples/example.com_v2_wordpress.yaml new file mode 100644 index 00000000000..24bdf117e64 --- /dev/null +++ b/testdata/project-v4-with-plugins/config/samples/example.com_v2_wordpress.yaml @@ -0,0 +1,9 @@ +apiVersion: example.com.testproject.org/v2 +kind: Wordpress +metadata: + labels: + app.kubernetes.io/name: project-v4-with-plugins + app.kubernetes.io/managed-by: kustomize + name: wordpress-sample +spec: + # TODO(user): Add fields here diff --git a/testdata/project-v4-with-plugins/config/samples/kustomization.yaml b/testdata/project-v4-with-plugins/config/samples/kustomization.yaml index 44b0f44adcb..86922c235b3 100644 --- a/testdata/project-v4-with-plugins/config/samples/kustomization.yaml +++ b/testdata/project-v4-with-plugins/config/samples/kustomization.yaml @@ -2,4 +2,6 @@ resources: - example.com_v1alpha1_memcached.yaml - example.com_v1alpha1_busybox.yaml +- example.com_v1_wordpress.yaml +- example.com_v2_wordpress.yaml # +kubebuilder:scaffold:manifestskustomizesamples diff --git a/testdata/project-v4-with-plugins/dist/install.yaml b/testdata/project-v4-with-plugins/dist/install.yaml index 66788aef372..875bfef3a06 100644 --- a/testdata/project-v4-with-plugins/dist/install.yaml +++ b/testdata/project-v4-with-plugins/dist/install.yaml @@ -254,6 +254,108 @@ spec: subresources: status: {} --- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.4 + name: wordpresses.example.com.testproject.org +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + name: project-v4-with-plugins-webhook-service + namespace: project-v4-with-plugins-system + path: /convert + conversionReviewVersions: + - v1 + group: example.com.testproject.org + names: + kind: Wordpress + listKind: WordpressList + plural: wordpresses + singular: wordpress + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: Wordpress is the Schema for the wordpresses 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: WordpressSpec defines the desired state of Wordpress. + properties: + foo: + description: Foo is an example field of Wordpress. Edit wordpress_types.go + to remove/update + type: string + type: object + status: + description: WordpressStatus defines the observed state of Wordpress. + type: object + type: object + served: true + storage: true + subresources: + status: {} + - name: v2 + schema: + openAPIV3Schema: + description: Wordpress is the Schema for the wordpresses 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: WordpressSpec defines the desired state of Wordpress. + properties: + foo: + description: Foo is an example field of Wordpress. Edit wordpress_types.go + to remove/update + type: string + type: object + status: + description: WordpressStatus defines the observed state of Wordpress. + type: object + type: object + served: true + storage: false + subresources: + status: {} +--- apiVersion: v1 kind: ServiceAccount metadata: @@ -391,6 +493,7 @@ rules: resources: - busyboxes - memcacheds + - wordpresses verbs: - create - delete @@ -404,6 +507,7 @@ rules: resources: - busyboxes/finalizers - memcacheds/finalizers + - wordpresses/finalizers verbs: - update - apiGroups: @@ -411,6 +515,7 @@ rules: resources: - busyboxes/status - memcacheds/status + - wordpresses/status verbs: - get - patch @@ -495,6 +600,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-with-plugins + name: project-v4-with-plugins-wordpress-editor-role +rules: +- apiGroups: + - example.com.testproject.org + resources: + - wordpresses + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - example.com.testproject.org + resources: + - wordpresses/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-with-plugins + name: project-v4-with-plugins-wordpress-viewer-role +rules: +- apiGroups: + - example.com.testproject.org + resources: + - wordpresses + verbs: + - get + - list + - watch +- apiGroups: + - example.com.testproject.org + resources: + - wordpresses/status + verbs: + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: diff --git a/testdata/project-v4-with-plugins/internal/controller/suite_test.go b/testdata/project-v4-with-plugins/internal/controller/suite_test.go index 5259421161e..0114fe3b039 100644 --- a/testdata/project-v4-with-plugins/internal/controller/suite_test.go +++ b/testdata/project-v4-with-plugins/internal/controller/suite_test.go @@ -33,6 +33,7 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" + examplecomv1 "sigs.k8s.io/kubebuilder/testdata/project-v4-with-plugins/api/v1" examplecomv1alpha1 "sigs.k8s.io/kubebuilder/testdata/project-v4-with-plugins/api/v1alpha1" // +kubebuilder:scaffold:imports ) @@ -80,6 +81,9 @@ var _ = BeforeSuite(func() { err = examplecomv1alpha1.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) + err = examplecomv1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + // +kubebuilder:scaffold:scheme k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) diff --git a/testdata/project-v4-with-plugins/internal/controller/wordpress_controller.go b/testdata/project-v4-with-plugins/internal/controller/wordpress_controller.go new file mode 100644 index 00000000000..814224c6a11 --- /dev/null +++ b/testdata/project-v4-with-plugins/internal/controller/wordpress_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" + + examplecomv1 "sigs.k8s.io/kubebuilder/testdata/project-v4-with-plugins/api/v1" +) + +// WordpressReconciler reconciles a Wordpress object +type WordpressReconciler struct { + client.Client + Scheme *runtime.Scheme +} + +// +kubebuilder:rbac:groups=example.com.testproject.org,resources=wordpresses,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=example.com.testproject.org,resources=wordpresses/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=example.com.testproject.org,resources=wordpresses/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 Wordpress 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 *WordpressReconciler) 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 *WordpressReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&examplecomv1.Wordpress{}). + Named("wordpress"). + Complete(r) +} diff --git a/testdata/project-v4-with-plugins/internal/controller/wordpress_controller_test.go b/testdata/project-v4-with-plugins/internal/controller/wordpress_controller_test.go new file mode 100644 index 00000000000..d25dcb12a20 --- /dev/null +++ b/testdata/project-v4-with-plugins/internal/controller/wordpress_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" + + examplecomv1 "sigs.k8s.io/kubebuilder/testdata/project-v4-with-plugins/api/v1" +) + +var _ = Describe("Wordpress 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 + } + wordpress := &examplecomv1.Wordpress{} + + BeforeEach(func() { + By("creating the custom resource for the Kind Wordpress") + err := k8sClient.Get(ctx, typeNamespacedName, wordpress) + if err != nil && errors.IsNotFound(err) { + resource := &examplecomv1.Wordpress{ + 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 := &examplecomv1.Wordpress{} + err := k8sClient.Get(ctx, typeNamespacedName, resource) + Expect(err).NotTo(HaveOccurred()) + + By("Cleanup the specific resource instance Wordpress") + Expect(k8sClient.Delete(ctx, resource)).To(Succeed()) + }) + It("should successfully reconcile the resource", func() { + By("Reconciling the created resource") + controllerReconciler := &WordpressReconciler{ + 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-multigroup/internal/webhook/ship/v1beta1/frigate_webhook.go b/testdata/project-v4-with-plugins/internal/webhook/v1/wordpress_webhook.go similarity index 68% rename from testdata/project-v4-multigroup/internal/webhook/ship/v1beta1/frigate_webhook.go rename to testdata/project-v4-with-plugins/internal/webhook/v1/wordpress_webhook.go index 90b5342fa05..5361361dc48 100644 --- a/testdata/project-v4-multigroup/internal/webhook/ship/v1beta1/frigate_webhook.go +++ b/testdata/project-v4-with-plugins/internal/webhook/v1/wordpress_webhook.go @@ -14,22 +14,22 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1beta1 +package v1 import ( ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" - shipv1beta1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/api/ship/v1beta1" + examplecomv1 "sigs.k8s.io/kubebuilder/testdata/project-v4-with-plugins/api/v1" ) // nolint:unused // log is for logging in this package. -var frigatelog = logf.Log.WithName("frigate-resource") +var wordpresslog = logf.Log.WithName("wordpress-resource") -// SetupFrigateWebhookWithManager registers the webhook for Frigate in the manager. -func SetupFrigateWebhookWithManager(mgr ctrl.Manager) error { - return ctrl.NewWebhookManagedBy(mgr).For(&shipv1beta1.Frigate{}). +// SetupWordpressWebhookWithManager registers the webhook for Wordpress in the manager. +func SetupWordpressWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr).For(&examplecomv1.Wordpress{}). Complete() } diff --git a/testdata/project-v4-multigroup/internal/webhook/ship/v1beta1/frigate_webhook_test.go b/testdata/project-v4-with-plugins/internal/webhook/v1/wordpress_webhook_test.go similarity index 76% rename from testdata/project-v4-multigroup/internal/webhook/ship/v1beta1/frigate_webhook_test.go rename to testdata/project-v4-with-plugins/internal/webhook/v1/wordpress_webhook_test.go index 1882c0df82c..4d22379e74e 100644 --- a/testdata/project-v4-multigroup/internal/webhook/ship/v1beta1/frigate_webhook_test.go +++ b/testdata/project-v4-with-plugins/internal/webhook/v1/wordpress_webhook_test.go @@ -14,25 +14,25 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1beta1 +package v1 import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - shipv1beta1 "sigs.k8s.io/kubebuilder/testdata/project-v4-multigroup/api/ship/v1beta1" + examplecomv1 "sigs.k8s.io/kubebuilder/testdata/project-v4-with-plugins/api/v1" // TODO (user): Add any additional imports if needed ) -var _ = Describe("Frigate Webhook", func() { +var _ = Describe("Wordpress Webhook", func() { var ( - obj *shipv1beta1.Frigate - oldObj *shipv1beta1.Frigate + obj *examplecomv1.Wordpress + oldObj *examplecomv1.Wordpress ) BeforeEach(func() { - obj = &shipv1beta1.Frigate{} - oldObj = &shipv1beta1.Frigate{} + obj = &examplecomv1.Wordpress{} + oldObj = &examplecomv1.Wordpress{} 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 @@ -42,11 +42,11 @@ var _ = Describe("Frigate Webhook", func() { // TODO (user): Add any teardown logic common to all tests }) - Context("When creating Frigate under Conversion Webhook", func() { + Context("When creating Wordpress 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 := &shipv1beta1.Frigate{} + // convertedObj := &examplecomv1.Wordpress{} // Expect(obj.ConvertTo(convertedObj)).To(Succeed()) // Expect(convertedObj).ToNot(BeNil()) // }) diff --git a/testdata/project-v4/PROJECT b/testdata/project-v4/PROJECT index 1ea7da269fe..de92e3145d7 100644 --- a/testdata/project-v4/PROJECT +++ b/testdata/project-v4/PROJECT @@ -33,6 +33,14 @@ resources: webhooks: conversion: true webhookVersion: v1 +- api: + crdVersion: v1 + namespaced: true + domain: testproject.org + group: crew + kind: FirstMate + 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/firstmate_types.go b/testdata/project-v4/api/v1/firstmate_types.go index 63ce2a69d17..f344fe67bac 100644 --- a/testdata/project-v4/api/v1/firstmate_types.go +++ b/testdata/project-v4/api/v1/firstmate_types.go @@ -40,7 +40,8 @@ type FirstMateStatus struct { // +kubebuilder:object:root=true // +kubebuilder:subresource:status - +// +kubebuilder:storageversion +// +kubebuilder:conversion:hub // FirstMate is the Schema for the firstmates API. type FirstMate struct { metav1.TypeMeta `json:",inline"` diff --git a/testdata/project-v4/api/v2/firstmate_types.go b/testdata/project-v4/api/v2/firstmate_types.go new file mode 100644 index 00000000000..2f6f0ebd84c --- /dev/null +++ b/testdata/project-v4/api/v2/firstmate_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. + +// FirstMateSpec defines the desired state of FirstMate. +type FirstMateSpec 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 FirstMate. Edit firstmate_types.go to remove/update + Foo string `json:"foo,omitempty"` +} + +// FirstMateStatus defines the observed state of FirstMate. +type FirstMateStatus 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 + +// FirstMate is the Schema for the firstmates API. +type FirstMate struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec FirstMateSpec `json:"spec,omitempty"` + Status FirstMateStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// FirstMateList contains a list of FirstMate. +type FirstMateList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []FirstMate `json:"items"` +} + +func init() { + SchemeBuilder.Register(&FirstMate{}, &FirstMateList{}) +} diff --git a/testdata/project-v4/api/v2/groupversion_info.go b/testdata/project-v4/api/v2/groupversion_info.go new file mode 100644 index 00000000000..2751fd346b1 --- /dev/null +++ b/testdata/project-v4/api/v2/groupversion_info.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 v2 contains API Schema definitions for the crew v2 API group. +// +kubebuilder:object:generate=true +// +groupName=crew.testproject.org +package v2 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects. + GroupVersion = schema.GroupVersion{Group: "crew.testproject.org", Version: "v2"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme. + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/testdata/project-v4/api/v2/zz_generated.deepcopy.go b/testdata/project-v4/api/v2/zz_generated.deepcopy.go new file mode 100644 index 00000000000..db8e6aded83 --- /dev/null +++ b/testdata/project-v4/api/v2/zz_generated.deepcopy.go @@ -0,0 +1,114 @@ +//go:build !ignore_autogenerated + +/* +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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v2 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FirstMate) DeepCopyInto(out *FirstMate) { + *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 FirstMate. +func (in *FirstMate) DeepCopy() *FirstMate { + if in == nil { + return nil + } + out := new(FirstMate) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *FirstMate) 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 *FirstMateList) DeepCopyInto(out *FirstMateList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]FirstMate, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FirstMateList. +func (in *FirstMateList) DeepCopy() *FirstMateList { + if in == nil { + return nil + } + out := new(FirstMateList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *FirstMateList) 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 *FirstMateSpec) DeepCopyInto(out *FirstMateSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FirstMateSpec. +func (in *FirstMateSpec) DeepCopy() *FirstMateSpec { + if in == nil { + return nil + } + out := new(FirstMateSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FirstMateStatus) DeepCopyInto(out *FirstMateStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FirstMateStatus. +func (in *FirstMateStatus) DeepCopy() *FirstMateStatus { + if in == nil { + return nil + } + out := new(FirstMateStatus) + in.DeepCopyInto(out) + return out +} diff --git a/testdata/project-v4/cmd/main.go b/testdata/project-v4/cmd/main.go index 6d3a70630b8..e7b186138dd 100644 --- a/testdata/project-v4/cmd/main.go +++ b/testdata/project-v4/cmd/main.go @@ -38,6 +38,7 @@ import ( certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" crewv1 "sigs.k8s.io/kubebuilder/testdata/project-v4/api/v1" + crewv2 "sigs.k8s.io/kubebuilder/testdata/project-v4/api/v2" "sigs.k8s.io/kubebuilder/testdata/project-v4/internal/controller" webhookcertmanagerv1 "sigs.k8s.io/kubebuilder/testdata/project-v4/internal/webhook/v1" webhookcorev1 "sigs.k8s.io/kubebuilder/testdata/project-v4/internal/webhook/v1" @@ -54,6 +55,7 @@ func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) utilruntime.Must(crewv1.AddToScheme(scheme)) + utilruntime.Must(crewv2.AddToScheme(scheme)) utilruntime.Must(certmanagerv1.AddToScheme(scheme)) // +kubebuilder:scaffold:scheme } diff --git a/testdata/project-v4/config/crd/bases/crew.testproject.org_firstmates.yaml b/testdata/project-v4/config/crd/bases/crew.testproject.org_firstmates.yaml index 550eb68d8e6..b597e31a390 100644 --- a/testdata/project-v4/config/crd/bases/crew.testproject.org_firstmates.yaml +++ b/testdata/project-v4/config/crd/bases/crew.testproject.org_firstmates.yaml @@ -52,3 +52,41 @@ spec: storage: true subresources: status: {} + - name: v2 + schema: + openAPIV3Schema: + description: FirstMate is the Schema for the firstmates 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: FirstMateSpec defines the desired state of FirstMate. + properties: + foo: + description: Foo is an example field of FirstMate. Edit firstmate_types.go + to remove/update + type: string + type: object + status: + description: FirstMateStatus defines the observed state of FirstMate. + type: object + type: object + served: true + storage: false + subresources: + status: {} diff --git a/testdata/project-v4/config/samples/crew_v2_firstmate.yaml b/testdata/project-v4/config/samples/crew_v2_firstmate.yaml new file mode 100644 index 00000000000..725f8761f4a --- /dev/null +++ b/testdata/project-v4/config/samples/crew_v2_firstmate.yaml @@ -0,0 +1,9 @@ +apiVersion: crew.testproject.org/v2 +kind: FirstMate +metadata: + labels: + app.kubernetes.io/name: project-v4 + app.kubernetes.io/managed-by: kustomize + name: firstmate-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 787262813fe..ce83fd55d0c 100644 --- a/testdata/project-v4/config/samples/kustomization.yaml +++ b/testdata/project-v4/config/samples/kustomization.yaml @@ -2,5 +2,6 @@ resources: - crew_v1_captain.yaml - crew_v1_firstmate.yaml +- crew_v2_firstmate.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 644e7898cf7..5290b3bd872 100644 --- a/testdata/project-v4/dist/install.yaml +++ b/testdata/project-v4/dist/install.yaml @@ -198,6 +198,44 @@ spec: storage: true subresources: status: {} + - name: v2 + schema: + openAPIV3Schema: + description: FirstMate is the Schema for the firstmates 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: FirstMateSpec defines the desired state of FirstMate. + properties: + foo: + description: Foo is an example field of FirstMate. Edit firstmate_types.go + to remove/update + type: string + type: object + status: + description: FirstMateStatus defines the observed state of FirstMate. + type: object + type: object + served: true + storage: false + subresources: + status: {} --- apiVersion: v1 kind: ServiceAccount