Skip to content

Commit 06ca07b

Browse files
JoelSpeedjpbetzJefftreejakobmoellerdev
authored
✨ Generation of typed apply clients using upstream generator (#818)
* Stub out generator * Add apply gen to controller-tools * Add code-generator to go.mod * Integrate upstream apply config generator * Cleanup unused code from previous implementation * Convert controller-tools tags to genclient * Add generated clients * Cleanup markers, ensure correct path for non GOPATH * Add test to check generated content against generated master * chore: resolve applyconfig gen correctly * Migrate to gengo v2 * Update generated test data * Ignore testdata for the purposes of go generate * Rename apply command to applyconfiguration * Rename package to applyconfiguration * Rework tests to use temporary directory for output files * Update cronjob_types with the latest version * Update groupversion inline with latest kubebuilder * Update go.mod to match latest of top level * Move test apis into an API v1 folder to be more accurate * Add test for generating client outside of API directory * Address feedback on gen.go --------- Co-authored-by: Joe Betz <[email protected]> Co-authored-by: Jefftree <[email protected]> Co-authored-by: Jakob Möller <[email protected]>
1 parent ae8400e commit 06ca07b

32 files changed

+3254
-7
lines changed

cmd/controller-gen/main.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import (
2424
"strings"
2525

2626
"github.com/spf13/cobra"
27+
28+
"sigs.k8s.io/controller-tools/pkg/applyconfiguration"
2729
"sigs.k8s.io/controller-tools/pkg/crd"
2830
"sigs.k8s.io/controller-tools/pkg/deepcopy"
2931
"sigs.k8s.io/controller-tools/pkg/genall"
@@ -48,11 +50,12 @@ var (
4850
// each turns into a command line option,
4951
// and has options for output forms.
5052
allGenerators = map[string]genall.Generator{
51-
"crd": crd.Generator{},
52-
"rbac": rbac.Generator{},
53-
"object": deepcopy.Generator{},
54-
"webhook": webhook.Generator{},
55-
"schemapatch": schemapatcher.Generator{},
53+
"crd": crd.Generator{},
54+
"rbac": rbac.Generator{},
55+
"object": deepcopy.Generator{},
56+
"applyconfiguration": applyconfiguration.Generator{},
57+
"webhook": webhook.Generator{},
58+
"schemapatch": schemapatcher.Generator{},
5659
}
5760

5861
// allOutputRules defines the list of all known output rules, giving
@@ -139,13 +142,18 @@ func main() {
139142
controller-gen object paths=./apis/v1beta1/some_types.go
140143
141144
# Generate OpenAPI v3 schemas for API packages and merge them into existing CRD manifests
142-
controller-gen schemapatch:manifests=./manifests output:dir=./manifests paths=./pkg/apis/...
145+
controller-gen schemapatch:manifests=./manifests output:dir=./manifests paths=./pkg/apis/...
143146
144147
# Run all the generators for a given project
145148
controller-gen paths=./apis/...
146149
147150
# Explain the markers for generating CRDs, and their arguments
148151
controller-gen crd -ww
152+
153+
# Generate applyconfigurations for CRDs for use with Server Side Apply. They will be placed
154+
# into a "applyconfiguration/" subdirectory
155+
156+
controller-gen applyconfiguration paths=./apis/...
149157
`,
150158
RunE: func(c *cobra.Command, rawOpts []string) error {
151159
// print version if asked for it

go.mod

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ require (
1616
k8s.io/api v0.33.0-beta.0
1717
k8s.io/apiextensions-apiserver v0.33.0-beta.0
1818
k8s.io/apimachinery v0.33.0-beta.0
19+
k8s.io/code-generator v0.33.0-beta.0
20+
k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7
1921
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738
2022
sigs.k8s.io/yaml v1.4.0
2123
)
@@ -24,10 +26,15 @@ require (
2426
github.com/fsnotify/fsnotify v1.7.0 // indirect
2527
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
2628
github.com/go-logr/logr v1.4.2 // indirect
29+
github.com/go-openapi/jsonpointer v0.21.0 // indirect
30+
github.com/go-openapi/jsonreference v0.20.2 // indirect
31+
github.com/go-openapi/swag v0.23.0 // indirect
2732
github.com/gogo/protobuf v1.3.2 // indirect
33+
github.com/google/gnostic-models v0.6.9 // indirect
2834
github.com/inconshreveable/mousetrap v1.1.0 // indirect
35+
github.com/josharian/intern v1.0.0 // indirect
2936
github.com/json-iterator/go v1.1.12 // indirect
30-
github.com/kr/text v0.2.0 // indirect
37+
github.com/mailru/easyjson v0.7.7 // indirect
3138
github.com/mattn/go-colorable v0.1.13 // indirect
3239
github.com/mattn/go-isatty v0.0.20 // indirect
3340
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
@@ -39,9 +46,11 @@ require (
3946
golang.org/x/sync v0.12.0 // indirect
4047
golang.org/x/sys v0.31.0 // indirect
4148
golang.org/x/text v0.23.0 // indirect
49+
google.golang.org/protobuf v1.36.5 // indirect
4250
gopkg.in/inf.v0 v0.9.1 // indirect
4351
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
4452
k8s.io/klog/v2 v2.130.1 // indirect
53+
k8s.io/kube-openapi v0.0.0-20250304201544-e5f78fe3ede9 // indirect
4554
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
4655
sigs.k8s.io/randfill v1.0.0 // indirect
4756
sigs.k8s.io/structured-merge-diff/v4 v4.6.0 // indirect

go.sum

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv
1313
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
1414
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
1515
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
16+
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
17+
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
18+
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
19+
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
20+
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
21+
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
22+
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
23+
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
1624
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
1725
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
1826
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
2836
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
2937
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
3038
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
39+
github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
40+
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
3141
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
3242
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
3343
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
4050
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
4151
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
4252
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
53+
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
54+
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
4355
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
4456
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
4557
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
4658
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
59+
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
4760
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
4861
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
62+
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
63+
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
4964
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
5065
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
66+
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
67+
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
5168
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
5269
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
5370
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
173190
k8s.io/apiextensions-apiserver v0.33.0-beta.0/go.mod h1:TKTeoFcmGvtiDNV+wj8wJfZhamZNOhvi9yOIE2d1iWs=
174191
k8s.io/apimachinery v0.33.0-beta.0 h1:vLDBChfQwyimk6AbuT7OZOIqxSg/44JlXuxqBk85j68=
175192
k8s.io/apimachinery v0.33.0-beta.0/go.mod h1:S2OIkExGqJOXYSYcAJwQ9zWcc6BkBUdTJUu4M7z0cvo=
193+
k8s.io/code-generator v0.33.0-beta.0 h1:QYiWYFUT9G7lnF1ucDYr/sZUaG/kptrooX2PJxEL+Go=
194+
k8s.io/code-generator v0.33.0-beta.0/go.mod h1:RBvFpvqtyQygCBjMayNyYqdzy+89LdzqAx0Th+dgmzQ=
195+
k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7 h1:2OX19X59HxDprNCVrWi6jb7LW1PoqTlYqEq5H2oetog=
196+
k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU=
176197
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
177198
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
199+
k8s.io/kube-openapi v0.0.0-20250304201544-e5f78fe3ede9 h1:t0huyHnz6HsokckRxAF1bY0cqPFwzINKCL7yltEjZQc=
200+
k8s.io/kube-openapi v0.0.0-20250304201544-e5f78fe3ede9/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8=
178201
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
179202
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
180203
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package applyconfiguration
18+
19+
import (
20+
"fmt"
21+
"io"
22+
"io/fs"
23+
"os"
24+
"path/filepath"
25+
"strings"
26+
27+
. "github.com/onsi/ginkgo"
28+
. "github.com/onsi/ginkgo/extensions/table"
29+
. "github.com/onsi/gomega"
30+
"k8s.io/apimachinery/pkg/util/sets"
31+
32+
"sigs.k8s.io/controller-tools/pkg/crd"
33+
"sigs.k8s.io/controller-tools/pkg/genall"
34+
"sigs.k8s.io/controller-tools/pkg/loader"
35+
"sigs.k8s.io/controller-tools/pkg/markers"
36+
)
37+
38+
const (
39+
cronjobDir = "./testdata/cronjob"
40+
applyConfigurationDir = "applyconfiguration"
41+
)
42+
43+
type outputToMap map[string]*outputFile
44+
45+
// Open implements genall.OutputRule.
46+
func (m outputToMap) Open(_ *loader.Package, path string) (io.WriteCloser, error) {
47+
if _, ok := m[path]; !ok {
48+
m[path] = &outputFile{}
49+
}
50+
return m[path], nil
51+
}
52+
53+
type outputFile struct {
54+
contents []byte
55+
}
56+
57+
func (o *outputFile) Write(p []byte) (int, error) {
58+
o.contents = append(o.contents, p...)
59+
return len(p), nil
60+
}
61+
62+
func (o *outputFile) Close() error {
63+
return nil
64+
}
65+
66+
var _ = Describe("ApplyConfiguration generation from API types", func() {
67+
var originalCWD string
68+
69+
BeforeEach(func() {
70+
var tmpDir string
71+
72+
By("Setting up a temporary directory", func() {
73+
var err error
74+
tmpDir, err = os.MkdirTemp("", "applyconfiguration-integration-test")
75+
Expect(err).NotTo(HaveOccurred(), "Should be able to create a temporary directory")
76+
77+
// Copy the testdata directory, but removed the generated files.
78+
Expect(os.CopyFS(tmpDir, os.DirFS(cronjobDir))).To(Succeed(), "Should be able to copy source files")
79+
Expect(os.RemoveAll(filepath.Join(tmpDir, "api/v1", applyConfigurationDir))).To(Succeed(), "Should be able to remove generated file from temp directory")
80+
})
81+
82+
By("Switching into testdata to appease go modules", func() {
83+
cwd, err := os.Getwd()
84+
Expect(err).NotTo(HaveOccurred())
85+
86+
originalCWD = cwd
87+
88+
Expect(os.Chdir(tmpDir)).To(Succeed()) // go modules are directory-sensitive
89+
})
90+
91+
By(fmt.Sprintf("Completed set up in %s", tmpDir))
92+
})
93+
94+
AfterEach(func() {
95+
// Reset the working directory
96+
Expect(os.Chdir(originalCWD)).To(Succeed())
97+
})
98+
99+
DescribeTable("should be able to verify generated ApplyConfiguration types for the CronJob schema", func(outputPackage string) {
100+
Expect(replaceOutputPkgMarker("./api/v1", outputPackage)).To(Succeed())
101+
102+
// The output is used to capture the generated CRD file.
103+
// The output of the applyconfiguration cannot be generated to memory, gengo handles all of the writing to disk directly.
104+
output := make(outputToMap)
105+
106+
By("Initializing the runtime")
107+
optionsRegistry := &markers.Registry{}
108+
Expect(genall.RegisterOptionsMarkers(optionsRegistry)).To(Succeed())
109+
Expect(optionsRegistry.Register(markers.Must(markers.MakeDefinition("crd", markers.DescribesPackage, crd.Generator{})))).To(Succeed())
110+
Expect(optionsRegistry.Register(markers.Must(markers.MakeDefinition("applyconfiguration", markers.DescribesPackage, Generator{})))).To(Succeed())
111+
112+
rt, err := genall.FromOptions(optionsRegistry, []string{
113+
"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
114+
"applyconfiguration",
115+
"paths=./api/v1",
116+
})
117+
Expect(err).NotTo(HaveOccurred())
118+
119+
rt.OutputRules = genall.OutputRules{Default: output}
120+
121+
originalFS := os.DirFS(filepath.Join(originalCWD, cronjobDir))
122+
tmpFS := os.DirFS(".")
123+
124+
By("Running the generator")
125+
hadErrs := rt.Run()
126+
127+
By("Checking for generation errors")
128+
Expect(hadErrs).To(BeFalse(), "Generator should run without errors")
129+
130+
filesInOriginal := make(map[string][]byte)
131+
originalFileNames := sets.New[string]()
132+
Expect(fs.WalkDir(originalFS, filepath.Join("api/v1", applyConfigurationDir), func(path string, d fs.DirEntry, err error) error {
133+
if err != nil {
134+
return err
135+
}
136+
137+
if d.IsDir() {
138+
return nil
139+
}
140+
141+
data, err := os.ReadFile(filepath.Join(originalCWD, cronjobDir, path))
142+
if err != nil {
143+
return fmt.Errorf("error reading file %s: %w", path, err)
144+
}
145+
146+
// Record the path without the path prefix for comparison later.
147+
path = strings.TrimPrefix(path, filepath.Join("api/v1", applyConfigurationDir)+"/")
148+
originalFileNames.Insert(path)
149+
filesInOriginal[path] = data
150+
return nil
151+
})).To(Succeed())
152+
153+
filesInOutput := make(map[string][]byte)
154+
outputFileNames := sets.New[string]()
155+
Expect(fs.WalkDir(tmpFS, filepath.Join("api/v1", outputPackage), func(path string, d fs.DirEntry, err error) error {
156+
if err != nil {
157+
return err
158+
}
159+
160+
if d.IsDir() {
161+
return nil
162+
}
163+
164+
data, err := os.ReadFile(path)
165+
if err != nil {
166+
return fmt.Errorf("error reading file %s: %w", path, err)
167+
}
168+
169+
// Record the path without the path prefix for comparison later.
170+
path = strings.TrimPrefix(path, filepath.Join("api/v1", outputPackage)+"/")
171+
outputFileNames.Insert(path)
172+
filesInOutput[path] = data
173+
return nil
174+
})).To(Succeed())
175+
176+
// // Every file should be in both sets, check for files not in both sets.
177+
Expect(outputFileNames.UnsortedList()).To(ConsistOf(originalFileNames.UnsortedList()), "Generated files should match the checked in files")
178+
179+
for name, content := range filesInOriginal {
180+
// If the output package uses a relative path we need to remove the "../" from the package name.
181+
outputPackageName := strings.ReplaceAll(outputPackage, "../", "")
182+
183+
// Make sure the package string is correct for the newly generated content.
184+
content = []byte(strings.Replace(string(content), "package applyconfiguration", fmt.Sprintf("package %s", outputPackageName), 1))
185+
186+
// Make sure the import paths are correct for the newly generated content.
187+
content = []byte(strings.ReplaceAll(string(content), "testdata/cronjob/api/v1/applyconfiguration", filepath.Join("testdata/cronjob/api/v1", outputPackage)))
188+
189+
Expect(string(filesInOutput[name])).To(BeComparableTo(string(content)), "Generated files should match the checked in files, diff found in %s", name)
190+
}
191+
},
192+
Entry("with the default applyconfiguration output package", "applyconfiguration"),
193+
Entry("with the an alternative output package", "other"),
194+
Entry("with a package outside of the current directory", "../../clients"),
195+
)
196+
})
197+
198+
func replaceOutputPkgMarker(dir string, newOutputPackage string) error {
199+
f, err := os.Open(filepath.Join(dir, "groupversion_info.go"))
200+
if err != nil {
201+
return fmt.Errorf("error opening groupversion_info.go: %w", err)
202+
}
203+
defer f.Close()
204+
205+
data, err := io.ReadAll(f)
206+
if err != nil {
207+
return fmt.Errorf("error reading groupversion_info.go: %w", err)
208+
}
209+
210+
newData := strings.Replace(string(data), "// +kubebuilder:ac:output:package=\"applyconfiguration\"", fmt.Sprintf("// +kubebuilder:ac:output:package=\"%s\"", newOutputPackage), 1)
211+
212+
if err := os.WriteFile(filepath.Join(dir, "groupversion_info.go"), []byte(newData), 0644); err != nil {
213+
return fmt.Errorf("error writing groupversion_info.go: %w", err)
214+
}
215+
216+
return nil
217+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package applyconfiguration
18+
19+
import (
20+
"testing"
21+
22+
. "github.com/onsi/ginkgo"
23+
. "github.com/onsi/gomega"
24+
)
25+
26+
func TestObjectGeneration(t *testing.T) {
27+
RegisterFailHandler(Fail)
28+
RunSpecs(t, "ApplyConfiguration Generation Suite")
29+
}

0 commit comments

Comments
 (0)