Skip to content

Commit 0aa6676

Browse files
jakobmoellerdevJoelSpeed
authored andcommitted
chore: resolve applyconfig gen correctly
1 parent 49b2a52 commit 0aa6676

File tree

14 files changed

+54
-65
lines changed

14 files changed

+54
-65
lines changed

pkg/applyconfigurations/applyconfiguration_integration_test.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"io"
2222
"io/fs"
2323
"os"
24+
"path/filepath"
2425
"strings"
2526

2627
. "github.com/onsi/ginkgo"
@@ -57,6 +58,13 @@ func (o *outputFile) Close() error {
5758
}
5859

5960
var _ = Describe("CRD Generation From Parsing to CustomResourceDefinition", func() {
61+
outputPath := "testapplyconfiguration"
62+
masterPath := "applyconfiguration"
63+
By("resetting the test directory")
64+
// not using after each to allow for inspection of failed tests
65+
BeforeEach(func() {
66+
Expect(os.RemoveAll(filepath.Join(".", outputPath))).To(Succeed())
67+
})
6068
It("should be able to verify generated ApplyConfiguration types for the CronJob schema", func() {
6169
By("switching into testdata to appease go modules")
6270
cwd, err := os.Getwd()
@@ -79,6 +87,8 @@ var _ = Describe("CRD Generation From Parsing to CustomResourceDefinition", func
7987
Expect(err).NotTo(HaveOccurred())
8088
rt.OutputRules = genall.OutputRules{Default: output}
8189

90+
cronJobFS := os.DirFS(".")
91+
8292
By("running the generator and checking for errors")
8393
hadErrs := rt.Run()
8494

@@ -87,8 +97,6 @@ var _ = Describe("CRD Generation From Parsing to CustomResourceDefinition", func
8797

8898
filesInMaster := make(map[string][]byte)
8999
masterFileNames := sets.New[string]()
90-
cronJobFS := os.DirFS(".")
91-
masterPath := "applyconfiguration-master"
92100
Expect(fs.WalkDir(cronJobFS, masterPath, func(path string, d fs.DirEntry, err error) error {
93101
if err != nil {
94102
return err
@@ -112,7 +120,6 @@ var _ = Describe("CRD Generation From Parsing to CustomResourceDefinition", func
112120

113121
filesInOutput := make(map[string][]byte)
114122
outputFileNames := sets.New[string]()
115-
outputPath := "applyconfiguration"
116123
Expect(fs.WalkDir(cronJobFS, outputPath, func(path string, d fs.DirEntry, err error) error {
117124
if err != nil {
118125
return err

pkg/applyconfigurations/gen.go

Lines changed: 35 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,8 @@ package applyconfigurations
1919
import (
2020
"fmt"
2121
"go/ast"
22-
"go/types"
2322
"os"
2423
"path/filepath"
25-
"strings"
2624

2725
"k8s.io/apimachinery/pkg/util/sets"
2826
generatorargs "k8s.io/code-generator/cmd/applyconfiguration-gen/args"
@@ -39,14 +37,10 @@ import (
3937
var (
4038
isCRDMarker = markers.Must(markers.MakeDefinition("kubebuilder:resource", markers.DescribesType, crdmarkers.Resource{}))
4139
enablePkgMarker = markers.Must(markers.MakeDefinition("kubebuilder:ac:generate", markers.DescribesPackage, false))
40+
outputPkgMarker = markers.Must(markers.MakeDefinition("kubebuilder:ac:output:package", markers.DescribesPackage, ""))
4241
enableTypeMarker = markers.Must(markers.MakeDefinition("kubebuilder:ac:generate", markers.DescribesType, false))
4342
)
4443

45-
var importMapping = map[string]string{
46-
"k8s.io/apimachinery/pkg/apis/": "k8s.io/client-go/applyconfigurations/",
47-
"k8s.io/api/": "k8s.io/client-go/applyconfigurations/",
48-
}
49-
5044
const importPathSuffix = "applyconfiguration"
5145

5246
// +controllertools:marker:generateHelp
@@ -67,17 +61,18 @@ func (Generator) CheckFilter() loader.NodeFilter {
6761

6862
func (Generator) RegisterMarkers(into *markers.Registry) error {
6963
if err := markers.RegisterAll(into,
70-
isCRDMarker, enablePkgMarker, enableTypeMarker); err != nil {
64+
isCRDMarker, enablePkgMarker, enableTypeMarker, outputPkgMarker); err != nil {
7165
return err
7266
}
7367

7468
into.AddHelp(isCRDMarker,
7569
markers.SimpleHelp("apply", "enables apply configuration generation for this type"))
7670
into.AddHelp(
7771
enableTypeMarker, markers.SimpleHelp("apply", "overrides enabling or disabling applyconfigurations generation for the type"))
78-
7972
into.AddHelp(
8073
enablePkgMarker, markers.SimpleHelp("apply", "overrides enabling or disabling applyconfigurations generation for the package"))
74+
into.AddHelp(
75+
outputPkgMarker, markers.SimpleHelp("apply", "overrides the default output package for the applyconfigurations generation"))
8176
return nil
8277

8378
}
@@ -102,6 +97,18 @@ func enabledOnType(info *markers.TypeInfo) bool {
10297
return isCRD(info)
10398
}
10499

100+
func outputPkg(col *markers.Collector, pkg *loader.Package) (string, error) {
101+
pkgMarkers, err := markers.PackageMarkers(col, pkg)
102+
if err != nil {
103+
return "", err
104+
}
105+
pkgMarker := pkgMarkers.Get(outputPkgMarker.Name)
106+
if pkgMarker != nil {
107+
return pkgMarker.(string), nil
108+
}
109+
return "", nil
110+
}
111+
105112
// isCRD marks whether the type is a CRD based on the +kubebuilder:resource marker.
106113
func isCRD(info *markers.TypeInfo) bool {
107114
objectEnabled := info.Markers.Get(isCRDMarker.Name)
@@ -146,46 +153,6 @@ type ObjectGenCtx struct {
146153
HeaderFilePath string
147154
}
148155

149-
type Universe struct {
150-
typeMetadata map[types.Type]*typeMetadata
151-
}
152-
153-
type typeMetadata struct {
154-
used bool
155-
}
156-
157-
func (u *Universe) existingApplyConfigPath(_ *types.Named, pkgPath string) (string, bool) {
158-
for prefix, replacePath := range importMapping {
159-
if strings.HasPrefix(pkgPath, prefix) {
160-
path := replacePath + strings.TrimPrefix(pkgPath, prefix)
161-
return path, true
162-
}
163-
}
164-
return "", false
165-
}
166-
167-
func (u *Universe) IsApplyConfigGenerated(typeInfo *types.Named) bool {
168-
if t, ok := u.typeMetadata[typeInfo]; ok {
169-
return t.used
170-
}
171-
return false
172-
}
173-
174-
func (u *Universe) GetApplyConfigPath(typeInfo *types.Named, pkgPath string) (string, bool) {
175-
isApplyConfigGenerated := u.IsApplyConfigGenerated(typeInfo)
176-
if path, ok := u.existingApplyConfigPath(typeInfo, pkgPath); ok {
177-
if isApplyConfigGenerated {
178-
return path, true
179-
}
180-
return pkgPath, false
181-
}
182-
// ApplyConfig is necessary but location is not explicitly specified. Assume the ApplyConfig exists at the below directory
183-
if isApplyConfigGenerated {
184-
return pkgPath + "/" + importPathSuffix, true
185-
}
186-
return pkgPath, false
187-
}
188-
189156
// generateForPackage generates apply configuration implementations for
190157
// types in the given package, writing the formatted result to given writer.
191158
// May return nil if source could not be generated.
@@ -194,12 +161,27 @@ func (ctx *ObjectGenCtx) generateForPackage(root *loader.Package) error {
194161
if !enabled {
195162
return nil
196163
}
164+
if len(root.GoFiles) == 0 {
165+
return nil
166+
}
197167

198168
genericArgs, _ := generatorargs.NewDefaults()
199169
genericArgs.InputDirs = []string{root.PkgPath}
200-
genericArgs.OutputPackagePath = filepath.Join(root.PkgPath, importPathSuffix)
201170
genericArgs.GoHeaderFilePath = ctx.HeaderFilePath
202171

172+
outpkg, _ := outputPkg(ctx.Collector, root)
173+
if outpkg == "" {
174+
outpkg = importPathSuffix
175+
}
176+
genericArgs.OutputPackagePath = filepath.Join(root.PkgPath, outpkg)
177+
178+
// attempts to retrieve the correct base directory to output apply configurations to by
179+
// looking into the package and retrieving the first go file it finds, and using that as the output base.
180+
// this is because we cannot rely on gogen calculating the correct output base.
181+
// if we leave this empty, gogen will attempt to use GOPATH to write the files which is not wanted
182+
genericArgs.OutputBase = filepath.Dir(root.GoFiles[0])
183+
trimPathPrefix := filepath.Join(genericArgs.OutputBase, root.PkgPath) + "/"
184+
203185
// Make the generated header static so that it doesn't rely on the compiled binary name.
204186
genericArgs.GeneratedByCommentTemplate = "// Code generated by applyconfiguration-gen. DO NOT EDIT.\n"
205187

@@ -216,9 +198,9 @@ func (ctx *ObjectGenCtx) generateForPackage(root *loader.Package) error {
216198
if err != nil {
217199
return err
218200
}
219-
220-
// This allows the correct output location when GOPATH is unset.
221-
c.TrimPathPrefix = root.PkgPath + "/"
201+
// The output package path is fully qualified. It contains the OutputBase (which is the module directory)
202+
// that means we will have to trim the fully qualified pkg down again.
203+
c.TrimPathPrefix = trimPathPrefix
222204

223205
pkg, ok := c.Universe[root.PkgPath]
224206
if !ok {

pkg/applyconfigurations/testdata/cronjob/applyconfiguration/utils.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/applyconfigurations/testdata/cronjob/groupversion_info.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ limitations under the License.
1717
// +groupName=testdata.kubebuilder.io
1818
// +versionName=v1
1919
// +kubebuilder:ac:generate=true
20+
// +kubebuilder:ac:output:package="testapplyconfiguration"
2021
package testdata

pkg/applyconfigurations/testdata/cronjob/applyconfiguration-master/utils.go renamed to pkg/applyconfigurations/testdata/cronjob/testapplyconfiguration/utils.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/applyconfigurations/zz_generated.markerhelp.go

Lines changed: 0 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/oot_testsubdirectory

Whitespace-only changes.

pkg/webhook/zz_generated.markerhelp.go

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)