@@ -24,7 +24,6 @@ import (
24
24
"go/types"
25
25
"io"
26
26
"path/filepath"
27
- "regexp"
28
27
"sort"
29
28
"strings"
30
29
@@ -37,11 +36,19 @@ import (
37
36
// Based on deepcopy gen but with legacy marker support removed.
38
37
39
38
var (
40
- enablePkgMarker = markers .Must (markers .MakeDefinition ("kubebuilder:object :generate" , markers .DescribesPackage , false ))
41
- enableTypeMarker = markers .Must (markers .MakeDefinition ("kubebuilder:object :generate" , markers .DescribesType , false ))
42
- isObjectMarker = markers .Must (markers .MakeDefinition ("kubebuilder:object :root" , markers .DescribesType , false ))
39
+ enablePkgMarker = markers .Must (markers .MakeDefinition ("kubebuilder:ac :generate" , markers .DescribesPackage , false ))
40
+ enableTypeMarker = markers .Must (markers .MakeDefinition ("kubebuilder:ac :generate" , markers .DescribesType , false ))
41
+ isObjectMarker = markers .Must (markers .MakeDefinition ("kubebuilder:ac :root" , markers .DescribesType , false ))
43
42
)
44
43
44
+ var importMapping = map [string ]string {
45
+ "k8s.io/apimachinery/pkg/apis/" : "k8s.io/client-go/applyconfigurations/" ,
46
+ "k8s.io/api/" : "k8s.io/client-go/applyconfigurations/" ,
47
+ }
48
+
49
+ const importPathSuffix = "ac"
50
+ const packageFileName = "zz_generated.applyconfigurations.go"
51
+
45
52
// +controllertools:marker:generateHelp
46
53
47
54
// Generator generates code containing apply configuration type implementations.
@@ -102,21 +109,23 @@ func genObjectInterface(info *markers.TypeInfo) bool {
102
109
return false
103
110
}
104
111
105
- func groupAndPackageVersion (pkg string ) string {
106
- parts := strings .Split (pkg , "/" )
107
- return parts [len (parts )- 2 ] + "/" + parts [len (parts )- 1 ]
112
+ func createApplyConfigPackage (universe * Universe , pkg * loader.Package ) * loader.Package {
113
+ newPkg := & loader.Package {Package : & packages.Package {}}
114
+ dir := filepath .Dir (pkg .CompiledGoFiles [0 ])
115
+ // TODO|jefftree: This forces the package to live in a new "ac" directory. Is this code the best way to accomplish the task?
116
+ newPkg .CompiledGoFiles = append (newPkg .CompiledGoFiles , dir + "/" + importPathSuffix + "/" )
117
+ return newPkg
108
118
}
109
119
110
- func createApplyConfigPackage (universe Universe , pkg * loader.Package ) * loader.Package {
111
- newPkg := & loader.Package {Package : & packages.Package {}}
120
+ type PkgInfo struct {
121
+ objGenCtx * ObjectGenCtx
122
+ pkg * loader.Package
123
+ used bool
124
+ typeInfo []types.Type
125
+ }
112
126
113
- if filepath .Dir (pkg .CompiledGoFiles [0 ]) == universe .baseFilePath {
114
- newPkg .CompiledGoFiles = append (newPkg .CompiledGoFiles , universe .baseFilePath + "/" + universe .importPathSuffix + "/" )
115
- } else {
116
- desiredPath := universe .baseFilePath + "/" + universe .importPathSuffix + "/" + groupAndPackageVersion (pkg .PkgPath ) + "/"
117
- newPkg .CompiledGoFiles = append (newPkg .CompiledGoFiles , desiredPath )
118
- }
119
- return newPkg
127
+ func (p * PkgInfo ) GenerateTypes () {
128
+ p .typeInfo = p .objGenCtx .generateEligibleTypes (p .pkg )
120
129
}
121
130
122
131
func (d Generator ) Generate (ctx * genall.GenerationContext ) error {
@@ -140,29 +149,17 @@ func (d Generator) Generate(ctx *genall.GenerationContext) error {
140
149
var pkgList []* loader.Package
141
150
visited := make (map [string ]* loader.Package )
142
151
143
- //TODO|jefftree: This might cause problems if multiple packages are provided
144
- crdRoot := ctx .Roots [0 ]
145
-
146
152
for _ , root := range ctx .Roots {
153
+ visited [root .PkgPath ] = root
147
154
pkgList = append (pkgList , root )
148
155
}
149
156
150
- for len (pkgList ) != 0 {
151
- pkg := pkgList [0 ]
152
- pkgList = pkgList [1 :]
153
- if _ , ok := visited [pkg .PkgPath ]; ok {
154
- continue
155
- }
156
-
157
- visited [pkg .PkgPath ] = pkg
158
-
157
+ for _ , pkg := range pkgList {
159
158
for _ , imp := range pkg .Imports () {
160
- // Only index k8s types
161
- match , _ := regexp .MatchString ("k8s.io/.*apis?/.+" , imp .PkgPath )
162
- if ! match {
159
+ if _ , ok := visited [imp .PkgPath ]; ok {
163
160
continue
164
161
}
165
- pkgList = append ( pkgList , imp )
162
+ visited [ imp . PkgPath ] = imp
166
163
}
167
164
}
168
165
@@ -171,21 +168,15 @@ func (d Generator) Generate(ctx *genall.GenerationContext) error {
171
168
eligibleTypes = append (eligibleTypes , objGenCtx .generateEligibleTypes (pkg )... )
172
169
}
173
170
174
- universe := Universe {
175
- eligibleTypes : eligibleTypes ,
176
- baseImportPath : crdRoot .PkgPath ,
177
- importPathSuffix : "ac" ,
178
- baseFilePath : filepath .Dir (crdRoot .CompiledGoFiles [0 ]),
171
+ universe := & Universe {
172
+ eligibleTypes : eligibleTypes ,
179
173
}
180
174
181
- // universe.baseImportPath = "k8s.io/client-go/applyconfigurations"
182
-
183
- for _ , pkg := range visited {
175
+ for _ , pkg := range pkgList {
184
176
outContents := objGenCtx .generateForPackage (universe , pkg )
185
177
if outContents == nil {
186
178
continue
187
179
}
188
-
189
180
newPkg := createApplyConfigPackage (universe , pkg )
190
181
writeOut (ctx , newPkg , outContents )
191
182
}
@@ -242,15 +233,49 @@ func (ctx *ObjectGenCtx) generateEligibleTypes(root *loader.Package) []types.Typ
242
233
243
234
type Universe struct {
244
235
eligibleTypes []types.Type
245
- baseImportPath string
246
- importPathSuffix string
247
- baseFilePath string
236
+ }
237
+
238
+ func (u * Universe ) existingApplyConfig (typeInfo * types.Named , pkgPath string ) (string , bool ) {
239
+ for prefix , replacePath := range importMapping {
240
+ if strings .HasPrefix (pkgPath , prefix ) {
241
+ path := replacePath + strings .TrimPrefix (pkgPath , prefix )
242
+ return path , true
243
+ }
244
+ }
245
+ return "" , false
246
+ }
247
+
248
+ func (u * Universe ) IsApplyConfigGenerated (typeInfo * types.Named , pkgPath string ) bool {
249
+ exists := false
250
+ for _ , b := range u .eligibleTypes {
251
+ if b == typeInfo {
252
+ exists = true
253
+ break
254
+ }
255
+ }
256
+ return exists
257
+ }
258
+
259
+ func (u * Universe ) GetApplyConfigPath (typeInfo * types.Named , pkgPath string ) (string , bool ) {
260
+ isApplyConfigGenerated := u .IsApplyConfigGenerated (typeInfo , pkgPath )
261
+ if path , ok := u .existingApplyConfig (typeInfo , pkgPath ); ok {
262
+ if isApplyConfigGenerated {
263
+ return path , true
264
+ } else {
265
+ return pkgPath , false
266
+ }
267
+ }
268
+ // ApplyConfig is necessary but location is not explicitly specified. Assume the ApplyConfig exists at the below directory
269
+ if isApplyConfigGenerated {
270
+ return pkgPath + "/" + importPathSuffix , true
271
+ }
272
+ return pkgPath , false
248
273
}
249
274
250
275
// generateForPackage generates apply configuration implementations for
251
276
// types in the given package, writing the formatted result to given writer.
252
277
// May return nil if source could not be generated.
253
- func (ctx * ObjectGenCtx ) generateForPackage (universe Universe , root * loader.Package ) []byte {
278
+ func (ctx * ObjectGenCtx ) generateForPackage (universe * Universe , root * loader.Package ) []byte {
254
279
byType := make (map [string ][]byte )
255
280
imports := & importsList {
256
281
byPath : make (map [string ]string ),
@@ -274,17 +299,17 @@ func (ctx *ObjectGenCtx) generateForPackage(universe Universe, root *loader.Pack
274
299
codeWriter : & codeWriter {out : outContent },
275
300
}
276
301
277
- copyCtx .GenerateTypesFor (& universe , root , info )
302
+ copyCtx .GenerateTypesFor (universe , root , info )
278
303
for _ , field := range info .Fields {
279
304
if field .Name != "" {
280
- copyCtx .GenerateMemberSet (& universe , field , root , info )
305
+ copyCtx .GenerateMemberSet (universe , field , root , info )
281
306
}
282
307
}
283
308
284
309
copyCtx .GenerateStructConstructor (root , info )
285
310
286
311
if isRootType (info ) {
287
- copyCtx .GenerateTypeGetter ( & universe , root , info )
312
+ copyCtx .GenerateRootFunctions ( universe , root , info )
288
313
}
289
314
290
315
outBytes := outContent .Bytes ()
@@ -335,7 +360,7 @@ func writeTypes(pkg *loader.Package, out io.Writer, byType map[string][]byte) {
335
360
// writeFormatted outputs the given code, after gofmt-ing it. If we couldn't gofmt,
336
361
// we write the unformatted code for debugging purposes.
337
362
func writeOut (ctx * genall.GenerationContext , root * loader.Package , outBytes []byte ) {
338
- outputFile , err := ctx .Open (root , "zz_generated.applyconfigurations.go" )
363
+ outputFile , err := ctx .Open (root , packageFileName )
339
364
if err != nil {
340
365
root .AddError (err )
341
366
return
0 commit comments