@@ -19,10 +19,8 @@ package applyconfigurations
19
19
import (
20
20
"fmt"
21
21
"go/ast"
22
- "go/types"
23
22
"os"
24
23
"path/filepath"
25
- "strings"
26
24
27
25
"k8s.io/apimachinery/pkg/util/sets"
28
26
generatorargs "k8s.io/code-generator/cmd/applyconfiguration-gen/args"
@@ -39,14 +37,10 @@ import (
39
37
var (
40
38
isCRDMarker = markers .Must (markers .MakeDefinition ("kubebuilder:resource" , markers .DescribesType , crdmarkers.Resource {}))
41
39
enablePkgMarker = markers .Must (markers .MakeDefinition ("kubebuilder:ac:generate" , markers .DescribesPackage , false ))
40
+ outputPkgMarker = markers .Must (markers .MakeDefinition ("kubebuilder:ac:output:package" , markers .DescribesPackage , "" ))
42
41
enableTypeMarker = markers .Must (markers .MakeDefinition ("kubebuilder:ac:generate" , markers .DescribesType , false ))
43
42
)
44
43
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
-
50
44
const importPathSuffix = "applyconfiguration"
51
45
52
46
// +controllertools:marker:generateHelp
@@ -67,17 +61,18 @@ func (Generator) CheckFilter() loader.NodeFilter {
67
61
68
62
func (Generator ) RegisterMarkers (into * markers.Registry ) error {
69
63
if err := markers .RegisterAll (into ,
70
- isCRDMarker , enablePkgMarker , enableTypeMarker ); err != nil {
64
+ isCRDMarker , enablePkgMarker , enableTypeMarker , outputPkgMarker ); err != nil {
71
65
return err
72
66
}
73
67
74
68
into .AddHelp (isCRDMarker ,
75
69
markers .SimpleHelp ("apply" , "enables apply configuration generation for this type" ))
76
70
into .AddHelp (
77
71
enableTypeMarker , markers .SimpleHelp ("apply" , "overrides enabling or disabling applyconfigurations generation for the type" ))
78
-
79
72
into .AddHelp (
80
73
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" ))
81
76
return nil
82
77
83
78
}
@@ -102,6 +97,18 @@ func enabledOnType(info *markers.TypeInfo) bool {
102
97
return isCRD (info )
103
98
}
104
99
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
+
105
112
// isCRD marks whether the type is a CRD based on the +kubebuilder:resource marker.
106
113
func isCRD (info * markers.TypeInfo ) bool {
107
114
objectEnabled := info .Markers .Get (isCRDMarker .Name )
@@ -146,46 +153,6 @@ type ObjectGenCtx struct {
146
153
HeaderFilePath string
147
154
}
148
155
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
-
189
156
// generateForPackage generates apply configuration implementations for
190
157
// types in the given package, writing the formatted result to given writer.
191
158
// May return nil if source could not be generated.
@@ -194,12 +161,27 @@ func (ctx *ObjectGenCtx) generateForPackage(root *loader.Package) error {
194
161
if ! enabled {
195
162
return nil
196
163
}
164
+ if len (root .GoFiles ) == 0 {
165
+ return nil
166
+ }
197
167
198
168
genericArgs , _ := generatorargs .NewDefaults ()
199
169
genericArgs .InputDirs = []string {root .PkgPath }
200
- genericArgs .OutputPackagePath = filepath .Join (root .PkgPath , importPathSuffix )
201
170
genericArgs .GoHeaderFilePath = ctx .HeaderFilePath
202
171
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
+
203
185
// Make the generated header static so that it doesn't rely on the compiled binary name.
204
186
genericArgs .GeneratedByCommentTemplate = "// Code generated by applyconfiguration-gen. DO NOT EDIT.\n "
205
187
@@ -216,9 +198,9 @@ func (ctx *ObjectGenCtx) generateForPackage(root *loader.Package) error {
216
198
if err != nil {
217
199
return err
218
200
}
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
222
204
223
205
pkg , ok := c .Universe [root .PkgPath ]
224
206
if ! ok {
0 commit comments