From 6f0d732b4a6cfe0cd83771ff1751f61316e70b37 Mon Sep 17 00:00:00 2001 From: Yongxiu Cui Date: Thu, 7 Dec 2023 13:27:54 -0800 Subject: [PATCH] Fix controller-tools doesn't support single files as input https://github.com/kubernetes-sigs/controller-tools/issues/837 --- pkg/loader/loader.go | 20 +-- pkg/loader/loader_test.go | 120 +++++++------- pkg/webhook/parser_integration_test.go | 135 ++++++++++++++++ .../testdata/valid-single/cronjob_types.go | 71 ++++++++ .../testdata/valid-single/cronjobtwo_types.go | 71 ++++++++ .../testdata/valid-single/manifests_all.yaml | 152 ++++++++++++++++++ .../testdata/valid-single/manifests_one.yaml | 82 ++++++++++ .../testdata/valid-single/manifests_two.yaml | 82 ++++++++++ .../testdata/valid-single/webhook_one.go | 50 ++++++ .../testdata/valid-single/webhook_two.go | 50 ++++++ 10 files changed, 764 insertions(+), 69 deletions(-) create mode 100644 pkg/webhook/testdata/valid-single/cronjob_types.go create mode 100644 pkg/webhook/testdata/valid-single/cronjobtwo_types.go create mode 100644 pkg/webhook/testdata/valid-single/manifests_all.yaml create mode 100644 pkg/webhook/testdata/valid-single/manifests_one.yaml create mode 100644 pkg/webhook/testdata/valid-single/manifests_two.yaml create mode 100644 pkg/webhook/testdata/valid-single/webhook_one.go create mode 100644 pkg/webhook/testdata/valid-single/webhook_two.go diff --git a/pkg/loader/loader.go b/pkg/loader/loader.go index 7762e53e7..aa8f51bca 100644 --- a/pkg/loader/loader.go +++ b/pkg/loader/loader.go @@ -389,12 +389,6 @@ func LoadRootsWithConfig(cfg *packages.Config, roots ...string) ([]*Package, err } }() - // uniquePkgIDs is used to keep track of the discovered packages to be nice - // and try and prevent packages from showing up twice when nested module - // support is enabled. there is not harm that comes from this per se, but - // it makes testing easier when a known number of modules can be asserted - uniquePkgIDs := sets.String{} - // loadPackages returns the Go packages for the provided roots // // if validatePkgFn is nil, a package will be returned in the slice, @@ -412,10 +406,7 @@ func LoadRootsWithConfig(cfg *packages.Config, roots ...string) ([]*Package, err var pkgs []*Package for _, rp := range rawPkgs { p := l.packageFor(rp) - if !uniquePkgIDs.Has(p.ID) { - pkgs = append(pkgs, p) - uniquePkgIDs.Insert(p.ID) - } + pkgs = append(pkgs, p) } return pkgs, nil } @@ -568,13 +559,14 @@ func LoadRootsWithConfig(cfg *packages.Config, roots ...string) ([]*Package, err for _, r := range fspRoots { b, d := filepath.Base(r), filepath.Dir(r) - // we want the base part of the path to be either "..." or ".", except - // Go's filepath utilities clean paths during manipulation, removing the - // ".". thus, if not "...", let's update the path components so that: + // we want the base part of the path to be either "..." or ".", except Go's + // filepath utilities clean paths during manipulation or go file path, + // removing the ".". thus, if not "..." or go file, let's update the path + // components so that: // // d = r // b = "." - if b != "..." { + if b != "..." && filepath.Ext(b) != ".go" { d = r b = "." } diff --git a/pkg/loader/loader_test.go b/pkg/loader/loader_test.go index a1ba6f339..8e20a2013 100644 --- a/pkg/loader/loader_test.go +++ b/pkg/loader/loader_test.go @@ -33,17 +33,16 @@ var _ = Describe("Loader parsing root module", func() { testmodPkg = loaderPkg + "/testmod" ) - var indexOfPackage = func(pkgID string, pkgs []*loader.Package) int { - for i := range pkgs { - if pkgs[i].ID == pkgID { - return i - } - } - return -1 + var assertPkgExists = func(pkgID string, pkgs map[string]struct{}) { + Expect(pkgs).Should(HaveKey(pkgID)) } - var assertPkgExists = func(pkgID string, pkgs []*loader.Package) { - ExpectWithOffset(1, indexOfPackage(pkgID, pkgs)).Should(BeNumerically(">", -1)) + var dedupPkgs = func(pkgs []*loader.Package) map[string]struct{} { + uniquePkgs := make(map[string]struct{}) + for _, p := range pkgs { + uniquePkgs[p.ID] = struct{}{} + } + return uniquePkgs } Context("with named packages/modules", func() { @@ -67,8 +66,9 @@ var _ = Describe("Loader parsing root module", func() { It("should load one package", func() { pkgs, err := loader.LoadRoots("sigs.k8s.io/controller-tools/pkg/loader/testmod/submod1") Expect(err).ToNot(HaveOccurred()) - Expect(pkgs).To(HaveLen(1)) - assertPkgExists(testmodPkg+"/submod1", pkgs) + uniquePkgs := dedupPkgs(pkgs) + Expect(uniquePkgs).To(HaveLen(1)) + assertPkgExists(testmodPkg+"/submod1", uniquePkgs) }) }) @@ -76,13 +76,14 @@ var _ = Describe("Loader parsing root module", func() { It("should load six packages", func() { pkgs, err := loader.LoadRoots("sigs.k8s.io/controller-tools/pkg/loader/testmod/...") Expect(err).ToNot(HaveOccurred()) - Expect(pkgs).To(HaveLen(6)) - assertPkgExists(testmodPkg, pkgs) - assertPkgExists(testmodPkg+"/subdir1", pkgs) - assertPkgExists(testmodPkg+"/subdir1/subdir1", pkgs) - assertPkgExists(testmodPkg+"/subdir1/subdir2", pkgs) - assertPkgExists(testmodPkg+"/submod1", pkgs) - assertPkgExists(testmodPkg+"/submod1/subdir1", pkgs) + uniquePkgs := dedupPkgs(pkgs) + Expect(uniquePkgs).To(HaveLen(6)) + assertPkgExists(testmodPkg, uniquePkgs) + assertPkgExists(testmodPkg+"/subdir1", uniquePkgs) + assertPkgExists(testmodPkg+"/subdir1/subdir1", uniquePkgs) + assertPkgExists(testmodPkg+"/subdir1/subdir2", uniquePkgs) + assertPkgExists(testmodPkg+"/submod1", uniquePkgs) + assertPkgExists(testmodPkg+"/submod1/subdir1", uniquePkgs) }) }) @@ -90,14 +91,15 @@ var _ = Describe("Loader parsing root module", func() { It("should load seven packages", func() { pkgs, err := loader.LoadRoots("sigs.k8s.io/controller-tools/pkg/loader/testmod/...", "./...") Expect(err).ToNot(HaveOccurred()) - Expect(pkgs).To(HaveLen(7)) - assertPkgExists(testmodPkg, pkgs) - assertPkgExists(testmodPkg+"/subdir1", pkgs) - assertPkgExists(testmodPkg+"/subdir1/subdir1", pkgs) - assertPkgExists(testmodPkg+"/subdir1/subdir2", pkgs) - assertPkgExists(testmodPkg+"/subdir1/submod1", pkgs) - assertPkgExists(testmodPkg+"/submod1", pkgs) - assertPkgExists(testmodPkg+"/submod1/subdir1", pkgs) + uniquePkgs := dedupPkgs(pkgs) + Expect(uniquePkgs).To(HaveLen(7)) + assertPkgExists(testmodPkg, uniquePkgs) + assertPkgExists(testmodPkg+"/subdir1", uniquePkgs) + assertPkgExists(testmodPkg+"/subdir1/subdir1", uniquePkgs) + assertPkgExists(testmodPkg+"/subdir1/subdir2", uniquePkgs) + assertPkgExists(testmodPkg+"/subdir1/submod1", uniquePkgs) + assertPkgExists(testmodPkg+"/submod1", uniquePkgs) + assertPkgExists(testmodPkg+"/submod1/subdir1", uniquePkgs) }) }) }) @@ -106,8 +108,9 @@ var _ = Describe("Loader parsing root module", func() { It("should load one package", func() { pkgs, err := loader.LoadRoots("../crd/.") Expect(err).ToNot(HaveOccurred()) - Expect(pkgs).To(HaveLen(1)) - assertPkgExists(pkgPkg+"/crd", pkgs) + uniquePkgs := dedupPkgs(pkgs) + Expect(uniquePkgs).To(HaveLen(1)) + assertPkgExists(pkgPkg+"/crd", uniquePkgs) }) }) @@ -115,8 +118,9 @@ var _ = Describe("Loader parsing root module", func() { It("should load one package", func() { pkgs, err := loader.LoadRoots("./") Expect(err).ToNot(HaveOccurred()) - Expect(pkgs).To(HaveLen(1)) - assertPkgExists(loaderPkg, pkgs) + uniquePkgs := dedupPkgs(pkgs) + Expect(uniquePkgs).To(HaveLen(1)) + assertPkgExists(loaderPkg, uniquePkgs) }) }) @@ -124,8 +128,9 @@ var _ = Describe("Loader parsing root module", func() { It("should load one package", func() { pkgs, err := loader.LoadRoots("../../pkg/loader") Expect(err).ToNot(HaveOccurred()) - Expect(pkgs).To(HaveLen(1)) - assertPkgExists(loaderPkg, pkgs) + uniquePkgs := dedupPkgs(pkgs) + Expect(uniquePkgs).To(HaveLen(1)) + assertPkgExists(loaderPkg, uniquePkgs) }) }) @@ -135,14 +140,15 @@ var _ = Describe("Loader parsing root module", func() { "../../pkg/loader/../loader/testmod/...", "./testmod/./../testmod//.") Expect(err).ToNot(HaveOccurred()) - Expect(pkgs).To(HaveLen(7)) - assertPkgExists(testmodPkg, pkgs) - assertPkgExists(testmodPkg+"/subdir1", pkgs) - assertPkgExists(testmodPkg+"/subdir1/subdir1", pkgs) - assertPkgExists(testmodPkg+"/subdir1/subdir2", pkgs) - assertPkgExists(testmodPkg+"/subdir1/submod1", pkgs) - assertPkgExists(testmodPkg+"/submod1", pkgs) - assertPkgExists(testmodPkg+"/submod1/subdir1", pkgs) + uniquePkgs := dedupPkgs(pkgs) + Expect(uniquePkgs).To(HaveLen(7)) + assertPkgExists(testmodPkg, uniquePkgs) + assertPkgExists(testmodPkg+"/subdir1", uniquePkgs) + assertPkgExists(testmodPkg+"/subdir1/subdir1", uniquePkgs) + assertPkgExists(testmodPkg+"/subdir1/subdir2", uniquePkgs) + assertPkgExists(testmodPkg+"/subdir1/submod1", uniquePkgs) + assertPkgExists(testmodPkg+"/submod1", uniquePkgs) + assertPkgExists(testmodPkg+"/submod1/subdir1", uniquePkgs) }) }) @@ -150,14 +156,15 @@ var _ = Describe("Loader parsing root module", func() { It("should load seven packages", func() { pkgs, err := loader.LoadRoots("./testmod/...") Expect(err).ToNot(HaveOccurred()) - Expect(pkgs).To(HaveLen(7)) - assertPkgExists(testmodPkg, pkgs) - assertPkgExists(testmodPkg+"/subdir1", pkgs) - assertPkgExists(testmodPkg+"/subdir1/subdir1", pkgs) - assertPkgExists(testmodPkg+"/subdir1/subdir2", pkgs) - assertPkgExists(testmodPkg+"/subdir1/submod1", pkgs) - assertPkgExists(testmodPkg+"/submod1", pkgs) - assertPkgExists(testmodPkg+"/submod1/subdir1", pkgs) + uniquePkgs := dedupPkgs(pkgs) + Expect(uniquePkgs).To(HaveLen(7)) + assertPkgExists(testmodPkg, uniquePkgs) + assertPkgExists(testmodPkg+"/subdir1", uniquePkgs) + assertPkgExists(testmodPkg+"/subdir1/subdir1", uniquePkgs) + assertPkgExists(testmodPkg+"/subdir1/subdir2", uniquePkgs) + assertPkgExists(testmodPkg+"/subdir1/submod1", uniquePkgs) + assertPkgExists(testmodPkg+"/submod1", uniquePkgs) + assertPkgExists(testmodPkg+"/submod1/subdir1", uniquePkgs) }) }) @@ -165,8 +172,9 @@ var _ = Describe("Loader parsing root module", func() { It("should load one package", func() { pkgs, err := loader.LoadRoots("./testmod/subdir1/submod1/...") Expect(err).ToNot(HaveOccurred()) - Expect(pkgs).To(HaveLen(1)) - assertPkgExists(testmodPkg+"/subdir1/submod1", pkgs) + uniquePkgs := dedupPkgs(pkgs) + Expect(uniquePkgs).To(HaveLen(1)) + assertPkgExists(testmodPkg+"/subdir1/submod1", uniquePkgs) }) }) @@ -174,9 +182,10 @@ var _ = Describe("Loader parsing root module", func() { It("should load two packages", func() { pkgs, err := loader.LoadRoots("./testmod", "./testmod/submod1") Expect(err).ToNot(HaveOccurred()) - Expect(pkgs).To(HaveLen(2)) - assertPkgExists(testmodPkg, pkgs) - assertPkgExists(testmodPkg+"/submod1", pkgs) + uniquePkgs := dedupPkgs(pkgs) + Expect(uniquePkgs).To(HaveLen(2)) + assertPkgExists(testmodPkg, uniquePkgs) + assertPkgExists(testmodPkg+"/submod1", uniquePkgs) }) }) @@ -184,8 +193,9 @@ var _ = Describe("Loader parsing root module", func() { It("should load one package", func() { pkgs, err := loader.LoadRoots("./testmod/submod1/subdir1/") Expect(err).ToNot(HaveOccurred()) - Expect(pkgs).To(HaveLen(1)) - assertPkgExists(testmodPkg+"/submod1/subdir1", pkgs) + uniquePkgs := dedupPkgs(pkgs) + Expect(uniquePkgs).To(HaveLen(1)) + assertPkgExists(testmodPkg+"/submod1/subdir1", uniquePkgs) }) }) }) diff --git a/pkg/webhook/parser_integration_test.go b/pkg/webhook/parser_integration_test.go index f020cfc2e..743602c87 100644 --- a/pkg/webhook/parser_integration_test.go +++ b/pkg/webhook/parser_integration_test.go @@ -326,6 +326,141 @@ var _ = Describe("Webhook Generation From Parsing to CustomResourceDefinition", err = webhook.Generator{}.Generate(genCtx) Expect(err).To(HaveOccurred()) }) + + It("should properly generate the webhook definition for single file one", func() { + By("switching into testdata to appease go modules") + cwd, err := os.Getwd() + Expect(err).NotTo(HaveOccurred()) + Expect(os.Chdir("./testdata/valid-single")).To(Succeed()) // go modules are directory-sensitive + defer func() { Expect(os.Chdir(cwd)).To(Succeed()) }() + + By("loading the golang file") + pkgs, err := loader.LoadRoots("webhook_one.go") + Expect(err).NotTo(HaveOccurred()) + Expect(pkgs).To(HaveLen(1)) + + By("setting up the parser") + reg := &markers.Registry{} + Expect(reg.Register(webhook.ConfigDefinition)).To(Succeed()) + + By("requesting that the manifest be generated") + outputDir, err := os.MkdirTemp("", "webhook-integration-test") + Expect(err).NotTo(HaveOccurred()) + defer os.RemoveAll(outputDir) + genCtx := &genall.GenerationContext{ + Collector: &markers.Collector{Registry: reg}, + Roots: pkgs, + OutputRule: genall.OutputToDirectory(outputDir), + } + Expect(webhook.Generator{}.Generate(genCtx)).To(Succeed()) + for _, r := range genCtx.Roots { + Expect(r.Errors).To(HaveLen(0)) + } + + By("loading the generated v1 YAML") + actualFile, err := os.ReadFile(path.Join(outputDir, "manifests.yaml")) + Expect(err).NotTo(HaveOccurred()) + actualMutating, actualValidating := unmarshalBothV1(actualFile) + + By("loading the desired v1 YAML") + expectedFile, err := os.ReadFile("manifests_one.yaml") + Expect(err).NotTo(HaveOccurred()) + expectedMutating, expectedValidating := unmarshalBothV1(expectedFile) + + By("comparing the two") + assertSame(actualMutating, expectedMutating) + assertSame(actualValidating, expectedValidating) + }) + + It("should properly generate the webhook definition for single file two", func() { + By("switching into testdata to appease go modules") + cwd, err := os.Getwd() + Expect(err).NotTo(HaveOccurred()) + Expect(os.Chdir("./testdata/valid-single")).To(Succeed()) // go modules are directory-sensitive + defer func() { Expect(os.Chdir(cwd)).To(Succeed()) }() + + By("loading the golang file") + pkgs, err := loader.LoadRoots("webhook_two.go") + Expect(err).NotTo(HaveOccurred()) + Expect(pkgs).To(HaveLen(1)) + + By("setting up the parser") + reg := &markers.Registry{} + Expect(reg.Register(webhook.ConfigDefinition)).To(Succeed()) + + By("requesting that the manifest be generated") + outputDir, err := os.MkdirTemp("", "webhook-integration-test") + Expect(err).NotTo(HaveOccurred()) + defer os.RemoveAll(outputDir) + genCtx := &genall.GenerationContext{ + Collector: &markers.Collector{Registry: reg}, + Roots: pkgs, + OutputRule: genall.OutputToDirectory(outputDir), + } + Expect(webhook.Generator{}.Generate(genCtx)).To(Succeed()) + for _, r := range genCtx.Roots { + Expect(r.Errors).To(HaveLen(0)) + } + + By("loading the generated v1 YAML") + actualFile, err := os.ReadFile(path.Join(outputDir, "manifests.yaml")) + Expect(err).NotTo(HaveOccurred()) + actualMutating, actualValidating := unmarshalBothV1(actualFile) + + By("loading the desired v1 YAML") + expectedFile, err := os.ReadFile("manifests_two.yaml") + Expect(err).NotTo(HaveOccurred()) + expectedMutating, expectedValidating := unmarshalBothV1(expectedFile) + + By("comparing the two") + assertSame(actualMutating, expectedMutating) + assertSame(actualValidating, expectedValidating) + }) + + It("should properly generate the webhook definition for multiple files", func() { + By("switching into testdata to appease go modules") + cwd, err := os.Getwd() + Expect(err).NotTo(HaveOccurred()) + Expect(os.Chdir("./testdata/valid-single")).To(Succeed()) // go modules are directory-sensitive + defer func() { Expect(os.Chdir(cwd)).To(Succeed()) }() + + By("loading the roots") + pkgs, err := loader.LoadRoots(".") + Expect(err).NotTo(HaveOccurred()) + Expect(pkgs).To(HaveLen(1)) + + By("setting up the parser") + reg := &markers.Registry{} + Expect(reg.Register(webhook.ConfigDefinition)).To(Succeed()) + + By("requesting that the manifest be generated") + outputDir, err := os.MkdirTemp("", "webhook-integration-test") + Expect(err).NotTo(HaveOccurred()) + defer os.RemoveAll(outputDir) + genCtx := &genall.GenerationContext{ + Collector: &markers.Collector{Registry: reg}, + Roots: pkgs, + OutputRule: genall.OutputToDirectory(outputDir), + } + Expect(webhook.Generator{}.Generate(genCtx)).To(Succeed()) + for _, r := range genCtx.Roots { + Expect(r.Errors).To(HaveLen(0)) + } + + By("loading the generated v1 YAML") + actualFile, err := os.ReadFile(path.Join(outputDir, "manifests.yaml")) + Expect(err).NotTo(HaveOccurred()) + actualMutating, actualValidating := unmarshalBothV1(actualFile) + + By("loading the desired v1 YAML") + expectedFile, err := os.ReadFile("manifests_all.yaml") + Expect(err).NotTo(HaveOccurred()) + expectedMutating, expectedValidating := unmarshalBothV1(expectedFile) + + By("comparing the two") + assertSame(actualMutating, expectedMutating) + assertSame(actualValidating, expectedValidating) + }) }) func unmarshalBothV1(in []byte) (mutating admissionregv1.MutatingWebhookConfiguration, validating admissionregv1.ValidatingWebhookConfiguration) { diff --git a/pkg/webhook/testdata/valid-single/cronjob_types.go b/pkg/webhook/testdata/valid-single/cronjob_types.go new file mode 100644 index 000000000..4a95bf52a --- /dev/null +++ b/pkg/webhook/testdata/valid-single/cronjob_types.go @@ -0,0 +1,71 @@ +/* + +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. +*/ + +//go:generate ../../../../.run-controller-gen.sh webhook paths=. output:dir=. + +// +groupName=testdata.kubebuilder.io +// +versionName=v1 +package cronjob + +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. + +// CronJobSpec defines the desired state of CronJob +type CronJobSpec struct { + // The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. + Schedule string `json:"schedule"` +} + +// CronJobStatus defines the observed state of CronJob +type CronJobStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file + + // Information when was the last time the job was successfully scheduled. + // +optional + LastScheduleTime *metav1.Time `json:"lastScheduleTime,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:singular=mycronjob + +// CronJob is the Schema for the cronjobs API +type CronJob struct { + /* + */ + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec CronJobSpec `json:"spec,omitempty"` + Status CronJobStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// CronJobList contains a list of CronJob +type CronJobList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []CronJob `json:"items"` +} + +func init() { + SchemeBuilder.Register(&CronJob{}, &CronJobList{}) +} diff --git a/pkg/webhook/testdata/valid-single/cronjobtwo_types.go b/pkg/webhook/testdata/valid-single/cronjobtwo_types.go new file mode 100644 index 000000000..8bb184302 --- /dev/null +++ b/pkg/webhook/testdata/valid-single/cronjobtwo_types.go @@ -0,0 +1,71 @@ +/* + +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. +*/ + +//go:generate ../../../../.run-controller-gen.sh webhook paths=. output:dir=. + +// +groupName=testdata.kubebuilder.io +// +versionName=v1 +package cronjob + +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. + +// CronJobTwoSpec defines the desired state of CronJobTwo +type CronJobTwoSpec struct { + // The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. + Schedule string `json:"schedule"` +} + +// CronJobTwoStatus defines the observed state of CronJobTwo +type CronJobTwoStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file + + // Information when was the last time the job was successfully scheduled. + // +optional + LastScheduleTime *metav1.Time `json:"lastScheduleTime,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:singular=mycronjobtwo + +// CronJobTwo is the Schema for the cronjobtwos API +type CronJobTwo struct { + /* + */ + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec CronJobTwoSpec `json:"spec,omitempty"` + Status CronJobTwoStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// CronJobTwoList contains a list of CronJobTwo +type CronJobTwoList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []CronJobTwo `json:"items"` +} + +func init() { + SchemeBuilder.Register(&CronJobTwo{}, &CronJobTwoList{}) +} diff --git a/pkg/webhook/testdata/valid-single/manifests_all.yaml b/pkg/webhook/testdata/valid-single/manifests_all.yaml new file mode 100644 index 000000000..ad5f17cd4 --- /dev/null +++ b/pkg/webhook/testdata/valid-single/manifests_all.yaml @@ -0,0 +1,152 @@ +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: mutating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-testdata-kubebuilder-io-v1-cronjob + failurePolicy: Fail + matchPolicy: Equivalent + name: default.cronjob.testdata.kubebuilder.io + reinvocationPolicy: IfNeeded + rules: + - apiGroups: + - testdata.kubebuiler.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - cronjobs + sideEffects: None + timeoutSeconds: 10 +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-testdata-kubebuilder-io-v1-cronjobtwo + failurePolicy: Fail + matchPolicy: Equivalent + name: default.cronjobtwo.testdata.kubebuilder.io + reinvocationPolicy: IfNeeded + rules: + - apiGroups: + - testdata.kubebuiler.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - cronjobtwos + sideEffects: None + timeoutSeconds: 10 +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: validating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-testdata-kubebuilder-io-v1-cronjob + failurePolicy: Fail + matchPolicy: Equivalent + name: validation.cronjob.testdata.kubebuilder.io + rules: + - apiGroups: + - testdata.kubebuiler.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - cronjobs + sideEffects: None + timeoutSeconds: 10 +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-testdata-kubebuilder-io-v1-cronjob + failurePolicy: Fail + matchPolicy: Equivalent + name: validation.cronjob.testdata.kubebuilder.io + rules: + - apiGroups: + - testdata.kubebuiler.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - cronjobs + sideEffects: NoneOnDryRun + timeoutSeconds: 10 +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-testdata-kubebuilder-io-v1-cronjobtwo + failurePolicy: Fail + matchPolicy: Equivalent + name: validation.cronjobtwo.testdata.kubebuilder.io + rules: + - apiGroups: + - testdata.kubebuiler.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - cronjobtwos + sideEffects: None + timeoutSeconds: 10 +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-testdata-kubebuilder-io-v1-cronjobtwo + failurePolicy: Fail + matchPolicy: Equivalent + name: validation.cronjobtwo.testdata.kubebuilder.io + rules: + - apiGroups: + - testdata.kubebuiler.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - cronjobtwos + sideEffects: NoneOnDryRun + timeoutSeconds: 10 diff --git a/pkg/webhook/testdata/valid-single/manifests_one.yaml b/pkg/webhook/testdata/valid-single/manifests_one.yaml new file mode 100644 index 000000000..9a2011559 --- /dev/null +++ b/pkg/webhook/testdata/valid-single/manifests_one.yaml @@ -0,0 +1,82 @@ +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: mutating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-testdata-kubebuilder-io-v1-cronjob + failurePolicy: Fail + matchPolicy: Equivalent + name: default.cronjob.testdata.kubebuilder.io + rules: + - apiGroups: + - testdata.kubebuiler.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - cronjobs + sideEffects: None + timeoutSeconds: 10 + reinvocationPolicy: IfNeeded +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: validating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-testdata-kubebuilder-io-v1-cronjob + failurePolicy: Fail + matchPolicy: Equivalent + name: validation.cronjob.testdata.kubebuilder.io + rules: + - apiGroups: + - testdata.kubebuiler.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - cronjobs + sideEffects: None + timeoutSeconds: 10 +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-testdata-kubebuilder-io-v1-cronjob + failurePolicy: Fail + matchPolicy: Equivalent + name: validation.cronjob.testdata.kubebuilder.io + rules: + - apiGroups: + - testdata.kubebuiler.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - cronjobs + sideEffects: NoneOnDryRun + timeoutSeconds: 10 diff --git a/pkg/webhook/testdata/valid-single/manifests_two.yaml b/pkg/webhook/testdata/valid-single/manifests_two.yaml new file mode 100644 index 000000000..697763b74 --- /dev/null +++ b/pkg/webhook/testdata/valid-single/manifests_two.yaml @@ -0,0 +1,82 @@ +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: mutating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-testdata-kubebuilder-io-v1-cronjobtwo + failurePolicy: Fail + matchPolicy: Equivalent + name: default.cronjobtwo.testdata.kubebuilder.io + reinvocationPolicy: IfNeeded + rules: + - apiGroups: + - testdata.kubebuiler.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - cronjobtwos + sideEffects: None + timeoutSeconds: 10 +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: validating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-testdata-kubebuilder-io-v1-cronjobtwo + failurePolicy: Fail + matchPolicy: Equivalent + name: validation.cronjobtwo.testdata.kubebuilder.io + rules: + - apiGroups: + - testdata.kubebuiler.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - cronjobtwos + sideEffects: None + timeoutSeconds: 10 +- admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-testdata-kubebuilder-io-v1-cronjobtwo + failurePolicy: Fail + matchPolicy: Equivalent + name: validation.cronjobtwo.testdata.kubebuilder.io + rules: + - apiGroups: + - testdata.kubebuiler.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - cronjobtwos + sideEffects: NoneOnDryRun + timeoutSeconds: 10 diff --git a/pkg/webhook/testdata/valid-single/webhook_one.go b/pkg/webhook/testdata/valid-single/webhook_one.go new file mode 100644 index 000000000..9e8685278 --- /dev/null +++ b/pkg/webhook/testdata/valid-single/webhook_one.go @@ -0,0 +1,50 @@ +/* + +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 cronjob + +import ( + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" +) + +func (c *CronJob) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(c). + Complete() +} + +// +kubebuilder:webhook:webhookVersions=v1,verbs=create;update,path=/validate-testdata-kubebuilder-io-v1-cronjob,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=testdata.kubebuiler.io,resources=cronjobs,versions=v1,name=validation.cronjob.testdata.kubebuilder.io,sideEffects=None,timeoutSeconds=10,admissionReviewVersions=v1;v1beta1 +// +kubebuilder:webhook:verbs=create;update,path=/validate-testdata-kubebuilder-io-v1-cronjob,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=testdata.kubebuiler.io,resources=cronjobs,versions=v1,name=validation.cronjob.testdata.kubebuilder.io,sideEffects=NoneOnDryRun,timeoutSeconds=10,admissionReviewVersions=v1;v1beta1 +// +kubebuilder:webhook:webhookVersions=v1,verbs=create;update,path=/mutate-testdata-kubebuilder-io-v1-cronjob,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=testdata.kubebuiler.io,resources=cronjobs,versions=v1,name=default.cronjob.testdata.kubebuilder.io,sideEffects=None,timeoutSeconds=10,admissionReviewVersions=v1;v1beta1,reinvocationPolicy=IfNeeded + +var _ webhook.Defaulter = &CronJob{} +var _ webhook.Validator = &CronJob{} + +func (c *CronJob) Default() { +} + +func (c *CronJob) ValidateCreate() error { + return nil +} + +func (c *CronJob) ValidateUpdate(_ runtime.Object) error { + return nil +} + +func (c *CronJob) ValidateDelete() error { + return nil +} diff --git a/pkg/webhook/testdata/valid-single/webhook_two.go b/pkg/webhook/testdata/valid-single/webhook_two.go new file mode 100644 index 000000000..1f38aca9b --- /dev/null +++ b/pkg/webhook/testdata/valid-single/webhook_two.go @@ -0,0 +1,50 @@ +/* + +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 cronjob + +import ( + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" +) + +func (c *CronJobTwo) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(c). + Complete() +} + +// +kubebuilder:webhook:webhookVersions=v1,verbs=create;update,path=/validate-testdata-kubebuilder-io-v1-cronjobtwo,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=testdata.kubebuiler.io,resources=cronjobtwos,versions=v1,name=validation.cronjobtwo.testdata.kubebuilder.io,sideEffects=None,timeoutSeconds=10,admissionReviewVersions=v1;v1beta1 +// +kubebuilder:webhook:verbs=create;update,path=/validate-testdata-kubebuilder-io-v1-cronjobtwo,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=testdata.kubebuiler.io,resources=cronjobtwos,versions=v1,name=validation.cronjobtwo.testdata.kubebuilder.io,sideEffects=NoneOnDryRun,timeoutSeconds=10,admissionReviewVersions=v1;v1beta1 +// +kubebuilder:webhook:webhookVersions=v1,verbs=create;update,path=/mutate-testdata-kubebuilder-io-v1-cronjobtwo,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=testdata.kubebuiler.io,resources=cronjobtwos,versions=v1,name=default.cronjobtwo.testdata.kubebuilder.io,sideEffects=None,timeoutSeconds=10,admissionReviewVersions=v1;v1beta1,reinvocationPolicy=IfNeeded + +var _ webhook.Defaulter = &CronJobTwo{} +var _ webhook.Validator = &CronJobTwo{} + +func (c *CronJobTwo) Default() { +} + +func (c *CronJobTwo) ValidateCreate() error { + return nil +} + +func (c *CronJobTwo) ValidateUpdate(_ runtime.Object) error { + return nil +} + +func (c *CronJobTwo) ValidateDelete() error { + return nil +}