diff --git a/cmd/controller-gen/main.go b/cmd/controller-gen/main.go index 41b899dc7..f880b04ce 100644 --- a/cmd/controller-gen/main.go +++ b/cmd/controller-gen/main.go @@ -24,6 +24,8 @@ import ( "strings" "github.com/spf13/cobra" + + "sigs.k8s.io/controller-tools/pkg/applyconfiguration" "sigs.k8s.io/controller-tools/pkg/crd" "sigs.k8s.io/controller-tools/pkg/deepcopy" "sigs.k8s.io/controller-tools/pkg/genall" @@ -48,11 +50,12 @@ var ( // each turns into a command line option, // and has options for output forms. allGenerators = map[string]genall.Generator{ - "crd": crd.Generator{}, - "rbac": rbac.Generator{}, - "object": deepcopy.Generator{}, - "webhook": webhook.Generator{}, - "schemapatch": schemapatcher.Generator{}, + "crd": crd.Generator{}, + "rbac": rbac.Generator{}, + "object": deepcopy.Generator{}, + "applyconfiguration": applyconfiguration.Generator{}, + "webhook": webhook.Generator{}, + "schemapatch": schemapatcher.Generator{}, } // allOutputRules defines the list of all known output rules, giving @@ -139,13 +142,18 @@ func main() { controller-gen object paths=./apis/v1beta1/some_types.go # Generate OpenAPI v3 schemas for API packages and merge them into existing CRD manifests - controller-gen schemapatch:manifests=./manifests output:dir=./manifests paths=./pkg/apis/... + controller-gen schemapatch:manifests=./manifests output:dir=./manifests paths=./pkg/apis/... # Run all the generators for a given project controller-gen paths=./apis/... # Explain the markers for generating CRDs, and their arguments controller-gen crd -ww + + # Generate applyconfigurations for CRDs for use with Server Side Apply. They will be placed + # into a "applyconfiguration/" subdirectory + + controller-gen applyconfiguration paths=./apis/... `, RunE: func(c *cobra.Command, rawOpts []string) error { // print version if asked for it diff --git a/go.mod b/go.mod index 1c660bd0c..0d9ea779f 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,8 @@ require ( k8s.io/api v0.33.0-beta.0 k8s.io/apiextensions-apiserver v0.33.0-beta.0 k8s.io/apimachinery v0.33.0-beta.0 + k8s.io/code-generator v0.33.0-beta.0 + k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7 k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 sigs.k8s.io/yaml v1.4.0 ) @@ -24,10 +26,15 @@ require ( github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-logr/logr v1.4.2 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.23.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/google/gnostic-models v0.6.9 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/kr/text v0.2.0 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -39,9 +46,11 @@ require ( golang.org/x/sync v0.12.0 // indirect golang.org/x/sys v0.31.0 // indirect golang.org/x/text v0.23.0 // indirect + google.golang.org/protobuf v1.36.5 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect k8s.io/klog/v2 v2.130.1 // indirect + k8s.io/kube-openapi v0.0.0-20250304201544-e5f78fe3ede9 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect diff --git a/go.sum b/go.sum index 3ed093e62..1836a2213 100644 --- a/go.sum +++ b/go.sum @@ -13,6 +13,14 @@ github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= @@ -28,6 +36,8 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= +github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -40,14 +50,21 @@ github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAx github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -173,8 +190,14 @@ k8s.io/apiextensions-apiserver v0.33.0-beta.0 h1:3oqBvfd26IOekt96KEfE8A0wA/k1wDS k8s.io/apiextensions-apiserver v0.33.0-beta.0/go.mod h1:TKTeoFcmGvtiDNV+wj8wJfZhamZNOhvi9yOIE2d1iWs= k8s.io/apimachinery v0.33.0-beta.0 h1:vLDBChfQwyimk6AbuT7OZOIqxSg/44JlXuxqBk85j68= k8s.io/apimachinery v0.33.0-beta.0/go.mod h1:S2OIkExGqJOXYSYcAJwQ9zWcc6BkBUdTJUu4M7z0cvo= +k8s.io/code-generator v0.33.0-beta.0 h1:QYiWYFUT9G7lnF1ucDYr/sZUaG/kptrooX2PJxEL+Go= +k8s.io/code-generator v0.33.0-beta.0/go.mod h1:RBvFpvqtyQygCBjMayNyYqdzy+89LdzqAx0Th+dgmzQ= +k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7 h1:2OX19X59HxDprNCVrWi6jb7LW1PoqTlYqEq5H2oetog= +k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20250304201544-e5f78fe3ede9 h1:t0huyHnz6HsokckRxAF1bY0cqPFwzINKCL7yltEjZQc= +k8s.io/kube-openapi v0.0.0-20250304201544-e5f78fe3ede9/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= diff --git a/pkg/applyconfiguration/applyconfiguration_integration_test.go b/pkg/applyconfiguration/applyconfiguration_integration_test.go new file mode 100644 index 000000000..33d8f8101 --- /dev/null +++ b/pkg/applyconfiguration/applyconfiguration_integration_test.go @@ -0,0 +1,217 @@ +/* +Copyright 2019 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 applyconfiguration + +import ( + "fmt" + "io" + "io/fs" + "os" + "path/filepath" + "strings" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/extensions/table" + . "github.com/onsi/gomega" + "k8s.io/apimachinery/pkg/util/sets" + + "sigs.k8s.io/controller-tools/pkg/crd" + "sigs.k8s.io/controller-tools/pkg/genall" + "sigs.k8s.io/controller-tools/pkg/loader" + "sigs.k8s.io/controller-tools/pkg/markers" +) + +const ( + cronjobDir = "./testdata/cronjob" + applyConfigurationDir = "applyconfiguration" +) + +type outputToMap map[string]*outputFile + +// Open implements genall.OutputRule. +func (m outputToMap) Open(_ *loader.Package, path string) (io.WriteCloser, error) { + if _, ok := m[path]; !ok { + m[path] = &outputFile{} + } + return m[path], nil +} + +type outputFile struct { + contents []byte +} + +func (o *outputFile) Write(p []byte) (int, error) { + o.contents = append(o.contents, p...) + return len(p), nil +} + +func (o *outputFile) Close() error { + return nil +} + +var _ = Describe("ApplyConfiguration generation from API types", func() { + var originalCWD string + + BeforeEach(func() { + var tmpDir string + + By("Setting up a temporary directory", func() { + var err error + tmpDir, err = os.MkdirTemp("", "applyconfiguration-integration-test") + Expect(err).NotTo(HaveOccurred(), "Should be able to create a temporary directory") + + // Copy the testdata directory, but removed the generated files. + Expect(os.CopyFS(tmpDir, os.DirFS(cronjobDir))).To(Succeed(), "Should be able to copy source files") + Expect(os.RemoveAll(filepath.Join(tmpDir, "api/v1", applyConfigurationDir))).To(Succeed(), "Should be able to remove generated file from temp directory") + }) + + By("Switching into testdata to appease go modules", func() { + cwd, err := os.Getwd() + Expect(err).NotTo(HaveOccurred()) + + originalCWD = cwd + + Expect(os.Chdir(tmpDir)).To(Succeed()) // go modules are directory-sensitive + }) + + By(fmt.Sprintf("Completed set up in %s", tmpDir)) + }) + + AfterEach(func() { + // Reset the working directory + Expect(os.Chdir(originalCWD)).To(Succeed()) + }) + + DescribeTable("should be able to verify generated ApplyConfiguration types for the CronJob schema", func(outputPackage string) { + Expect(replaceOutputPkgMarker("./api/v1", outputPackage)).To(Succeed()) + + // The output is used to capture the generated CRD file. + // The output of the applyconfiguration cannot be generated to memory, gengo handles all of the writing to disk directly. + output := make(outputToMap) + + By("Initializing the runtime") + optionsRegistry := &markers.Registry{} + Expect(genall.RegisterOptionsMarkers(optionsRegistry)).To(Succeed()) + Expect(optionsRegistry.Register(markers.Must(markers.MakeDefinition("crd", markers.DescribesPackage, crd.Generator{})))).To(Succeed()) + Expect(optionsRegistry.Register(markers.Must(markers.MakeDefinition("applyconfiguration", markers.DescribesPackage, Generator{})))).To(Succeed()) + + rt, err := genall.FromOptions(optionsRegistry, []string{ + "crd:allowDangerousTypes=true,ignoreUnexportedFields=true", // Run another generator first to make sure they don't interfere; see also: the comment on cronjob_types.go:UntypedBlob + "applyconfiguration", + "paths=./api/v1", + }) + Expect(err).NotTo(HaveOccurred()) + + rt.OutputRules = genall.OutputRules{Default: output} + + originalFS := os.DirFS(filepath.Join(originalCWD, cronjobDir)) + tmpFS := os.DirFS(".") + + By("Running the generator") + hadErrs := rt.Run() + + By("Checking for generation errors") + Expect(hadErrs).To(BeFalse(), "Generator should run without errors") + + filesInOriginal := make(map[string][]byte) + originalFileNames := sets.New[string]() + Expect(fs.WalkDir(originalFS, filepath.Join("api/v1", applyConfigurationDir), func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + if d.IsDir() { + return nil + } + + data, err := os.ReadFile(filepath.Join(originalCWD, cronjobDir, path)) + if err != nil { + return fmt.Errorf("error reading file %s: %w", path, err) + } + + // Record the path without the path prefix for comparison later. + path = strings.TrimPrefix(path, filepath.Join("api/v1", applyConfigurationDir)+"/") + originalFileNames.Insert(path) + filesInOriginal[path] = data + return nil + })).To(Succeed()) + + filesInOutput := make(map[string][]byte) + outputFileNames := sets.New[string]() + Expect(fs.WalkDir(tmpFS, filepath.Join("api/v1", outputPackage), func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + if d.IsDir() { + return nil + } + + data, err := os.ReadFile(path) + if err != nil { + return fmt.Errorf("error reading file %s: %w", path, err) + } + + // Record the path without the path prefix for comparison later. + path = strings.TrimPrefix(path, filepath.Join("api/v1", outputPackage)+"/") + outputFileNames.Insert(path) + filesInOutput[path] = data + return nil + })).To(Succeed()) + + // // Every file should be in both sets, check for files not in both sets. + Expect(outputFileNames.UnsortedList()).To(ConsistOf(originalFileNames.UnsortedList()), "Generated files should match the checked in files") + + for name, content := range filesInOriginal { + // If the output package uses a relative path we need to remove the "../" from the package name. + outputPackageName := strings.ReplaceAll(outputPackage, "../", "") + + // Make sure the package string is correct for the newly generated content. + content = []byte(strings.Replace(string(content), "package applyconfiguration", fmt.Sprintf("package %s", outputPackageName), 1)) + + // Make sure the import paths are correct for the newly generated content. + content = []byte(strings.ReplaceAll(string(content), "testdata/cronjob/api/v1/applyconfiguration", filepath.Join("testdata/cronjob/api/v1", outputPackage))) + + Expect(string(filesInOutput[name])).To(BeComparableTo(string(content)), "Generated files should match the checked in files, diff found in %s", name) + } + }, + Entry("with the default applyconfiguration output package", "applyconfiguration"), + Entry("with the an alternative output package", "other"), + Entry("with a package outside of the current directory", "../../clients"), + ) +}) + +func replaceOutputPkgMarker(dir string, newOutputPackage string) error { + f, err := os.Open(filepath.Join(dir, "groupversion_info.go")) + if err != nil { + return fmt.Errorf("error opening groupversion_info.go: %w", err) + } + defer f.Close() + + data, err := io.ReadAll(f) + if err != nil { + return fmt.Errorf("error reading groupversion_info.go: %w", err) + } + + newData := strings.Replace(string(data), "// +kubebuilder:ac:output:package=\"applyconfiguration\"", fmt.Sprintf("// +kubebuilder:ac:output:package=\"%s\"", newOutputPackage), 1) + + if err := os.WriteFile(filepath.Join(dir, "groupversion_info.go"), []byte(newData), 0644); err != nil { + return fmt.Errorf("error writing groupversion_info.go: %w", err) + } + + return nil +} diff --git a/pkg/applyconfiguration/applyconfiguration_suite_test.go b/pkg/applyconfiguration/applyconfiguration_suite_test.go new file mode 100644 index 000000000..d684590cf --- /dev/null +++ b/pkg/applyconfiguration/applyconfiguration_suite_test.go @@ -0,0 +1,29 @@ +/* +Copyright 2019 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 applyconfiguration + +import ( + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +func TestObjectGeneration(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "ApplyConfiguration Generation Suite") +} diff --git a/pkg/applyconfiguration/doc.go b/pkg/applyconfiguration/doc.go new file mode 100644 index 000000000..de9f9206a --- /dev/null +++ b/pkg/applyconfiguration/doc.go @@ -0,0 +1,18 @@ +/* +Copyright 2019 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 applyconfigurations generates types for constructing declarative apply configurations. +package applyconfiguration diff --git a/pkg/applyconfiguration/gen.go b/pkg/applyconfiguration/gen.go new file mode 100644 index 000000000..73c727ab4 --- /dev/null +++ b/pkg/applyconfiguration/gen.go @@ -0,0 +1,236 @@ +/* +Copyright 2021 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 applyconfiguration + +import ( + "fmt" + "go/ast" + "os" + "path/filepath" + + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/code-generator/cmd/applyconfiguration-gen/args" + "k8s.io/code-generator/cmd/applyconfiguration-gen/generators" + + "k8s.io/gengo/v2" + "k8s.io/gengo/v2/generator" + "k8s.io/gengo/v2/parser" + + kerrors "k8s.io/apimachinery/pkg/util/errors" + crdmarkers "sigs.k8s.io/controller-tools/pkg/crd/markers" + "sigs.k8s.io/controller-tools/pkg/genall" + "sigs.k8s.io/controller-tools/pkg/loader" + "sigs.k8s.io/controller-tools/pkg/markers" +) + +// Based on deepcopy gen but with legacy marker support removed. + +var ( + isCRDMarker = markers.Must(markers.MakeDefinition("kubebuilder:resource", markers.DescribesType, crdmarkers.Resource{})) + enablePkgMarker = markers.Must(markers.MakeDefinition("kubebuilder:ac:generate", markers.DescribesPackage, false)) + outputPkgMarker = markers.Must(markers.MakeDefinition("kubebuilder:ac:output:package", markers.DescribesPackage, "")) + enableTypeMarker = markers.Must(markers.MakeDefinition("kubebuilder:ac:generate", markers.DescribesType, false)) +) + +const defaultOutputPackage = "applyconfiguration" + +// +controllertools:marker:generateHelp + +// Generator generates code containing apply configuration type implementations. +type Generator struct { + // HeaderFile specifies the header text (e.g. license) to prepend to generated files. + HeaderFile string `marker:",optional"` +} + +func (Generator) CheckFilter() loader.NodeFilter { + return func(node ast.Node) bool { + // ignore interfaces + _, isIface := node.(*ast.InterfaceType) + return !isIface + } +} + +func (Generator) RegisterMarkers(into *markers.Registry) error { + if err := markers.RegisterAll(into, + isCRDMarker, enablePkgMarker, enableTypeMarker, outputPkgMarker); err != nil { + return err + } + + into.AddHelp(isCRDMarker, + markers.SimpleHelp("apply", "enables apply configuration generation for this type")) + into.AddHelp( + enableTypeMarker, markers.SimpleHelp("apply", "overrides enabling or disabling applyconfiguration generation for the type, can be used to generate applyconfiguration for a single type when the package generation is disabled, or to disable generation for a single type when the package generation is enabled")) + into.AddHelp( + enablePkgMarker, markers.SimpleHelp("apply", "overrides enabling or disabling applyconfiguration generation for the package")) + into.AddHelp( + outputPkgMarker, markers.SimpleHelp("apply", "overrides the default output package for the applyconfiguration generation, supports relative paths to the API directory. The default value is \"applyconfiguration\"")) + return nil +} + +func enabledOnPackage(col *markers.Collector, pkg *loader.Package) (bool, error) { + pkgMarkers, err := markers.PackageMarkers(col, pkg) + if err != nil { + return false, err + } + pkgMarker := pkgMarkers.Get(enablePkgMarker.Name) + if pkgMarker != nil { + return pkgMarker.(bool), nil + } + return false, nil +} + +func enabledOnType(info *markers.TypeInfo) bool { + if typeMarker := info.Markers.Get(enableTypeMarker.Name); typeMarker != nil { + return typeMarker.(bool) + } + return isCRD(info) +} + +func outputPkg(col *markers.Collector, pkg *loader.Package) string { + pkgMarkers, err := markers.PackageMarkers(col, pkg) + if err != nil { + // Use the default when there's an error. + return defaultOutputPackage + } + + pkgMarker := pkgMarkers.Get(outputPkgMarker.Name) + if pkgMarker != nil { + return pkgMarker.(string) + } + + return defaultOutputPackage +} + +func isCRD(info *markers.TypeInfo) bool { + objectEnabled := info.Markers.Get(isCRDMarker.Name) + return objectEnabled != nil +} + +func (d Generator) Generate(ctx *genall.GenerationContext) error { + headerFilePath := d.HeaderFile + + if headerFilePath == "" { + tmpFile, err := os.CreateTemp("", "applyconfig-header-*.txt") + if err != nil { + return fmt.Errorf("failed to create temporary file: %w", err) + } + if err := tmpFile.Close(); err != nil { + return fmt.Errorf("failed to close temporary file: %w", err) + } + + defer os.Remove(tmpFile.Name()) + + headerFilePath = tmpFile.Name() + } + + objGenCtx := ObjectGenCtx{ + Collector: ctx.Collector, + Checker: ctx.Checker, + HeaderFilePath: headerFilePath, + } + + errs := []error{} + for _, pkg := range ctx.Roots { + if err := objGenCtx.generateForPackage(pkg); err != nil { + errs = append(errs, err) + } + } + + if len(errs) > 0 { + return kerrors.NewAggregate(errs) + } + + return nil +} + +// ObjectGenCtx contains the common info for generating apply configuration implementations. +// It mostly exists so that generating for a package can be easily tested without +// requiring a full set of output rules, etc. +type ObjectGenCtx struct { + Collector *markers.Collector + Checker *loader.TypeChecker + HeaderFilePath string +} + +// generateForPackage generates apply configuration implementations for +// types in the given package, writing the formatted result to given writer. +func (ctx *ObjectGenCtx) generateForPackage(root *loader.Package) error { + enabled, _ := enabledOnPackage(ctx.Collector, root) + if !enabled { + return nil + } + if len(root.GoFiles) == 0 { + return nil + } + + arguments := args.New() + arguments.GoHeaderFile = ctx.HeaderFilePath + + outpkg := outputPkg(ctx.Collector, root) + + arguments.OutputDir = filepath.Join(root.Dir, outpkg) + arguments.OutputPkg = filepath.Join(root.Package.PkgPath, outpkg) + + // The following code is based on gengo/v2.Execute. + // We have lifted it from there so that we can adjust the markers on the types to make sure + // that Kubebuilder generation markers are converted into the genclient marker + // prior to executing the targets. + buildTags := []string{gengo.StdBuildTag} + p := parser.NewWithOptions(parser.Options{BuildTags: buildTags}) + if err := p.LoadPackages(root.PkgPath); err != nil { + return fmt.Errorf("failed making a parser: %w", err) + } + + c, err := generator.NewContext(p, generators.NameSystems(), generators.DefaultNameSystem()) + if err != nil { + return fmt.Errorf("failed making a context: %w", err) + } + + pkg, ok := c.Universe[root.PkgPath] + if !ok { + return fmt.Errorf("package %q not found in universe", root.Name) + } + + // For each type we think should be generated, make sure it has a genclient + // marker else the apply generator will not generate it. + if err := markers.EachType(ctx.Collector, root, func(info *markers.TypeInfo) { + if !enabledOnType(info) { + return + } + + typ, ok := pkg.Types[info.Name] + if !ok { + return + } + + comments := sets.NewString(typ.CommentLines...) + comments.Insert(typ.SecondClosestCommentLines...) + + if !comments.Has("// +genclient") { + typ.CommentLines = append(typ.CommentLines, "+genclient") + } + }); err != nil { + return err + } + + targets := generators.GetTargets(c, arguments) + if err := c.ExecuteTargets(targets); err != nil { + return fmt.Errorf("failed executing generator: %w", err) + } + + return nil +} diff --git a/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/associativetype.go b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/associativetype.go new file mode 100644 index 000000000..b87f5b537 --- /dev/null +++ b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/associativetype.go @@ -0,0 +1,41 @@ +// Code generated by applyconfiguration. DO NOT EDIT. + +package v1 + +// AssociativeTypeApplyConfiguration represents a declarative configuration of the AssociativeType type for use +// with apply. +type AssociativeTypeApplyConfiguration struct { + Name *string `json:"name,omitempty"` + Secondary *int `json:"secondary,omitempty"` + Foo *string `json:"foo,omitempty"` +} + +// AssociativeTypeApplyConfiguration constructs a declarative configuration of the AssociativeType type for use with +// apply. +func AssociativeType() *AssociativeTypeApplyConfiguration { + return &AssociativeTypeApplyConfiguration{} +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *AssociativeTypeApplyConfiguration) WithName(value string) *AssociativeTypeApplyConfiguration { + b.Name = &value + return b +} + +// WithSecondary sets the Secondary field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Secondary field is set to the value of the last call. +func (b *AssociativeTypeApplyConfiguration) WithSecondary(value int) *AssociativeTypeApplyConfiguration { + b.Secondary = &value + return b +} + +// WithFoo sets the Foo field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Foo field is set to the value of the last call. +func (b *AssociativeTypeApplyConfiguration) WithFoo(value string) *AssociativeTypeApplyConfiguration { + b.Foo = &value + return b +} diff --git a/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/containsnestedmap.go b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/containsnestedmap.go new file mode 100644 index 000000000..8ce4471cd --- /dev/null +++ b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/containsnestedmap.go @@ -0,0 +1,29 @@ +// Code generated by applyconfiguration. DO NOT EDIT. + +package v1 + +// ContainsNestedMapApplyConfiguration represents a declarative configuration of the ContainsNestedMap type for use +// with apply. +type ContainsNestedMapApplyConfiguration struct { + InnerMap map[string]string `json:"innerMap,omitempty"` +} + +// ContainsNestedMapApplyConfiguration constructs a declarative configuration of the ContainsNestedMap type for use with +// apply. +func ContainsNestedMap() *ContainsNestedMapApplyConfiguration { + return &ContainsNestedMapApplyConfiguration{} +} + +// WithInnerMap puts the entries into the InnerMap field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the InnerMap field, +// overwriting an existing map entries in InnerMap field with the same key. +func (b *ContainsNestedMapApplyConfiguration) WithInnerMap(entries map[string]string) *ContainsNestedMapApplyConfiguration { + if b.InnerMap == nil && len(entries) > 0 { + b.InnerMap = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.InnerMap[k] = v + } + return b +} diff --git a/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/cronjob.go b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/cronjob.go new file mode 100644 index 000000000..0b66b4b6a --- /dev/null +++ b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/cronjob.go @@ -0,0 +1,209 @@ +// Code generated by applyconfiguration. DO NOT EDIT. + +package v1 + +import ( + apismetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + metav1 "k8s.io/client-go/applyconfigurations/meta/v1" +) + +// CronJobApplyConfiguration represents a declarative configuration of the CronJob type for use +// with apply. +type CronJobApplyConfiguration struct { + metav1.TypeMetaApplyConfiguration `json:",inline"` + *metav1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"` + Spec *CronJobSpecApplyConfiguration `json:"spec,omitempty"` + Status *CronJobStatusApplyConfiguration `json:"status,omitempty"` +} + +// CronJob constructs a declarative configuration of the CronJob type for use with +// apply. +func CronJob(name, namespace string) *CronJobApplyConfiguration { + b := &CronJobApplyConfiguration{} + b.WithName(name) + b.WithNamespace(namespace) + b.WithKind("CronJob") + b.WithAPIVersion("api/v1") + return b +} + +// WithKind sets the Kind field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Kind field is set to the value of the last call. +func (b *CronJobApplyConfiguration) WithKind(value string) *CronJobApplyConfiguration { + b.TypeMetaApplyConfiguration.Kind = &value + return b +} + +// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the APIVersion field is set to the value of the last call. +func (b *CronJobApplyConfiguration) WithAPIVersion(value string) *CronJobApplyConfiguration { + b.TypeMetaApplyConfiguration.APIVersion = &value + return b +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *CronJobApplyConfiguration) WithName(value string) *CronJobApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.Name = &value + return b +} + +// WithGenerateName sets the GenerateName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the GenerateName field is set to the value of the last call. +func (b *CronJobApplyConfiguration) WithGenerateName(value string) *CronJobApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.GenerateName = &value + return b +} + +// WithNamespace sets the Namespace field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Namespace field is set to the value of the last call. +func (b *CronJobApplyConfiguration) WithNamespace(value string) *CronJobApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.Namespace = &value + return b +} + +// WithUID sets the UID field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UID field is set to the value of the last call. +func (b *CronJobApplyConfiguration) WithUID(value types.UID) *CronJobApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.UID = &value + return b +} + +// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ResourceVersion field is set to the value of the last call. +func (b *CronJobApplyConfiguration) WithResourceVersion(value string) *CronJobApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.ResourceVersion = &value + return b +} + +// WithGeneration sets the Generation field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Generation field is set to the value of the last call. +func (b *CronJobApplyConfiguration) WithGeneration(value int64) *CronJobApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.Generation = &value + return b +} + +// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the CreationTimestamp field is set to the value of the last call. +func (b *CronJobApplyConfiguration) WithCreationTimestamp(value apismetav1.Time) *CronJobApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.CreationTimestamp = &value + return b +} + +// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionTimestamp field is set to the value of the last call. +func (b *CronJobApplyConfiguration) WithDeletionTimestamp(value apismetav1.Time) *CronJobApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.DeletionTimestamp = &value + return b +} + +// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call. +func (b *CronJobApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *CronJobApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + b.ObjectMetaApplyConfiguration.DeletionGracePeriodSeconds = &value + return b +} + +// WithLabels puts the entries into the Labels field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Labels field, +// overwriting an existing map entries in Labels field with the same key. +func (b *CronJobApplyConfiguration) WithLabels(entries map[string]string) *CronJobApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.ObjectMetaApplyConfiguration.Labels == nil && len(entries) > 0 { + b.ObjectMetaApplyConfiguration.Labels = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.ObjectMetaApplyConfiguration.Labels[k] = v + } + return b +} + +// WithAnnotations puts the entries into the Annotations field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the Annotations field, +// overwriting an existing map entries in Annotations field with the same key. +func (b *CronJobApplyConfiguration) WithAnnotations(entries map[string]string) *CronJobApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + if b.ObjectMetaApplyConfiguration.Annotations == nil && len(entries) > 0 { + b.ObjectMetaApplyConfiguration.Annotations = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.ObjectMetaApplyConfiguration.Annotations[k] = v + } + return b +} + +// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the OwnerReferences field. +func (b *CronJobApplyConfiguration) WithOwnerReferences(values ...*metav1.OwnerReferenceApplyConfiguration) *CronJobApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + if values[i] == nil { + panic("nil value passed to WithOwnerReferences") + } + b.ObjectMetaApplyConfiguration.OwnerReferences = append(b.ObjectMetaApplyConfiguration.OwnerReferences, *values[i]) + } + return b +} + +// WithFinalizers adds the given value to the Finalizers field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Finalizers field. +func (b *CronJobApplyConfiguration) WithFinalizers(values ...string) *CronJobApplyConfiguration { + b.ensureObjectMetaApplyConfigurationExists() + for i := range values { + b.ObjectMetaApplyConfiguration.Finalizers = append(b.ObjectMetaApplyConfiguration.Finalizers, values[i]) + } + return b +} + +func (b *CronJobApplyConfiguration) ensureObjectMetaApplyConfigurationExists() { + if b.ObjectMetaApplyConfiguration == nil { + b.ObjectMetaApplyConfiguration = &metav1.ObjectMetaApplyConfiguration{} + } +} + +// WithSpec sets the Spec field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Spec field is set to the value of the last call. +func (b *CronJobApplyConfiguration) WithSpec(value *CronJobSpecApplyConfiguration) *CronJobApplyConfiguration { + b.Spec = value + return b +} + +// WithStatus sets the Status field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Status field is set to the value of the last call. +func (b *CronJobApplyConfiguration) WithStatus(value *CronJobStatusApplyConfiguration) *CronJobApplyConfiguration { + b.Status = value + return b +} + +// GetName retrieves the value of the Name field in the declarative configuration. +func (b *CronJobApplyConfiguration) GetName() *string { + b.ensureObjectMetaApplyConfigurationExists() + return b.ObjectMetaApplyConfiguration.Name +} diff --git a/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/cronjobspec.go b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/cronjobspec.go new file mode 100644 index 000000000..2357d9d78 --- /dev/null +++ b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/cronjobspec.go @@ -0,0 +1,851 @@ +// Code generated by applyconfiguration. DO NOT EDIT. + +package v1 + +import ( + v1beta1 "k8s.io/api/batch/v1beta1" + corev1 "k8s.io/api/core/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + intstr "k8s.io/apimachinery/pkg/util/intstr" + apiv1 "sigs.k8s.io/controller-tools/pkg/applyconfiguration/testdata/cronjob/api/v1" +) + +// CronJobSpecApplyConfiguration represents a declarative configuration of the CronJobSpec type for use +// with apply. +type CronJobSpecApplyConfiguration struct { + Schedule *string `json:"schedule,omitempty"` + StartingDeadlineSeconds *int64 `json:"startingDeadlineSeconds,omitempty"` + ConcurrencyPolicy *apiv1.ConcurrencyPolicy `json:"concurrencyPolicy,omitempty"` + Suspend *bool `json:"suspend,omitempty"` + NoReallySuspend *apiv1.TotallyABool `json:"noReallySuspend,omitempty"` + BinaryName []byte `json:"binaryName,omitempty"` + CanBeNull *string `json:"canBeNull,omitempty"` + JobTemplate *v1beta1.JobTemplateSpec `json:"jobTemplate,omitempty"` + SuccessfulJobsHistoryLimit *int32 `json:"successfulJobsHistoryLimit,omitempty"` + FailedJobsHistoryLimit *int32 `json:"failedJobsHistoryLimit,omitempty"` + ByteSliceData map[string][]byte `json:"byteSliceData,omitempty"` + StringSliceData map[string][]string `json:"stringSliceData,omitempty"` + PtrData map[string]*string `json:"ptrData,omitempty"` + TwoOfAKindPart0 *string `json:"twoOfAKindPart0,omitempty"` + TwoOfAKindPart1 *apiv1.LongerString `json:"twoOfAKindPart1,omitempty"` + DefaultedString *string `json:"defaultedString,omitempty"` + DefaultedSlice []string `json:"defaultedSlice,omitempty"` + DefaultedObject []RootObjectApplyConfiguration `json:"defaultedObject,omitempty"` + DefaultedEmptySlice []string `json:"defaultedEmptySlice,omitempty"` + DefaultedEmptyMap map[string]string `json:"defaultedEmptyMap,omitempty"` + DefaultedEmptyObject *EmpiableObjectApplyConfiguration `json:"defaultedEmptyObject,omitempty"` + DoubleDefaultedString *string `json:"doubleDefaultedString,omitempty"` + KubernetesDefaultedString *string `json:"kubernetesDefaultedString,omitempty"` + KubernetesDefaultedSlice []string `json:"kubernetesDefaultedSlice,omitempty"` + KubernetesDefaultedObject []RootObjectApplyConfiguration `json:"kubernetesDefaultedObject,omitempty"` + KubernetesDefaultedEmptySlice []string `json:"kubernetesDefaultedEmptySlice,omitempty"` + KubernetesDefaultedEmptyMap map[string]string `json:"kubernetesDefaultedEmptyMap,omitempty"` + KubernetesDefaultedEmptyObject *EmpiableObjectApplyConfiguration `json:"kubernetesDefaultedEmptyObject,omitempty"` + KubernetesDefaultedRef *string `json:"kubernetesDefaultedRef,omitempty"` + PatternObject *string `json:"patternObject,omitempty"` + EmbeddedResource *runtime.RawExtension `json:"embeddedResource,omitempty"` + UnprunedJSON *NestedObjectApplyConfiguration `json:"unprunedJSON,omitempty"` + UnprunedEmbeddedResource *runtime.RawExtension `json:"unprunedEmbeddedResource,omitempty"` + UnprunedFromType *PreservedApplyConfiguration `json:"unprunedFomType,omitempty"` + UnprunedFromTypeAndField *PreservedApplyConfiguration `json:"unprunedFomTypeAndField,omitempty"` + AssociativeList []AssociativeTypeApplyConfiguration `json:"associativeList,omitempty"` + NestedAssociativeList *apiv1.NestedAssociativeList `json:"nestedassociativeList,omitempty"` + MapOfInfo map[string][]byte `json:"mapOfInfo,omitempty"` + NestedMapOfInfo *apiv1.NestedMapOfInfo `json:"nestedMapOfInfo,omitempty"` + StructWithSeveralFields *NestedObjectApplyConfiguration `json:"structWithSeveralFields,omitempty"` + NestedStructWithSeveralFields *NestedStructWithSeveralFieldsApplyConfiguration `json:"nestedStructWithSeveralFields,omitempty"` + NestedStructWithSeveralFieldsDoubleMarked *NestedStructWithSeveralFieldsApplyConfiguration `json:"nestedStructWithSeveralFieldsDoubleMarked,omitempty"` + JustNestedObject *JustNestedObjectApplyConfiguration `json:"justNestedObject,omitempty"` + ExplicitlyOptionalKubebuilder *string `json:"explicitlyOptionalKubebuilder,omitempty"` + ExplicitlyOptionalKubernetes *string `json:"explicitlyOptionalKubernetes,omitempty"` + ExplicitlyRequiredKubebuilder *string `json:"explicitlyRequiredKubebuilder,omitempty"` + ExplicitlyRequiredKubernetes *string `json:"explicitlyRequiredKubernetes,omitempty"` + MinMaxProperties *MinMaxObjectApplyConfiguration `json:"minMaxProperties,omitempty"` + Schemaless []byte `json:"schemaless,omitempty"` + IntOrStringWithAPattern *intstr.IntOrString `json:"intOrStringWithAPattern,omitempty"` + NestedMap map[string]map[string]string `json:"nestedMap,omitempty"` + NestedNestedMap map[string]map[string]map[string]string `json:"nestedNestedMap,omitempty"` + ContainsNestedMapMap map[string]ContainsNestedMapApplyConfiguration `json:"nestedMapInStruct,omitempty"` + MapOfArraysOfFloats map[string][]bool `json:"mapOfArraysOfFloats,omitempty"` + FloatWithValidations *float64 `json:"floatWithValidations,omitempty"` + Float64WithValidations *float64 `json:"float64WithValidations,omitempty"` + IntWithValidations *int `json:"intWithValidations,omitempty"` + Int32WithValidations *int32 `json:"int32WithValidations,omitempty"` + unexportedStructApplyConfiguration `json:",inline"` + ExportedStructApplyConfiguration `json:",inline"` + StringWithEvenLength *string `json:"stringWithEvenLength,omitempty"` + StringWithEvenLengthAndMessageExpression *string `json:"stringWithEvenLengthAndMessageExpression,omitempty"` + StringWithEvenLengthAndGoodPrefix *apiv1.StringEvenType `json:"stringWithEvenLengthAndGoodPrefix,omitempty"` + ForbiddenInt *int `json:"forbiddenInt,omitempty"` + Array *[3]int `json:"array,omitempty"` + ArrayUsingCompositeLiteral *[3]string `json:"arrayUsingCompositeLiteral,omitempty"` + Hosts []string `json:"hosts,omitempty"` + EnumSlice []int `json:"enumSlice,omitempty"` + HostsAlias *apiv1.Hosts `json:"hostsAlias,omitempty"` + AliasFromPackage *corev1.IPFamilyPolicy `json:"aliasFromPackage,omitempty"` + StringAlias *string `json:"stringAlias,omitempty"` + StringAliasPtr *string `json:"stringAliasPtr,omitempty"` + StringAliasAddedValidation *string `json:"stringAliasAddedValidation,omitempty"` + StringAliasAlreadyValidated *string `json:"stringAliasAlreadyValidated,omitempty"` + StringPair []string `json:"stringPair,omitempty"` + LongerStringArray []apiv1.LongerString `json:"longerStringArray,omitempty"` + IntOrStringArrayWithAPattern []*intstr.IntOrString `json:"intOrStringArrayWithAPattern,omitempty"` + Protocol *corev1.Protocol `json:"protocol,omitempty"` + SelectableFieldString *string `json:"selectableFieldString,omitempty"` + EmbeddedStructApplyConfiguration `json:",inline"` + OnlyAllowSettingOnUpdate *int32 `json:"onlyAllowSettingOnUpdate,omitempty"` +} + +// CronJobSpecApplyConfiguration constructs a declarative configuration of the CronJobSpec type for use with +// apply. +func CronJobSpec() *CronJobSpecApplyConfiguration { + return &CronJobSpecApplyConfiguration{} +} + +// WithSchedule sets the Schedule field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Schedule field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithSchedule(value string) *CronJobSpecApplyConfiguration { + b.Schedule = &value + return b +} + +// WithStartingDeadlineSeconds sets the StartingDeadlineSeconds field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the StartingDeadlineSeconds field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithStartingDeadlineSeconds(value int64) *CronJobSpecApplyConfiguration { + b.StartingDeadlineSeconds = &value + return b +} + +// WithConcurrencyPolicy sets the ConcurrencyPolicy field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ConcurrencyPolicy field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithConcurrencyPolicy(value apiv1.ConcurrencyPolicy) *CronJobSpecApplyConfiguration { + b.ConcurrencyPolicy = &value + return b +} + +// WithSuspend sets the Suspend field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Suspend field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithSuspend(value bool) *CronJobSpecApplyConfiguration { + b.Suspend = &value + return b +} + +// WithNoReallySuspend sets the NoReallySuspend field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the NoReallySuspend field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithNoReallySuspend(value apiv1.TotallyABool) *CronJobSpecApplyConfiguration { + b.NoReallySuspend = &value + return b +} + +// WithBinaryName adds the given value to the BinaryName field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the BinaryName field. +func (b *CronJobSpecApplyConfiguration) WithBinaryName(values ...byte) *CronJobSpecApplyConfiguration { + for i := range values { + b.BinaryName = append(b.BinaryName, values[i]) + } + return b +} + +// WithCanBeNull sets the CanBeNull field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the CanBeNull field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithCanBeNull(value string) *CronJobSpecApplyConfiguration { + b.CanBeNull = &value + return b +} + +// WithJobTemplate sets the JobTemplate field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the JobTemplate field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithJobTemplate(value v1beta1.JobTemplateSpec) *CronJobSpecApplyConfiguration { + b.JobTemplate = &value + return b +} + +// WithSuccessfulJobsHistoryLimit sets the SuccessfulJobsHistoryLimit field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the SuccessfulJobsHistoryLimit field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithSuccessfulJobsHistoryLimit(value int32) *CronJobSpecApplyConfiguration { + b.SuccessfulJobsHistoryLimit = &value + return b +} + +// WithFailedJobsHistoryLimit sets the FailedJobsHistoryLimit field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the FailedJobsHistoryLimit field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithFailedJobsHistoryLimit(value int32) *CronJobSpecApplyConfiguration { + b.FailedJobsHistoryLimit = &value + return b +} + +// WithByteSliceData puts the entries into the ByteSliceData field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the ByteSliceData field, +// overwriting an existing map entries in ByteSliceData field with the same key. +func (b *CronJobSpecApplyConfiguration) WithByteSliceData(entries map[string][]byte) *CronJobSpecApplyConfiguration { + if b.ByteSliceData == nil && len(entries) > 0 { + b.ByteSliceData = make(map[string][]byte, len(entries)) + } + for k, v := range entries { + b.ByteSliceData[k] = v + } + return b +} + +// WithStringSliceData puts the entries into the StringSliceData field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the StringSliceData field, +// overwriting an existing map entries in StringSliceData field with the same key. +func (b *CronJobSpecApplyConfiguration) WithStringSliceData(entries map[string][]string) *CronJobSpecApplyConfiguration { + if b.StringSliceData == nil && len(entries) > 0 { + b.StringSliceData = make(map[string][]string, len(entries)) + } + for k, v := range entries { + b.StringSliceData[k] = v + } + return b +} + +// WithPtrData puts the entries into the PtrData field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the PtrData field, +// overwriting an existing map entries in PtrData field with the same key. +func (b *CronJobSpecApplyConfiguration) WithPtrData(entries map[string]*string) *CronJobSpecApplyConfiguration { + if b.PtrData == nil && len(entries) > 0 { + b.PtrData = make(map[string]*string, len(entries)) + } + for k, v := range entries { + b.PtrData[k] = v + } + return b +} + +// WithTwoOfAKindPart0 sets the TwoOfAKindPart0 field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the TwoOfAKindPart0 field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithTwoOfAKindPart0(value string) *CronJobSpecApplyConfiguration { + b.TwoOfAKindPart0 = &value + return b +} + +// WithTwoOfAKindPart1 sets the TwoOfAKindPart1 field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the TwoOfAKindPart1 field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithTwoOfAKindPart1(value apiv1.LongerString) *CronJobSpecApplyConfiguration { + b.TwoOfAKindPart1 = &value + return b +} + +// WithDefaultedString sets the DefaultedString field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DefaultedString field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithDefaultedString(value string) *CronJobSpecApplyConfiguration { + b.DefaultedString = &value + return b +} + +// WithDefaultedSlice adds the given value to the DefaultedSlice field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the DefaultedSlice field. +func (b *CronJobSpecApplyConfiguration) WithDefaultedSlice(values ...string) *CronJobSpecApplyConfiguration { + for i := range values { + b.DefaultedSlice = append(b.DefaultedSlice, values[i]) + } + return b +} + +// WithDefaultedObject adds the given value to the DefaultedObject field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the DefaultedObject field. +func (b *CronJobSpecApplyConfiguration) WithDefaultedObject(values ...*RootObjectApplyConfiguration) *CronJobSpecApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithDefaultedObject") + } + b.DefaultedObject = append(b.DefaultedObject, *values[i]) + } + return b +} + +// WithDefaultedEmptySlice adds the given value to the DefaultedEmptySlice field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the DefaultedEmptySlice field. +func (b *CronJobSpecApplyConfiguration) WithDefaultedEmptySlice(values ...string) *CronJobSpecApplyConfiguration { + for i := range values { + b.DefaultedEmptySlice = append(b.DefaultedEmptySlice, values[i]) + } + return b +} + +// WithDefaultedEmptyMap puts the entries into the DefaultedEmptyMap field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the DefaultedEmptyMap field, +// overwriting an existing map entries in DefaultedEmptyMap field with the same key. +func (b *CronJobSpecApplyConfiguration) WithDefaultedEmptyMap(entries map[string]string) *CronJobSpecApplyConfiguration { + if b.DefaultedEmptyMap == nil && len(entries) > 0 { + b.DefaultedEmptyMap = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.DefaultedEmptyMap[k] = v + } + return b +} + +// WithDefaultedEmptyObject sets the DefaultedEmptyObject field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DefaultedEmptyObject field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithDefaultedEmptyObject(value *EmpiableObjectApplyConfiguration) *CronJobSpecApplyConfiguration { + b.DefaultedEmptyObject = value + return b +} + +// WithDoubleDefaultedString sets the DoubleDefaultedString field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the DoubleDefaultedString field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithDoubleDefaultedString(value string) *CronJobSpecApplyConfiguration { + b.DoubleDefaultedString = &value + return b +} + +// WithKubernetesDefaultedString sets the KubernetesDefaultedString field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the KubernetesDefaultedString field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithKubernetesDefaultedString(value string) *CronJobSpecApplyConfiguration { + b.KubernetesDefaultedString = &value + return b +} + +// WithKubernetesDefaultedSlice adds the given value to the KubernetesDefaultedSlice field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the KubernetesDefaultedSlice field. +func (b *CronJobSpecApplyConfiguration) WithKubernetesDefaultedSlice(values ...string) *CronJobSpecApplyConfiguration { + for i := range values { + b.KubernetesDefaultedSlice = append(b.KubernetesDefaultedSlice, values[i]) + } + return b +} + +// WithKubernetesDefaultedObject adds the given value to the KubernetesDefaultedObject field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the KubernetesDefaultedObject field. +func (b *CronJobSpecApplyConfiguration) WithKubernetesDefaultedObject(values ...*RootObjectApplyConfiguration) *CronJobSpecApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithKubernetesDefaultedObject") + } + b.KubernetesDefaultedObject = append(b.KubernetesDefaultedObject, *values[i]) + } + return b +} + +// WithKubernetesDefaultedEmptySlice adds the given value to the KubernetesDefaultedEmptySlice field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the KubernetesDefaultedEmptySlice field. +func (b *CronJobSpecApplyConfiguration) WithKubernetesDefaultedEmptySlice(values ...string) *CronJobSpecApplyConfiguration { + for i := range values { + b.KubernetesDefaultedEmptySlice = append(b.KubernetesDefaultedEmptySlice, values[i]) + } + return b +} + +// WithKubernetesDefaultedEmptyMap puts the entries into the KubernetesDefaultedEmptyMap field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the KubernetesDefaultedEmptyMap field, +// overwriting an existing map entries in KubernetesDefaultedEmptyMap field with the same key. +func (b *CronJobSpecApplyConfiguration) WithKubernetesDefaultedEmptyMap(entries map[string]string) *CronJobSpecApplyConfiguration { + if b.KubernetesDefaultedEmptyMap == nil && len(entries) > 0 { + b.KubernetesDefaultedEmptyMap = make(map[string]string, len(entries)) + } + for k, v := range entries { + b.KubernetesDefaultedEmptyMap[k] = v + } + return b +} + +// WithKubernetesDefaultedEmptyObject sets the KubernetesDefaultedEmptyObject field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the KubernetesDefaultedEmptyObject field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithKubernetesDefaultedEmptyObject(value *EmpiableObjectApplyConfiguration) *CronJobSpecApplyConfiguration { + b.KubernetesDefaultedEmptyObject = value + return b +} + +// WithKubernetesDefaultedRef sets the KubernetesDefaultedRef field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the KubernetesDefaultedRef field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithKubernetesDefaultedRef(value string) *CronJobSpecApplyConfiguration { + b.KubernetesDefaultedRef = &value + return b +} + +// WithPatternObject sets the PatternObject field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the PatternObject field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithPatternObject(value string) *CronJobSpecApplyConfiguration { + b.PatternObject = &value + return b +} + +// WithEmbeddedResource sets the EmbeddedResource field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the EmbeddedResource field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithEmbeddedResource(value runtime.RawExtension) *CronJobSpecApplyConfiguration { + b.EmbeddedResource = &value + return b +} + +// WithUnprunedJSON sets the UnprunedJSON field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UnprunedJSON field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithUnprunedJSON(value *NestedObjectApplyConfiguration) *CronJobSpecApplyConfiguration { + b.UnprunedJSON = value + return b +} + +// WithUnprunedEmbeddedResource sets the UnprunedEmbeddedResource field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UnprunedEmbeddedResource field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithUnprunedEmbeddedResource(value runtime.RawExtension) *CronJobSpecApplyConfiguration { + b.UnprunedEmbeddedResource = &value + return b +} + +// WithUnprunedFromType sets the UnprunedFromType field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UnprunedFromType field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithUnprunedFromType(value *PreservedApplyConfiguration) *CronJobSpecApplyConfiguration { + b.UnprunedFromType = value + return b +} + +// WithUnprunedFromTypeAndField sets the UnprunedFromTypeAndField field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the UnprunedFromTypeAndField field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithUnprunedFromTypeAndField(value *PreservedApplyConfiguration) *CronJobSpecApplyConfiguration { + b.UnprunedFromTypeAndField = value + return b +} + +// WithAssociativeList adds the given value to the AssociativeList field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the AssociativeList field. +func (b *CronJobSpecApplyConfiguration) WithAssociativeList(values ...*AssociativeTypeApplyConfiguration) *CronJobSpecApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithAssociativeList") + } + b.AssociativeList = append(b.AssociativeList, *values[i]) + } + return b +} + +// WithNestedAssociativeList sets the NestedAssociativeList field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the NestedAssociativeList field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithNestedAssociativeList(value apiv1.NestedAssociativeList) *CronJobSpecApplyConfiguration { + b.NestedAssociativeList = &value + return b +} + +// WithMapOfInfo puts the entries into the MapOfInfo field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the MapOfInfo field, +// overwriting an existing map entries in MapOfInfo field with the same key. +func (b *CronJobSpecApplyConfiguration) WithMapOfInfo(entries map[string][]byte) *CronJobSpecApplyConfiguration { + if b.MapOfInfo == nil && len(entries) > 0 { + b.MapOfInfo = make(map[string][]byte, len(entries)) + } + for k, v := range entries { + b.MapOfInfo[k] = v + } + return b +} + +// WithNestedMapOfInfo sets the NestedMapOfInfo field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the NestedMapOfInfo field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithNestedMapOfInfo(value apiv1.NestedMapOfInfo) *CronJobSpecApplyConfiguration { + b.NestedMapOfInfo = &value + return b +} + +// WithStructWithSeveralFields sets the StructWithSeveralFields field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the StructWithSeveralFields field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithStructWithSeveralFields(value *NestedObjectApplyConfiguration) *CronJobSpecApplyConfiguration { + b.StructWithSeveralFields = value + return b +} + +// WithNestedStructWithSeveralFields sets the NestedStructWithSeveralFields field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the NestedStructWithSeveralFields field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithNestedStructWithSeveralFields(value *NestedStructWithSeveralFieldsApplyConfiguration) *CronJobSpecApplyConfiguration { + b.NestedStructWithSeveralFields = value + return b +} + +// WithNestedStructWithSeveralFieldsDoubleMarked sets the NestedStructWithSeveralFieldsDoubleMarked field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the NestedStructWithSeveralFieldsDoubleMarked field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithNestedStructWithSeveralFieldsDoubleMarked(value *NestedStructWithSeveralFieldsApplyConfiguration) *CronJobSpecApplyConfiguration { + b.NestedStructWithSeveralFieldsDoubleMarked = value + return b +} + +// WithJustNestedObject sets the JustNestedObject field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the JustNestedObject field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithJustNestedObject(value *JustNestedObjectApplyConfiguration) *CronJobSpecApplyConfiguration { + b.JustNestedObject = value + return b +} + +// WithExplicitlyOptionalKubebuilder sets the ExplicitlyOptionalKubebuilder field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ExplicitlyOptionalKubebuilder field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithExplicitlyOptionalKubebuilder(value string) *CronJobSpecApplyConfiguration { + b.ExplicitlyOptionalKubebuilder = &value + return b +} + +// WithExplicitlyOptionalKubernetes sets the ExplicitlyOptionalKubernetes field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ExplicitlyOptionalKubernetes field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithExplicitlyOptionalKubernetes(value string) *CronJobSpecApplyConfiguration { + b.ExplicitlyOptionalKubernetes = &value + return b +} + +// WithExplicitlyRequiredKubebuilder sets the ExplicitlyRequiredKubebuilder field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ExplicitlyRequiredKubebuilder field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithExplicitlyRequiredKubebuilder(value string) *CronJobSpecApplyConfiguration { + b.ExplicitlyRequiredKubebuilder = &value + return b +} + +// WithExplicitlyRequiredKubernetes sets the ExplicitlyRequiredKubernetes field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ExplicitlyRequiredKubernetes field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithExplicitlyRequiredKubernetes(value string) *CronJobSpecApplyConfiguration { + b.ExplicitlyRequiredKubernetes = &value + return b +} + +// WithMinMaxProperties sets the MinMaxProperties field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the MinMaxProperties field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithMinMaxProperties(value *MinMaxObjectApplyConfiguration) *CronJobSpecApplyConfiguration { + b.MinMaxProperties = value + return b +} + +// WithSchemaless adds the given value to the Schemaless field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Schemaless field. +func (b *CronJobSpecApplyConfiguration) WithSchemaless(values ...byte) *CronJobSpecApplyConfiguration { + for i := range values { + b.Schemaless = append(b.Schemaless, values[i]) + } + return b +} + +// WithIntOrStringWithAPattern sets the IntOrStringWithAPattern field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the IntOrStringWithAPattern field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithIntOrStringWithAPattern(value intstr.IntOrString) *CronJobSpecApplyConfiguration { + b.IntOrStringWithAPattern = &value + return b +} + +// WithNestedMap puts the entries into the NestedMap field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the NestedMap field, +// overwriting an existing map entries in NestedMap field with the same key. +func (b *CronJobSpecApplyConfiguration) WithNestedMap(entries map[string]map[string]string) *CronJobSpecApplyConfiguration { + if b.NestedMap == nil && len(entries) > 0 { + b.NestedMap = make(map[string]map[string]string, len(entries)) + } + for k, v := range entries { + b.NestedMap[k] = v + } + return b +} + +// WithNestedNestedMap puts the entries into the NestedNestedMap field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the NestedNestedMap field, +// overwriting an existing map entries in NestedNestedMap field with the same key. +func (b *CronJobSpecApplyConfiguration) WithNestedNestedMap(entries map[string]map[string]map[string]string) *CronJobSpecApplyConfiguration { + if b.NestedNestedMap == nil && len(entries) > 0 { + b.NestedNestedMap = make(map[string]map[string]map[string]string, len(entries)) + } + for k, v := range entries { + b.NestedNestedMap[k] = v + } + return b +} + +// WithContainsNestedMapMap puts the entries into the ContainsNestedMapMap field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the ContainsNestedMapMap field, +// overwriting an existing map entries in ContainsNestedMapMap field with the same key. +func (b *CronJobSpecApplyConfiguration) WithContainsNestedMapMap(entries map[string]ContainsNestedMapApplyConfiguration) *CronJobSpecApplyConfiguration { + if b.ContainsNestedMapMap == nil && len(entries) > 0 { + b.ContainsNestedMapMap = make(map[string]ContainsNestedMapApplyConfiguration, len(entries)) + } + for k, v := range entries { + b.ContainsNestedMapMap[k] = v + } + return b +} + +// WithMapOfArraysOfFloats puts the entries into the MapOfArraysOfFloats field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, the entries provided by each call will be put on the MapOfArraysOfFloats field, +// overwriting an existing map entries in MapOfArraysOfFloats field with the same key. +func (b *CronJobSpecApplyConfiguration) WithMapOfArraysOfFloats(entries map[string][]bool) *CronJobSpecApplyConfiguration { + if b.MapOfArraysOfFloats == nil && len(entries) > 0 { + b.MapOfArraysOfFloats = make(map[string][]bool, len(entries)) + } + for k, v := range entries { + b.MapOfArraysOfFloats[k] = v + } + return b +} + +// WithFloatWithValidations sets the FloatWithValidations field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the FloatWithValidations field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithFloatWithValidations(value float64) *CronJobSpecApplyConfiguration { + b.FloatWithValidations = &value + return b +} + +// WithFloat64WithValidations sets the Float64WithValidations field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Float64WithValidations field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithFloat64WithValidations(value float64) *CronJobSpecApplyConfiguration { + b.Float64WithValidations = &value + return b +} + +// WithIntWithValidations sets the IntWithValidations field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the IntWithValidations field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithIntWithValidations(value int) *CronJobSpecApplyConfiguration { + b.IntWithValidations = &value + return b +} + +// WithInt32WithValidations sets the Int32WithValidations field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Int32WithValidations field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithInt32WithValidations(value int32) *CronJobSpecApplyConfiguration { + b.Int32WithValidations = &value + return b +} + +// WithFoo sets the Foo field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Foo field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithFoo(value string) *CronJobSpecApplyConfiguration { + b.unexportedStructApplyConfiguration.Foo = &value + return b +} + +// WithBaz sets the Baz field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Baz field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithBaz(value string) *CronJobSpecApplyConfiguration { + b.ExportedStructApplyConfiguration.Baz = &value + return b +} + +// WithStringWithEvenLength sets the StringWithEvenLength field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the StringWithEvenLength field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithStringWithEvenLength(value string) *CronJobSpecApplyConfiguration { + b.StringWithEvenLength = &value + return b +} + +// WithStringWithEvenLengthAndMessageExpression sets the StringWithEvenLengthAndMessageExpression field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the StringWithEvenLengthAndMessageExpression field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithStringWithEvenLengthAndMessageExpression(value string) *CronJobSpecApplyConfiguration { + b.StringWithEvenLengthAndMessageExpression = &value + return b +} + +// WithStringWithEvenLengthAndGoodPrefix sets the StringWithEvenLengthAndGoodPrefix field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the StringWithEvenLengthAndGoodPrefix field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithStringWithEvenLengthAndGoodPrefix(value apiv1.StringEvenType) *CronJobSpecApplyConfiguration { + b.StringWithEvenLengthAndGoodPrefix = &value + return b +} + +// WithForbiddenInt sets the ForbiddenInt field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ForbiddenInt field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithForbiddenInt(value int) *CronJobSpecApplyConfiguration { + b.ForbiddenInt = &value + return b +} + +// WithArray sets the Array field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Array field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithArray(value [3]int) *CronJobSpecApplyConfiguration { + b.Array = &value + return b +} + +// WithArrayUsingCompositeLiteral sets the ArrayUsingCompositeLiteral field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ArrayUsingCompositeLiteral field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithArrayUsingCompositeLiteral(value [3]string) *CronJobSpecApplyConfiguration { + b.ArrayUsingCompositeLiteral = &value + return b +} + +// WithHosts adds the given value to the Hosts field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Hosts field. +func (b *CronJobSpecApplyConfiguration) WithHosts(values ...string) *CronJobSpecApplyConfiguration { + for i := range values { + b.Hosts = append(b.Hosts, values[i]) + } + return b +} + +// WithEnumSlice adds the given value to the EnumSlice field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the EnumSlice field. +func (b *CronJobSpecApplyConfiguration) WithEnumSlice(values ...int) *CronJobSpecApplyConfiguration { + for i := range values { + b.EnumSlice = append(b.EnumSlice, values[i]) + } + return b +} + +// WithHostsAlias sets the HostsAlias field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the HostsAlias field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithHostsAlias(value apiv1.Hosts) *CronJobSpecApplyConfiguration { + b.HostsAlias = &value + return b +} + +// WithAliasFromPackage sets the AliasFromPackage field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the AliasFromPackage field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithAliasFromPackage(value corev1.IPFamilyPolicy) *CronJobSpecApplyConfiguration { + b.AliasFromPackage = &value + return b +} + +// WithStringAlias sets the StringAlias field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the StringAlias field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithStringAlias(value string) *CronJobSpecApplyConfiguration { + b.StringAlias = &value + return b +} + +// WithStringAliasPtr sets the StringAliasPtr field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the StringAliasPtr field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithStringAliasPtr(value string) *CronJobSpecApplyConfiguration { + b.StringAliasPtr = &value + return b +} + +// WithStringAliasAddedValidation sets the StringAliasAddedValidation field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the StringAliasAddedValidation field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithStringAliasAddedValidation(value string) *CronJobSpecApplyConfiguration { + b.StringAliasAddedValidation = &value + return b +} + +// WithStringAliasAlreadyValidated sets the StringAliasAlreadyValidated field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the StringAliasAlreadyValidated field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithStringAliasAlreadyValidated(value string) *CronJobSpecApplyConfiguration { + b.StringAliasAlreadyValidated = &value + return b +} + +// WithStringPair adds the given value to the StringPair field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the StringPair field. +func (b *CronJobSpecApplyConfiguration) WithStringPair(values ...string) *CronJobSpecApplyConfiguration { + for i := range values { + b.StringPair = append(b.StringPair, values[i]) + } + return b +} + +// WithLongerStringArray adds the given value to the LongerStringArray field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the LongerStringArray field. +func (b *CronJobSpecApplyConfiguration) WithLongerStringArray(values ...apiv1.LongerString) *CronJobSpecApplyConfiguration { + for i := range values { + b.LongerStringArray = append(b.LongerStringArray, values[i]) + } + return b +} + +// WithIntOrStringArrayWithAPattern adds the given value to the IntOrStringArrayWithAPattern field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the IntOrStringArrayWithAPattern field. +func (b *CronJobSpecApplyConfiguration) WithIntOrStringArrayWithAPattern(values ...*intstr.IntOrString) *CronJobSpecApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithIntOrStringArrayWithAPattern") + } + b.IntOrStringArrayWithAPattern = append(b.IntOrStringArrayWithAPattern, *values[i]) + } + return b +} + +// WithProtocol sets the Protocol field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Protocol field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithProtocol(value corev1.Protocol) *CronJobSpecApplyConfiguration { + b.Protocol = &value + return b +} + +// WithSelectableFieldString sets the SelectableFieldString field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the SelectableFieldString field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithSelectableFieldString(value string) *CronJobSpecApplyConfiguration { + b.SelectableFieldString = &value + return b +} + +// WithFromEmbedded sets the FromEmbedded field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the FromEmbedded field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithFromEmbedded(value string) *CronJobSpecApplyConfiguration { + b.EmbeddedStructApplyConfiguration.FromEmbedded = &value + return b +} + +// WithOnlyAllowSettingOnUpdate sets the OnlyAllowSettingOnUpdate field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the OnlyAllowSettingOnUpdate field is set to the value of the last call. +func (b *CronJobSpecApplyConfiguration) WithOnlyAllowSettingOnUpdate(value int32) *CronJobSpecApplyConfiguration { + b.OnlyAllowSettingOnUpdate = &value + return b +} diff --git a/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/cronjobstatus.go b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/cronjobstatus.go new file mode 100644 index 000000000..22886a73a --- /dev/null +++ b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/cronjobstatus.go @@ -0,0 +1,103 @@ +// Code generated by applyconfiguration. DO NOT EDIT. + +package v1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + apiv1 "sigs.k8s.io/controller-tools/pkg/applyconfiguration/testdata/cronjob/api/v1" +) + +// CronJobStatusApplyConfiguration represents a declarative configuration of the CronJobStatus type for use +// with apply. +type CronJobStatusApplyConfiguration struct { + Active []corev1.ObjectReference `json:"active,omitempty"` + LastScheduleTime *metav1.Time `json:"lastScheduleTime,omitempty"` + LastScheduleTime2 *apiv1.Time2 `json:"lastScheduleTime2,omitempty"` + LastScheduleMicroTime *metav1.MicroTime `json:"lastScheduleMicroTime,omitempty"` + LastActiveLogURL *apiv1.URL `json:"lastActiveLogURL,omitempty"` + LastActiveLogURL2 *apiv1.URL2 `json:"lastActiveLogURL2,omitempty"` + LastActiveLogURL3 *apiv1.URL3 `json:"lastActiveLogURL3,omitempty"` + LastActiveLogURL4 *apiv1.URL4 `json:"lastActiveLogURL4,omitempty"` + Runtime *DurationApplyConfiguration `json:"duration,omitempty"` +} + +// CronJobStatusApplyConfiguration constructs a declarative configuration of the CronJobStatus type for use with +// apply. +func CronJobStatus() *CronJobStatusApplyConfiguration { + return &CronJobStatusApplyConfiguration{} +} + +// WithActive adds the given value to the Active field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Active field. +func (b *CronJobStatusApplyConfiguration) WithActive(values ...corev1.ObjectReference) *CronJobStatusApplyConfiguration { + for i := range values { + b.Active = append(b.Active, values[i]) + } + return b +} + +// WithLastScheduleTime sets the LastScheduleTime field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the LastScheduleTime field is set to the value of the last call. +func (b *CronJobStatusApplyConfiguration) WithLastScheduleTime(value metav1.Time) *CronJobStatusApplyConfiguration { + b.LastScheduleTime = &value + return b +} + +// WithLastScheduleTime2 sets the LastScheduleTime2 field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the LastScheduleTime2 field is set to the value of the last call. +func (b *CronJobStatusApplyConfiguration) WithLastScheduleTime2(value apiv1.Time2) *CronJobStatusApplyConfiguration { + b.LastScheduleTime2 = &value + return b +} + +// WithLastScheduleMicroTime sets the LastScheduleMicroTime field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the LastScheduleMicroTime field is set to the value of the last call. +func (b *CronJobStatusApplyConfiguration) WithLastScheduleMicroTime(value metav1.MicroTime) *CronJobStatusApplyConfiguration { + b.LastScheduleMicroTime = &value + return b +} + +// WithLastActiveLogURL sets the LastActiveLogURL field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the LastActiveLogURL field is set to the value of the last call. +func (b *CronJobStatusApplyConfiguration) WithLastActiveLogURL(value apiv1.URL) *CronJobStatusApplyConfiguration { + b.LastActiveLogURL = &value + return b +} + +// WithLastActiveLogURL2 sets the LastActiveLogURL2 field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the LastActiveLogURL2 field is set to the value of the last call. +func (b *CronJobStatusApplyConfiguration) WithLastActiveLogURL2(value apiv1.URL2) *CronJobStatusApplyConfiguration { + b.LastActiveLogURL2 = &value + return b +} + +// WithLastActiveLogURL3 sets the LastActiveLogURL3 field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the LastActiveLogURL3 field is set to the value of the last call. +func (b *CronJobStatusApplyConfiguration) WithLastActiveLogURL3(value apiv1.URL3) *CronJobStatusApplyConfiguration { + b.LastActiveLogURL3 = &value + return b +} + +// WithLastActiveLogURL4 sets the LastActiveLogURL4 field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the LastActiveLogURL4 field is set to the value of the last call. +func (b *CronJobStatusApplyConfiguration) WithLastActiveLogURL4(value apiv1.URL4) *CronJobStatusApplyConfiguration { + b.LastActiveLogURL4 = &value + return b +} + +// WithRuntime sets the Runtime field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Runtime field is set to the value of the last call. +func (b *CronJobStatusApplyConfiguration) WithRuntime(value *DurationApplyConfiguration) *CronJobStatusApplyConfiguration { + b.Runtime = value + return b +} diff --git a/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/duration.go b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/duration.go new file mode 100644 index 000000000..3fc540f17 --- /dev/null +++ b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/duration.go @@ -0,0 +1,27 @@ +// Code generated by applyconfiguration. DO NOT EDIT. + +package v1 + +import ( + time "time" +) + +// DurationApplyConfiguration represents a declarative configuration of the Duration type for use +// with apply. +type DurationApplyConfiguration struct { + Value *time.Duration `json:"value,omitempty"` +} + +// DurationApplyConfiguration constructs a declarative configuration of the Duration type for use with +// apply. +func Duration() *DurationApplyConfiguration { + return &DurationApplyConfiguration{} +} + +// WithValue sets the Value field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Value field is set to the value of the last call. +func (b *DurationApplyConfiguration) WithValue(value time.Duration) *DurationApplyConfiguration { + b.Value = &value + return b +} diff --git a/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/embeddedstruct.go b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/embeddedstruct.go new file mode 100644 index 000000000..8dfbb200f --- /dev/null +++ b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/embeddedstruct.go @@ -0,0 +1,23 @@ +// Code generated by applyconfiguration. DO NOT EDIT. + +package v1 + +// EmbeddedStructApplyConfiguration represents a declarative configuration of the EmbeddedStruct type for use +// with apply. +type EmbeddedStructApplyConfiguration struct { + FromEmbedded *string `json:"fromEmbedded,omitempty"` +} + +// EmbeddedStructApplyConfiguration constructs a declarative configuration of the EmbeddedStruct type for use with +// apply. +func EmbeddedStruct() *EmbeddedStructApplyConfiguration { + return &EmbeddedStructApplyConfiguration{} +} + +// WithFromEmbedded sets the FromEmbedded field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the FromEmbedded field is set to the value of the last call. +func (b *EmbeddedStructApplyConfiguration) WithFromEmbedded(value string) *EmbeddedStructApplyConfiguration { + b.FromEmbedded = &value + return b +} diff --git a/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/empiableobject.go b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/empiableobject.go new file mode 100644 index 000000000..201c5493c --- /dev/null +++ b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/empiableobject.go @@ -0,0 +1,32 @@ +// Code generated by applyconfiguration. DO NOT EDIT. + +package v1 + +// EmpiableObjectApplyConfiguration represents a declarative configuration of the EmpiableObject type for use +// with apply. +type EmpiableObjectApplyConfiguration struct { + Foo *string `json:"foo,omitempty"` + Bar *string `json:"bar,omitempty"` +} + +// EmpiableObjectApplyConfiguration constructs a declarative configuration of the EmpiableObject type for use with +// apply. +func EmpiableObject() *EmpiableObjectApplyConfiguration { + return &EmpiableObjectApplyConfiguration{} +} + +// WithFoo sets the Foo field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Foo field is set to the value of the last call. +func (b *EmpiableObjectApplyConfiguration) WithFoo(value string) *EmpiableObjectApplyConfiguration { + b.Foo = &value + return b +} + +// WithBar sets the Bar field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Bar field is set to the value of the last call. +func (b *EmpiableObjectApplyConfiguration) WithBar(value string) *EmpiableObjectApplyConfiguration { + b.Bar = &value + return b +} diff --git a/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/exportedstruct.go b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/exportedstruct.go new file mode 100644 index 000000000..73cdedeb1 --- /dev/null +++ b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/exportedstruct.go @@ -0,0 +1,23 @@ +// Code generated by applyconfiguration. DO NOT EDIT. + +package v1 + +// ExportedStructApplyConfiguration represents a declarative configuration of the ExportedStruct type for use +// with apply. +type ExportedStructApplyConfiguration struct { + Baz *string `json:"baz,omitempty"` +} + +// ExportedStructApplyConfiguration constructs a declarative configuration of the ExportedStruct type for use with +// apply. +func ExportedStruct() *ExportedStructApplyConfiguration { + return &ExportedStructApplyConfiguration{} +} + +// WithBaz sets the Baz field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Baz field is set to the value of the last call. +func (b *ExportedStructApplyConfiguration) WithBaz(value string) *ExportedStructApplyConfiguration { + b.Baz = &value + return b +} diff --git a/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/justnestedobject.go b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/justnestedobject.go new file mode 100644 index 000000000..9ac372f6f --- /dev/null +++ b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/justnestedobject.go @@ -0,0 +1,32 @@ +// Code generated by applyconfiguration. DO NOT EDIT. + +package v1 + +// JustNestedObjectApplyConfiguration represents a declarative configuration of the JustNestedObject type for use +// with apply. +type JustNestedObjectApplyConfiguration struct { + Foo *string `json:"foo,omitempty"` + Bar *bool `json:"bar,omitempty"` +} + +// JustNestedObjectApplyConfiguration constructs a declarative configuration of the JustNestedObject type for use with +// apply. +func JustNestedObject() *JustNestedObjectApplyConfiguration { + return &JustNestedObjectApplyConfiguration{} +} + +// WithFoo sets the Foo field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Foo field is set to the value of the last call. +func (b *JustNestedObjectApplyConfiguration) WithFoo(value string) *JustNestedObjectApplyConfiguration { + b.Foo = &value + return b +} + +// WithBar sets the Bar field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Bar field is set to the value of the last call. +func (b *JustNestedObjectApplyConfiguration) WithBar(value bool) *JustNestedObjectApplyConfiguration { + b.Bar = &value + return b +} diff --git a/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/minmaxobject.go b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/minmaxobject.go new file mode 100644 index 000000000..d42590a14 --- /dev/null +++ b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/minmaxobject.go @@ -0,0 +1,41 @@ +// Code generated by applyconfiguration. DO NOT EDIT. + +package v1 + +// MinMaxObjectApplyConfiguration represents a declarative configuration of the MinMaxObject type for use +// with apply. +type MinMaxObjectApplyConfiguration struct { + Foo *string `json:"foo,omitempty"` + Bar *string `json:"bar,omitempty"` + Baz *string `json:"baz,omitempty"` +} + +// MinMaxObjectApplyConfiguration constructs a declarative configuration of the MinMaxObject type for use with +// apply. +func MinMaxObject() *MinMaxObjectApplyConfiguration { + return &MinMaxObjectApplyConfiguration{} +} + +// WithFoo sets the Foo field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Foo field is set to the value of the last call. +func (b *MinMaxObjectApplyConfiguration) WithFoo(value string) *MinMaxObjectApplyConfiguration { + b.Foo = &value + return b +} + +// WithBar sets the Bar field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Bar field is set to the value of the last call. +func (b *MinMaxObjectApplyConfiguration) WithBar(value string) *MinMaxObjectApplyConfiguration { + b.Bar = &value + return b +} + +// WithBaz sets the Baz field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Baz field is set to the value of the last call. +func (b *MinMaxObjectApplyConfiguration) WithBaz(value string) *MinMaxObjectApplyConfiguration { + b.Baz = &value + return b +} diff --git a/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/nestedobject.go b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/nestedobject.go new file mode 100644 index 000000000..c71d89350 --- /dev/null +++ b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/nestedobject.go @@ -0,0 +1,32 @@ +// Code generated by applyconfiguration. DO NOT EDIT. + +package v1 + +// NestedObjectApplyConfiguration represents a declarative configuration of the NestedObject type for use +// with apply. +type NestedObjectApplyConfiguration struct { + Foo *string `json:"foo,omitempty"` + Bar *bool `json:"bar,omitempty"` +} + +// NestedObjectApplyConfiguration constructs a declarative configuration of the NestedObject type for use with +// apply. +func NestedObject() *NestedObjectApplyConfiguration { + return &NestedObjectApplyConfiguration{} +} + +// WithFoo sets the Foo field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Foo field is set to the value of the last call. +func (b *NestedObjectApplyConfiguration) WithFoo(value string) *NestedObjectApplyConfiguration { + b.Foo = &value + return b +} + +// WithBar sets the Bar field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Bar field is set to the value of the last call. +func (b *NestedObjectApplyConfiguration) WithBar(value bool) *NestedObjectApplyConfiguration { + b.Bar = &value + return b +} diff --git a/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/nestedstructwithseveralfields.go b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/nestedstructwithseveralfields.go new file mode 100644 index 000000000..90433a899 --- /dev/null +++ b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/nestedstructwithseveralfields.go @@ -0,0 +1,32 @@ +// Code generated by applyconfiguration. DO NOT EDIT. + +package v1 + +// NestedStructWithSeveralFieldsApplyConfiguration represents a declarative configuration of the NestedStructWithSeveralFields type for use +// with apply. +type NestedStructWithSeveralFieldsApplyConfiguration struct { + Foo *string `json:"foo,omitempty"` + Bar *bool `json:"bar,omitempty"` +} + +// NestedStructWithSeveralFieldsApplyConfiguration constructs a declarative configuration of the NestedStructWithSeveralFields type for use with +// apply. +func NestedStructWithSeveralFields() *NestedStructWithSeveralFieldsApplyConfiguration { + return &NestedStructWithSeveralFieldsApplyConfiguration{} +} + +// WithFoo sets the Foo field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Foo field is set to the value of the last call. +func (b *NestedStructWithSeveralFieldsApplyConfiguration) WithFoo(value string) *NestedStructWithSeveralFieldsApplyConfiguration { + b.Foo = &value + return b +} + +// WithBar sets the Bar field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Bar field is set to the value of the last call. +func (b *NestedStructWithSeveralFieldsApplyConfiguration) WithBar(value bool) *NestedStructWithSeveralFieldsApplyConfiguration { + b.Bar = &value + return b +} diff --git a/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/preserved.go b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/preserved.go new file mode 100644 index 000000000..1decb4dd3 --- /dev/null +++ b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/preserved.go @@ -0,0 +1,23 @@ +// Code generated by applyconfiguration. DO NOT EDIT. + +package v1 + +// PreservedApplyConfiguration represents a declarative configuration of the Preserved type for use +// with apply. +type PreservedApplyConfiguration struct { + ConcreteField *string `json:"concreteField,omitempty"` +} + +// PreservedApplyConfiguration constructs a declarative configuration of the Preserved type for use with +// apply. +func Preserved() *PreservedApplyConfiguration { + return &PreservedApplyConfiguration{} +} + +// WithConcreteField sets the ConcreteField field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the ConcreteField field is set to the value of the last call. +func (b *PreservedApplyConfiguration) WithConcreteField(value string) *PreservedApplyConfiguration { + b.ConcreteField = &value + return b +} diff --git a/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/rootobject.go b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/rootobject.go new file mode 100644 index 000000000..746a475b6 --- /dev/null +++ b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/rootobject.go @@ -0,0 +1,23 @@ +// Code generated by applyconfiguration. DO NOT EDIT. + +package v1 + +// RootObjectApplyConfiguration represents a declarative configuration of the RootObject type for use +// with apply. +type RootObjectApplyConfiguration struct { + Nested *NestedObjectApplyConfiguration `json:"nested,omitempty"` +} + +// RootObjectApplyConfiguration constructs a declarative configuration of the RootObject type for use with +// apply. +func RootObject() *RootObjectApplyConfiguration { + return &RootObjectApplyConfiguration{} +} + +// WithNested sets the Nested field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Nested field is set to the value of the last call. +func (b *RootObjectApplyConfiguration) WithNested(value *NestedObjectApplyConfiguration) *RootObjectApplyConfiguration { + b.Nested = value + return b +} diff --git a/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/unexportedstruct.go b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/unexportedstruct.go new file mode 100644 index 000000000..966d65cab --- /dev/null +++ b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1/unexportedstruct.go @@ -0,0 +1,23 @@ +// Code generated by applyconfiguration. DO NOT EDIT. + +package v1 + +// UnexportedStructApplyConfiguration represents a declarative configuration of the UnexportedStruct type for use +// with apply. +type UnexportedStructApplyConfiguration struct { + Foo *string `json:"foo,omitempty"` +} + +// UnexportedStructApplyConfiguration constructs a declarative configuration of the UnexportedStruct type for use with +// apply. +func UnexportedStruct() *UnexportedStructApplyConfiguration { + return &UnexportedStructApplyConfiguration{} +} + +// WithFoo sets the Foo field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Foo field is set to the value of the last call. +func (b *UnexportedStructApplyConfiguration) WithFoo(value string) *UnexportedStructApplyConfiguration { + b.Foo = &value + return b +} diff --git a/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/internal/internal.go b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/internal/internal.go new file mode 100644 index 000000000..a0c4c4ecc --- /dev/null +++ b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/internal/internal.go @@ -0,0 +1,46 @@ +// Code generated by applyconfiguration. DO NOT EDIT. + +package internal + +import ( + fmt "fmt" + sync "sync" + + typed "sigs.k8s.io/structured-merge-diff/v4/typed" +) + +func Parser() *typed.Parser { + parserOnce.Do(func() { + var err error + parser, err = typed.NewParser(schemaYAML) + if err != nil { + panic(fmt.Sprintf("Failed to parse schema: %v", err)) + } + }) + return parser +} + +var parserOnce sync.Once +var parser *typed.Parser +var schemaYAML = typed.YAMLObject(`types: +- name: __untyped_atomic_ + scalar: untyped + list: + elementType: + namedType: __untyped_atomic_ + elementRelationship: atomic + map: + elementType: + namedType: __untyped_atomic_ + elementRelationship: atomic +- name: __untyped_deduced_ + scalar: untyped + list: + elementType: + namedType: __untyped_atomic_ + elementRelationship: atomic + map: + elementType: + namedType: __untyped_deduced_ + elementRelationship: separable +`) diff --git a/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/utils.go b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/utils.go new file mode 100644 index 000000000..314abe174 --- /dev/null +++ b/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/utils.go @@ -0,0 +1,58 @@ +// Code generated by applyconfiguration. DO NOT EDIT. + +package applyconfiguration + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + testing "k8s.io/client-go/testing" + v1 "sigs.k8s.io/controller-tools/pkg/applyconfiguration/testdata/cronjob/api/v1" + apiv1 "sigs.k8s.io/controller-tools/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/api/v1" + internal "sigs.k8s.io/controller-tools/pkg/applyconfiguration/testdata/cronjob/api/v1/applyconfiguration/internal" +) + +// ForKind returns an apply configuration type for the given GroupVersionKind, or nil if no +// apply configuration type exists for the given GroupVersionKind. +func ForKind(kind schema.GroupVersionKind) interface{} { + switch kind { + // Group=api, Version=v1 + case v1.SchemeGroupVersion.WithKind("AssociativeType"): + return &apiv1.AssociativeTypeApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("ContainsNestedMap"): + return &apiv1.ContainsNestedMapApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("CronJob"): + return &apiv1.CronJobApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("CronJobSpec"): + return &apiv1.CronJobSpecApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("CronJobStatus"): + return &apiv1.CronJobStatusApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("Duration"): + return &apiv1.DurationApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("EmbeddedStruct"): + return &apiv1.EmbeddedStructApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("EmpiableObject"): + return &apiv1.EmpiableObjectApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("ExportedStruct"): + return &apiv1.ExportedStructApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("JustNestedObject"): + return &apiv1.JustNestedObjectApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("MinMaxObject"): + return &apiv1.MinMaxObjectApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("NestedObject"): + return &apiv1.NestedObjectApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("NestedStructWithSeveralFields"): + return &apiv1.NestedStructWithSeveralFieldsApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("Preserved"): + return &apiv1.PreservedApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("RootObject"): + return &apiv1.RootObjectApplyConfiguration{} + case v1.SchemeGroupVersion.WithKind("UnexportedStruct"): + return &apiv1.unexportedStructApplyConfiguration{} + + } + return nil +} + +func NewTypeConverter(scheme *runtime.Scheme) *testing.TypeConverter { + return &testing.TypeConverter{Scheme: scheme, TypeResolver: internal.Parser()} +} diff --git a/pkg/applyconfiguration/testdata/cronjob/api/v1/cronjob_types.go b/pkg/applyconfiguration/testdata/cronjob/api/v1/cronjob_types.go new file mode 100644 index 000000000..c1010c4b3 --- /dev/null +++ b/pkg/applyconfiguration/testdata/cronjob/api/v1/cronjob_types.go @@ -0,0 +1,765 @@ +/* + +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. +*/ + +// TODO(directxman12): test this across both versions (right now we're just +// trusting k/k conversion, which is probably fine though) + +//go:generate ../../../.run-controller-gen.sh crd:ignoreUnexportedFields=true,allowDangerousTypes=true paths=./;./deprecated;./unserved;./job/... output:dir=. + +// +groupName=testdata.kubebuilder.io +// +versionName=v1 +package v1 + +import ( + "encoding" + "encoding/json" + "fmt" + "net/url" + "strconv" + "time" + + batchv1beta1 "k8s.io/api/batch/v1beta1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/intstr" +) + +// 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. + +const DefaultRefValue = "defaultRefValue" + +// CronJobSpec defines the desired state of CronJob +// +kubebuilder:validation:XValidation:rule="has(oldSelf.forbiddenInt) || !has(self.forbiddenInt)",message="forbiddenInt is not allowed",fieldPath=".forbiddenInt",reason="FieldValueForbidden" +type CronJobSpec struct { + // The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron. + Schedule string `json:"schedule"` + + // Optional deadline in seconds for starting the job if it misses scheduled + // time for any reason. Missed jobs executions will be counted as failed ones. + // +optional + StartingDeadlineSeconds *int64 `json:"startingDeadlineSeconds,omitempty"` + + // Specifies how to treat concurrent executions of a Job. + // Valid values are: + // - "Allow" (default): allows CronJobs to run concurrently; + // - "Forbid": forbids concurrent runs, skipping next run if previous run hasn't finished yet; + // - "Replace": cancels currently running job and replaces it with a new one + // +optional + ConcurrencyPolicy ConcurrencyPolicy `json:"concurrencyPolicy,omitempty"` + + // This flag tells the controller to suspend subsequent executions, it does + // not apply to already started executions. Defaults to false. + // +optional + Suspend *bool `json:"suspend,omitempty"` + + // This tests that non-serialized fields aren't included in the schema. + InternalData string `json:"-"` + + // This flag is like suspend, but for when you really mean it. + // It helps test the +kubebuilder:validation:Type marker. + // +optional + NoReallySuspend *TotallyABool `json:"noReallySuspend,omitempty"` + + // This tests byte slice schema generation. + BinaryName []byte `json:"binaryName"` + + // This tests that nullable works correctly + // +nullable + CanBeNull string `json:"canBeNull"` + + // Specifies the job that will be created when executing a CronJob. + JobTemplate batchv1beta1.JobTemplateSpec `json:"jobTemplate"` + + // The number of successful finished jobs to retain. + // This is a pointer to distinguish between explicit zero and not specified. + // +optional + SuccessfulJobsHistoryLimit *int32 `json:"successfulJobsHistoryLimit,omitempty"` + + // The number of failed finished jobs to retain. + // This is a pointer to distinguish between explicit zero and not specified. + // +optional + FailedJobsHistoryLimit *int32 `json:"failedJobsHistoryLimit,omitempty"` + + // This tests byte slices are allowed as map values. + ByteSliceData map[string][]byte `json:"byteSliceData,omitempty"` + + // This tests string slices are allowed as map values. + StringSliceData map[string][]string `json:"stringSliceData,omitempty"` + + // This tests pointers are allowed as map values. + PtrData map[string]*string `json:"ptrData,omitempty"` + + // This tests that markers that are allowed on both fields and types are applied to fields + // +kubebuilder:validation:MinLength=4 + TwoOfAKindPart0 string `json:"twoOfAKindPart0"` + + // This tests that markers that are allowed on both fields and types are applied to types + TwoOfAKindPart1 LongerString `json:"twoOfAKindPart1"` + + // This tests that primitive defaulting can be performed. + // +kubebuilder:default=forty-two + // +kubebuilder:example=forty-two + DefaultedString string `json:"defaultedString"` + + // This tests that slice defaulting can be performed. + // +kubebuilder:default={a,b} + // +kubebuilder:example={a,b} + DefaultedSlice []string `json:"defaultedSlice"` + + // This tests that slice and object defaulting can be performed. + // +kubebuilder:default={{nested: {foo: "baz", bar: true}},{nested: {foo: "qux", bar: false}}} + // +kubebuilder:example={{nested: {foo: "baz", bar: true}},{nested: {foo: "qux", bar: false}}} + DefaultedObject []RootObject `json:"defaultedObject"` + + // This tests that empty slice defaulting can be performed. + // +kubebuilder:default={} + DefaultedEmptySlice []string `json:"defaultedEmptySlice"` + + // This tests that an empty object defaulting can be performed on a map. + // +kubebuilder:default={} + DefaultedEmptyMap map[string]string `json:"defaultedEmptyMap"` + + // This tests that an empty object defaulting can be performed on an object. + // +kubebuilder:default={} + DefaultedEmptyObject EmpiableObject `json:"defaultedEmptyObject"` + + // This tests that kubebuilder defaulting takes precedence. + // +kubebuilder:default="kubebuilder-default" + // +default="kubernetes-default" + DoubleDefaultedString string `json:"doubleDefaultedString"` + + // This tests that primitive defaulting can be performed. + // +default="forty-two" + KubernetesDefaultedString string `json:"kubernetesDefaultedString"` + + // This tests that slice defaulting can be performed. + // +default=["a","b"] + KubernetesDefaultedSlice []string `json:"kubernetesDefaultedSlice"` + + // This tests that slice and object defaulting can be performed. + // +default=[{"nested": {"foo": "baz", "bar": true}},{"nested": {"foo": "qux", "bar": false}}] + KubernetesDefaultedObject []RootObject `json:"kubernetesDefaultedObject"` + + // This tests that empty slice defaulting can be performed. + // +default=[] + KubernetesDefaultedEmptySlice []string `json:"kubernetesDefaultedEmptySlice"` + + // This tests that an empty object defaulting can be performed on a map. + // +default={} + KubernetesDefaultedEmptyMap map[string]string `json:"kubernetesDefaultedEmptyMap"` + + // This tests that an empty object defaulting can be performed on an object. + // +default={} + KubernetesDefaultedEmptyObject EmpiableObject `json:"kubernetesDefaultedEmptyObject"` + + // This tests that use of +default=ref(...) doesn't break generation + // +default=ref(DefaultRefValue) + KubernetesDefaultedRef string `json:"kubernetesDefaultedRef,omitempty"` + + // This tests that pattern validator is properly applied. + // +kubebuilder:validation:Pattern=`^$|^((https):\/\/?)[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|\/?))$` + PatternObject string `json:"patternObject"` + + // +kubebuilder:validation:EmbeddedResource + // +kubebuilder:validation:nullable + EmbeddedResource runtime.RawExtension `json:"embeddedResource"` + + // +kubebuilder:validation:nullable + // +kubebuilder:pruning:PreserveUnknownFields + UnprunedJSON NestedObject `json:"unprunedJSON"` + + // +kubebuilder:pruning:PreserveUnknownFields + // +kubebuilder:validation:EmbeddedResource + // +kubebuilder:validation:nullable + UnprunedEmbeddedResource runtime.RawExtension `json:"unprunedEmbeddedResource"` + + // This tests that a type-level pruning marker works. + UnprunedFromType Preserved `json:"unprunedFomType"` + + // This tests that a type-level pruning marker combined with a field-level pruning marker works. + // +kubebuilder:pruning:PreserveUnknownFields + UnprunedFromTypeAndField Preserved `json:"unprunedFomTypeAndField"` + + // This tests that associative lists work. + // +listType=map + // +listMapKey=name + // +listMapKey=secondary + AssociativeList []AssociativeType `json:"associativeList"` + + // This tests that associative lists work via a nested type. + NestedAssociativeList NestedAssociativeList `json:"nestedassociativeList"` + + // A map that allows different actors to manage different fields + // +mapType=granular + MapOfInfo map[string][]byte `json:"mapOfInfo"` + + // A map that allows different actors to manage different fields via a nested type. + NestedMapOfInfo NestedMapOfInfo `json:"nestedMapOfInfo"` + + // A struct that can only be entirely replaced + // +structType=atomic + StructWithSeveralFields NestedObject `json:"structWithSeveralFields"` + + // A struct that can only be entirely replaced via a nested type. + NestedStructWithSeveralFields NestedStructWithSeveralFields `json:"nestedStructWithSeveralFields"` + + // A struct that can only be entirely replaced via a nested type and + // field markers. + // +structType=atomic + NestedStructWithSeveralFieldsDoubleMarked NestedStructWithSeveralFields `json:"nestedStructWithSeveralFieldsDoubleMarked"` + + // This tests that type references are properly flattened + // +kubebuilder:validation:optional + JustNestedObject *JustNestedObject `json:"justNestedObject,omitempty"` + + // This tests explicitly optional kubebuilder fields + // +kubebuilder:validation:Optional + ExplicitlyOptionalKubebuilder string `json:"explicitlyOptionalKubebuilder"` + + // This tests explicitly optional kubernetes fields + // +optional + ExplicitlyOptionalKubernetes string `json:"explicitlyOptionalKubernetes"` + + // This tests explicitly required kubebuilder fields + // +kubebuilder:validation:Required + ExplicitlyRequiredKubebuilder string `json:"explicitlyRequiredKubebuilder,omitempty"` + + // This tests explicitly required kubernetes fields + // +required + ExplicitlyRequiredKubernetes string `json:"explicitlyRequiredKubernetes,omitempty"` + + // This tests that min/max properties work + MinMaxProperties MinMaxObject `json:"minMaxProperties,omitempty"` + + // This tests that the schemaless marker works + // +kubebuilder:validation:Schemaless + Schemaless []byte `json:"schemaless,omitempty"` + + // This tests that an IntOrString can also have string validation. + // This can be useful if you want to limit the string to a percentage or integer. + // The XIntOrString marker is a requirement for having a pattern on this type. + // +kubebuilder:validation:XIntOrString + // +kubebuilder:validation:MaxLength=11 + // +kubebuilder:validation:MinLength=2 + // +kubebuilder:validation:Pattern="^((100|[0-9]{1,2})%|[0-9]+)$" + IntOrStringWithAPattern *intstr.IntOrString `json:"intOrStringWithAPattern,omitempty"` + + // Checks that nested maps work + NestedMap map[string]map[string]string `json:"nestedMap,omitempty"` + + // Checks that multiply-nested maps work + NestedNestedMap map[string]map[string]map[string]string `json:"nestedNestedMap,omitempty"` + + // Checks that maps containing types that contain maps work + ContainsNestedMapMap map[string]ContainsNestedMap `json:"nestedMapInStruct,omitempty"` + + // Maps of arrays of things-that-aren’t-strings are permitted + MapOfArraysOfFloats map[string][]bool `json:"mapOfArraysOfFloats,omitempty"` + + // +kubebuilder:validation:Minimum=-0.5 + // +kubebuilder:validation:Maximum=1.5 + // +kubebuilder:validation:MultipleOf=0.5 + FloatWithValidations float64 `json:"floatWithValidations"` + + // +kubebuilder:validation:Minimum=-0.5 + // +kubebuilder:validation:Maximum=1.5 + // +kubebuilder:validation:MultipleOf=0.5 + Float64WithValidations float64 `json:"float64WithValidations"` + + // +kubebuilder:validation:Minimum=-2 + // +kubebuilder:validation:Maximum=2 + // +kubebuilder:validation:MultipleOf=2 + IntWithValidations int `json:"intWithValidations"` + + // +kubebuilder:validation:Minimum=-2 + // +kubebuilder:validation:Maximum=2 + // +kubebuilder:validation:MultipleOf=2 + Int32WithValidations int32 `json:"int32WithValidations"` + + // This tests that unexported fields are skipped in the schema generation + unexportedField string + + // This tests that both unexported and exported inline fields are not skipped in the schema generation + unexportedStruct `json:",inline"` + ExportedStruct `json:",inline"` + + // Test of the expression-based validation rule marker, with optional message. + // +kubebuilder:validation:XValidation:rule="self.size() % 2 == 0",message="must have even length" + // +kubebuilder:validation:XValidation:rule="true" + StringWithEvenLength string `json:"stringWithEvenLength,omitempty"` + + // Test of the expression-based validation with messageExpression marker. + // +kubebuilder:validation:XValidation:rule="self.size() % 2 == 0",messageExpression="'Length has to be even but is ' + len(self.stringWithEvenLengthAndMessageExpression) + ' instead'" + StringWithEvenLengthAndMessageExpression string `json:"stringWithEvenLengthAndMessageExpression,omitempty"` + + // Test of the expression-based validation on both field and type. + // +kubebuilder:validation:XValidation:rule="self.startsWith('good-')",message="must have good prefix" + StringWithEvenLengthAndGoodPrefix StringEvenType `json:"stringWithEvenLengthAndGoodPrefix,omitempty"` + + // Test that we can add a forbidden field using XValidation Reason and FieldPath. + // The validation is applied to the spec struct itself and not the field. + ForbiddenInt int `json:"forbiddenInt,omitempty"` + + // Checks that fixed-length arrays work + Array [3]int `json:"array,omitempty"` + + // Checks that arrays work when the type contains a composite literal + ArrayUsingCompositeLiteral [len(struct{ X [3]int }{}.X)]string `json:"arrayUsingCompositeLiteral,omitempty"` + + // This tests string slice item validation. + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:items:MinLength=1 + // +kubebuilder:validation:items:MaxLength=255 + // +kubebuilder:validation:items:Pattern=^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + // +listType=set + Hosts []string `json:"hosts,omitempty"` + + // This tests slice item validation with enum + // +kubebuilder:validation:items:Enum=0;1;3 + EnumSlice []int `json:"enumSlice,omitempty"` + + HostsAlias Hosts `json:"hostsAlias,omitempty"` + + // This tests that alias imported from a package is handled correctly. The + // corev1.IPFamilyPolicyType is just reused since it's available from + // imported package. We can create our own in a separate package if needed. + AliasFromPackage corev1.IPFamilyPolicyType `json:"aliasFromPackage,omitempty"` + + // This tests that string alias is handled correctly. + StringAlias StringAlias `json:"stringAlias,omitempty"` + StringAliasPtr *StringAlias `json:"stringAliasPtr,omitempty"` + + // This tests that validation on a string alias type is handled correctly. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=255 + StringAliasAddedValidation StringAlias `json:"stringAliasAddedValidation,omitempty"` + + // This tests that validation on a the string alias type itself is handled correctly. + StringAliasAlreadyValidated StringAliasWithValidation `json:"stringAliasAlreadyValidated,omitempty"` + + // This tests string slice validation. + // +kubebuilder:validation:MinItems=2 + // +kubebuilder:validation:MaxItems=2 + StringPair []string `json:"stringPair"` + + // This tests string alias slice item validation. + // +kubebuilder:validation:MinItems=3 + LongerStringArray []LongerString `json:"longerStringArray,omitempty"` + + // This tests that a slice of IntOrString can also have string validation. + // This can be useful if you want to limit the string to a percentage or integer. + // The XIntOrString marker is a requirement for having a pattern on this type. + // +kubebuilder:validation:items:XIntOrString + // +kubebuilder:validation:items:MaxLength=10 + // +kubebuilder:validation:items:MinLength=1 + // +kubebuilder:validation:items:Pattern="^((100|[0-9]{1,2})%|[0-9]+)$" + IntOrStringArrayWithAPattern []*intstr.IntOrString `json:"intOrStringArrayWithAPattern,omitempty"` + + // This tests that we can embed protocol correctly (without ending up with allOf). + // Context: https://github.com/kubernetes-sigs/controller-tools/issues/1027 + // Defaults to "TCP". + // +optional + // +default="TCP" + Protocol corev1.Protocol `json:"protocol,omitempty" protobuf:"bytes,4,opt,name=protocol,casttype=Protocol"` + + // This tests that selectable field. + SelectableFieldString string `json:"selectableFieldString,omitempty"` + + // This tests that embedded struct, which is an alias type, is handled correctly. + InlineAlias `json:",inline"` + + // Test that we can add a field that can only be set to a non-default value on updates using XValidation OptionalOldSelf. + // +kubebuilder:validation:XValidation:rule="oldSelf.hasValue() || self == 0",message="must be set to 0 on creation. can be set to any value on an update.",optionalOldSelf=true + OnlyAllowSettingOnUpdate int32 `json:"onlyAllowSettingOnUpdate,omitempty"` +} + +type InlineAlias = EmbeddedStruct + +// EmbeddedStruct is for testing that embedded struct is handled correctly when it is used through an alias type. +type EmbeddedStruct struct { + // FromEmbedded is a field from the embedded struct that was used through an alias type. + FromEmbedded string `json:"fromEmbedded,omitempty"` +} + +type StringAlias = string + +// +kubebuilder:validation:MinLength=1 +// +kubebuilder:validation:MaxLength=255 +type StringAliasWithValidation = string + +type ContainsNestedMap struct { + InnerMap map[string]string `json:"innerMap,omitempty"` +} + +// +kubebuilder:validation:Type=object +// +kubebuilder:pruning:PreserveUnknownFields +type Preserved struct { + ConcreteField string `json:"concreteField"` + Rest map[string]interface{} `json:"-"` +} + +func (p *Preserved) UnmarshalJSON(data []byte) error { + if err := json.Unmarshal(data, &p.Rest); err != nil { + return err + } + conc, found := p.Rest["concreteField"] + if !found { + return nil + } + concStr, isStr := conc.(string) + if !isStr { + return fmt.Errorf("concreteField was not string") + } + delete(p.Rest, "concreteField") + p.ConcreteField = concStr + return nil +} + +func (p *Preserved) MarshalJSON() ([]byte, error) { + full := make(map[string]interface{}, len(p.Rest)+1) + for k, v := range p.Rest { + full[k] = v + } + full["concreteField"] = p.ConcreteField + return json.Marshal(full) +} + +type NestedObject struct { + Foo string `json:"foo"` + Bar bool `json:"bar"` +} + +// +structType=atomic +type NestedStructWithSeveralFields NestedObject + +type JustNestedObject NestedObject + +// +kubebuilder:validation:MinProperties=1 +// +kubebuilder:validation:MaxProperties=2 +type MinMaxObject struct { + Foo string `json:"foo,omitempty"` + Bar string `json:"bar,omitempty"` + Baz string `json:"baz,omitempty"` +} + +type EmpiableObject struct { + // +kubebuilder:default=forty-two + Foo string `json:"foo,omitempty"` + Bar string `json:"bar,omitempty"` +} + +type unexportedStruct struct { + // This tests that exported fields are not skipped in the schema generation + Foo string `json:"foo"` + + // This tests that unexported fields are skipped in the schema generation + bar string +} + +type ExportedStruct struct { + // This tests that exported fields are not skipped in the schema generation + Baz string `json:"baz"` + + // This tests that unexported fields are skipped in the schema generation + qux string +} + +type RootObject struct { + Nested NestedObject `json:"nested"` +} + +type AssociativeType struct { + Name string `json:"name"` + Secondary int `json:"secondary"` + Foo string `json:"foo"` +} + +// +listType=map +// +listMapKey=name +// +listMapKey=secondary +type NestedAssociativeList []AssociativeType + +// +mapType=granular +type NestedMapOfInfo map[string][]byte + +// +kubebuilder:validation:MinLength=4 +// This tests that markers that are allowed on both fields and types are applied to types +type LongerString string + +// use an explicit type marker to verify that apply-first markers generate properly + +// +kubebuilder:validation:Type=string +// TotallyABool is a bool that serializes as a string. +type TotallyABool bool + +// This tests string slice item validation. +// +kubebuilder:validation:MinItems=1 +// +kubebuilder:validation:items:MinLength=1 +// +kubebuilder:validation:items:MaxLength=255 +// +kubebuilder:validation:items:Pattern=^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ +// +listType=set +type Hosts []string + +func (t TotallyABool) MarshalJSON() ([]byte, error) { + if t { + return []byte(`"true"`), nil + } else { + return []byte(`"false"`), nil + } +} + +func (t *TotallyABool) UnmarshalJSON(in []byte) error { + switch string(in) { + case `"true"`: + *t = true + return nil + case `"false"`: + *t = false + default: + return fmt.Errorf("bad TotallyABool value %q", string(in)) + } + return nil +} + +// +kubebuilder:validation:Type=string +// URL wraps url.URL. +// It has custom json marshal methods that enable it to be used in K8s CRDs +// such that the CRD resource will have the URL but operator code can can work with url.URL struct +type URL struct { + url.URL +} + +func (u *URL) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf("%q", u.String())), nil +} + +func (u *URL) UnmarshalJSON(b []byte) error { + var ref string + if err := json.Unmarshal(b, &ref); err != nil { + return err + } + if ref == "" { + *u = URL{} + return nil + } + + r, err := url.Parse(ref) + if err != nil { + return err + } else if r != nil { + *u = URL{*r} + } else { + *u = URL{} + } + return nil +} + +func (u *URL) String() string { + if u == nil { + return "" + } + return u.URL.String() +} + +// +kubebuilder:validation:Type=string +// URL2 is an alias of url.URL. +// It has custom json marshal methods that enable it to be used in K8s CRDs +// such that the CRD resource will have the URL but operator code can can work with url.URL struct +type URL2 url.URL + +func (u *URL2) MarshalJSON() ([]byte, error) { + return []byte(fmt.Sprintf("%q", u.String())), nil +} + +func (u *URL2) UnmarshalJSON(b []byte) error { + var ref string + if err := json.Unmarshal(b, &ref); err != nil { + return err + } + if ref == "" { + *u = URL2{} + return nil + } + + r, err := url.Parse(ref) + if err != nil { + return err + } else if r != nil { + *u = *(*URL2)(r) + } else { + *u = URL2{} + } + return nil +} + +func (u *URL2) String() string { + if u == nil { + return "" + } + return (*url.URL)(u).String() +} + +// URL3 wraps [net/url.URL]. It implements [encoding.TextMarshaler] so that it +// can be used in K8s CRDs such that the CRD resource will have the URL but +// operator code can can work with the URL struct. +type URL3 struct{ url.URL } + +var _ encoding.TextMarshaler = (*URL3)(nil) + +// MarshalText implements [encoding.TextMarshaler]. +func (u *URL3) MarshalText() (text []byte, err error) { + return u.MarshalBinary() +} + +// URL4 is newtype around [net/url.URL]. It implements [encoding.TextMarshaler] +// so that it can be used in K8s CRDs such that the CRD resource will have the +// URL but operator code can can work with the URL struct. +type URL4 url.URL + +var _ encoding.TextMarshaler = (*URL4)(nil) + +// MarshalText implements [encoding.TextMarshaler]. +func (u *URL4) MarshalText() (text []byte, err error) { + return (*url.URL)(u).MarshalBinary() +} + +// +kubebuilder:validation:Type=integer +// +kubebuilder:validation:Format=int64 +// Time2 is a newtype around [metav1.Time]. +// It implements both [encoding.TextMarshaler] and [json.Marshaler]. +// The latter is authoritative for the CRD generation. +type Time2 time.Time + +var _ interface { + encoding.TextMarshaler + json.Marshaler +} = (*Time2)(nil) + +// MarshalText implements [encoding.TextMarshaler]. +func (t *Time2) MarshalText() (text []byte, err error) { + return []byte((*time.Time)(t).String()), nil +} + +// MarshalJSON implements [json.Marshaler]. +func (t *Time2) MarshalJSON() ([]byte, error) { + return strconv.AppendInt(nil, (*time.Time)(t).UnixMilli(), 10), nil +} + +// Duration has a custom Marshaler but no markers. +// We want the CRD generation to infer type information +// from the go types and ignore the presense of the Marshaler. +type Duration struct { + Value time.Duration `json:"value"` +} + +func (d Duration) MarshalJSON() ([]byte, error) { + type durationWithoutUnmarshaler Duration + return json.Marshal(durationWithoutUnmarshaler(d)) +} + +var _ json.Marshaler = Duration{} + +// ConcurrencyPolicy describes how the job will be handled. +// Only one of the following concurrent policies may be specified. +// If none of the following policies is specified, the default one +// is AllowConcurrent. +// +kubebuilder:validation:Enum=Allow;Forbid;Replace +type ConcurrencyPolicy string + +const ( + // AllowConcurrent allows CronJobs to run concurrently. + AllowConcurrent ConcurrencyPolicy = "Allow" + + // ForbidConcurrent forbids concurrent runs, skipping next run if previous + // hasn't finished yet. + ForbidConcurrent ConcurrencyPolicy = "Forbid" + + // ReplaceConcurrent cancels currently running job and replaces it with a new one. + ReplaceConcurrent ConcurrencyPolicy = "Replace" +) + +// StringEvenType is a type that includes an expression-based validation. +// +kubebuilder:validation:XValidation:rule="self.size() % 2 == 0",message="must have even length" +type StringEvenType string + +// 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 + + // A list of pointers to currently running jobs. + // +optional + Active []corev1.ObjectReference `json:"active,omitempty"` + + // Information when was the last time the job was successfully scheduled. + // +optional + LastScheduleTime *metav1.Time `json:"lastScheduleTime,omitempty"` + + // Information when was the last time the job was successfully scheduled. + // +optional + LastScheduleTime2 Time2 `json:"lastScheduleTime2,omitempty"` + + // Information about the last time the job was successfully scheduled, + // with microsecond precision. + // +optional + LastScheduleMicroTime *metav1.MicroTime `json:"lastScheduleMicroTime,omitempty"` + + // LastActiveLogURL specifies the logging url for the last started job + // +optional + LastActiveLogURL *URL `json:"lastActiveLogURL,omitempty"` + + // LastActiveLogURL2 specifies the logging url for the last started job + // +optional + LastActiveLogURL2 *URL2 `json:"lastActiveLogURL2,omitempty"` + + // LastActiveLogURL3 specifies the logging url for the last started job + // +optional + LastActiveLogURL3 *URL3 `json:"lastActiveLogURL3,omitempty"` + + // LastActiveLogURL4 specifies the logging url for the last started job + // +optional + LastActiveLogURL4 *URL4 `json:"lastActiveLogURL4,omitempty"` + + Runtime *Duration `json:"duration,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:singular=mycronjob +// +kubebuilder:storageversion +// +kubebuilder:metadata:annotations="api-approved.kubernetes.io=https://github.com/kubernetes-sigs/controller-tools";"cert-manager.io/inject-ca-from-secret=cert-manager/cert-manager-webhook-ca" +// +kubebuilder:selectablefield:JSONPath=`.spec.selectableFieldString` + +// 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"` +} diff --git a/pkg/applyconfiguration/testdata/cronjob/api/v1/groupversion_info.go b/pkg/applyconfiguration/testdata/cronjob/api/v1/groupversion_info.go new file mode 100644 index 000000000..569e35bba --- /dev/null +++ b/pkg/applyconfiguration/testdata/cronjob/api/v1/groupversion_info.go @@ -0,0 +1,43 @@ +/* +Copyright 2022 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. +*/ + +// +groupName=testdata.kubebuilder.io +// +versionName=v1 +// +kubebuilder:ac:generate=true +// +kubebuilder:ac:output:package="applyconfiguration" +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +var ( + GroupName = "testdata.kubebuilder.io" + GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + + // AddToScheme exists solely to keep the old generators creating valid code + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to api.Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + metav1.AddToGroupVersion(scheme, GroupVersion) + + return nil +} diff --git a/pkg/applyconfiguration/testdata/cronjob/go.mod b/pkg/applyconfiguration/testdata/cronjob/go.mod new file mode 100644 index 000000000..5e5314ee9 --- /dev/null +++ b/pkg/applyconfiguration/testdata/cronjob/go.mod @@ -0,0 +1,49 @@ +module sigs.k8s.io/controller-tools/pkg/applyconfiguration/testdata/cronjob + +go 1.24.0 + +toolchain go1.24.1 + +require ( + k8s.io/api v0.33.0-beta.0 + k8s.io/apimachinery v0.33.0-beta.0 + k8s.io/client-go v0.33.0-beta.0 + sigs.k8s.io/structured-merge-diff/v4 v4.6.0 +) + +require ( + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/google/gnostic-models v0.6.9 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/x448/float16 v0.8.4 // indirect + golang.org/x/net v0.33.0 // indirect + golang.org/x/oauth2 v0.27.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/term v0.29.0 // indirect + golang.org/x/text v0.22.0 // indirect + golang.org/x/time v0.9.0 // indirect + google.golang.org/protobuf v1.36.5 // indirect + gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/klog/v2 v2.130.1 // indirect + k8s.io/kube-openapi v0.0.0-20250304201544-e5f78fe3ede9 // indirect + k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect + sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect + sigs.k8s.io/randfill v1.0.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect +) diff --git a/pkg/applyconfiguration/testdata/cronjob/go.sum b/pkg/applyconfiguration/testdata/cronjob/go.sum new file mode 100644 index 000000000..730d19731 --- /dev/null +++ b/pkg/applyconfiguration/testdata/cronjob/go.sum @@ -0,0 +1,154 @@ +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= +github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= +github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo= +github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM= +github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= +github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4= +github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= +golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= +golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= +golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +k8s.io/api v0.33.0-beta.0 h1:/sAUrfXsjKPST2mZjpWhjRdzSR6SD5KlJpiOgCQQhAQ= +k8s.io/api v0.33.0-beta.0/go.mod h1:TYyCgedkG4OVS4+4D2n25BdbMcexMSLx6Y7OkAzkxLQ= +k8s.io/apimachinery v0.33.0-beta.0 h1:vLDBChfQwyimk6AbuT7OZOIqxSg/44JlXuxqBk85j68= +k8s.io/apimachinery v0.33.0-beta.0/go.mod h1:S2OIkExGqJOXYSYcAJwQ9zWcc6BkBUdTJUu4M7z0cvo= +k8s.io/client-go v0.33.0-beta.0 h1:xRGKK5hU39pb6CFDCDOOlG+LEenB93/RK9hoP4eyAsU= +k8s.io/client-go v0.33.0-beta.0/go.mod h1:RF6hSu+FncpgHQs1zA1UfGbMq8gxay89r37bCQe+Mj4= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20250304201544-e5f78fe3ede9 h1:t0huyHnz6HsokckRxAF1bY0cqPFwzINKCL7yltEjZQc= +k8s.io/kube-openapi v0.0.0-20250304201544-e5f78fe3ede9/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= +k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= +k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= +sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo= +sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= +sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/structured-merge-diff/v4 v4.6.0 h1:IUA9nvMmnKWcj5jl84xn+T5MnlZKThmUW1TdblaLVAc= +sigs.k8s.io/structured-merge-diff/v4 v4.6.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/pkg/applyconfiguration/zz_generated.markerhelp.go b/pkg/applyconfiguration/zz_generated.markerhelp.go new file mode 100644 index 000000000..6e0a0af27 --- /dev/null +++ b/pkg/applyconfiguration/zz_generated.markerhelp.go @@ -0,0 +1,41 @@ +//go:build !ignore_autogenerated + +/* +Copyright2019 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 helpgen. DO NOT EDIT. + +package applyconfiguration + +import ( + "sigs.k8s.io/controller-tools/pkg/markers" +) + +func (Generator) Help() *markers.DefinitionHelp { + return &markers.DefinitionHelp{ + Category: "", + DetailedHelp: markers.DetailedHelp{ + Summary: "generates code containing apply configuration type implementations.", + Details: "", + }, + FieldHelp: map[string]markers.DetailedHelp{ + "HeaderFile": { + Summary: "specifies the header text (e.g. license) to prepend to generated files.", + Details: "", + }, + }, + } +} diff --git a/pkg/deepcopy/testdata/go.sum b/pkg/deepcopy/testdata/go.sum index 965a7973c..eb76c6bed 100644 --- a/pkg/deepcopy/testdata/go.sum +++ b/pkg/deepcopy/testdata/go.sum @@ -151,6 +151,7 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/pkg/genall/output.go b/pkg/genall/output.go index 3eb43b0c2..9531e82fa 100644 --- a/pkg/genall/output.go +++ b/pkg/genall/output.go @@ -154,6 +154,12 @@ func (o OutputArtifacts) Open(pkg *loader.Package, itemPath string) (io.WriteClo return nil, fmt.Errorf("cannot output to a package with no path on disk") } outDir := filepath.Dir(pkg.CompiledGoFiles[0]) + if _, err := os.Stat(outDir); os.IsNotExist(err) { + if err := os.MkdirAll(outDir, os.ModePerm); err != nil { + return nil, err + } + } + outPath := filepath.Join(outDir, itemPath) return os.Create(outPath) }