@@ -24,7 +24,6 @@ import (
2424 "go/types"
2525 "io"
2626 "path/filepath"
27- "regexp"
2827 "sort"
2928 "strings"
3029
@@ -37,11 +36,19 @@ import (
3736// Based on deepcopy gen but with legacy marker support removed.
3837
3938var (
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 ))
4342)
4443
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+
4552// +controllertools:marker:generateHelp
4653
4754// Generator generates code containing apply configuration type implementations.
@@ -102,21 +109,23 @@ func genObjectInterface(info *markers.TypeInfo) bool {
102109 return false
103110}
104111
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
108118}
109119
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+ }
112126
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 )
120129}
121130
122131func (d Generator ) Generate (ctx * genall.GenerationContext ) error {
@@ -140,29 +149,17 @@ func (d Generator) Generate(ctx *genall.GenerationContext) error {
140149 var pkgList []* loader.Package
141150 visited := make (map [string ]* loader.Package )
142151
143- //TODO|jefftree: This might cause problems if multiple packages are provided
144- crdRoot := ctx .Roots [0 ]
145-
146152 for _ , root := range ctx .Roots {
153+ visited [root .PkgPath ] = root
147154 pkgList = append (pkgList , root )
148155 }
149156
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 {
159158 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 {
163160 continue
164161 }
165- pkgList = append ( pkgList , imp )
162+ visited [ imp . PkgPath ] = imp
166163 }
167164 }
168165
@@ -171,21 +168,15 @@ func (d Generator) Generate(ctx *genall.GenerationContext) error {
171168 eligibleTypes = append (eligibleTypes , objGenCtx .generateEligibleTypes (pkg )... )
172169 }
173170
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 ,
179173 }
180174
181- // universe.baseImportPath = "k8s.io/client-go/applyconfigurations"
182-
183- for _ , pkg := range visited {
175+ for _ , pkg := range pkgList {
184176 outContents := objGenCtx .generateForPackage (universe , pkg )
185177 if outContents == nil {
186178 continue
187179 }
188-
189180 newPkg := createApplyConfigPackage (universe , pkg )
190181 writeOut (ctx , newPkg , outContents )
191182 }
@@ -242,15 +233,49 @@ func (ctx *ObjectGenCtx) generateEligibleTypes(root *loader.Package) []types.Typ
242233
243234type Universe struct {
244235 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
248273}
249274
250275// generateForPackage generates apply configuration implementations for
251276// types in the given package, writing the formatted result to given writer.
252277// 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 {
254279 byType := make (map [string ][]byte )
255280 imports := & importsList {
256281 byPath : make (map [string ]string ),
@@ -274,17 +299,17 @@ func (ctx *ObjectGenCtx) generateForPackage(universe Universe, root *loader.Pack
274299 codeWriter : & codeWriter {out : outContent },
275300 }
276301
277- copyCtx .GenerateTypesFor (& universe , root , info )
302+ copyCtx .GenerateTypesFor (universe , root , info )
278303 for _ , field := range info .Fields {
279304 if field .Name != "" {
280- copyCtx .GenerateMemberSet (& universe , field , root , info )
305+ copyCtx .GenerateMemberSet (universe , field , root , info )
281306 }
282307 }
283308
284309 copyCtx .GenerateStructConstructor (root , info )
285310
286311 if isRootType (info ) {
287- copyCtx .GenerateTypeGetter ( & universe , root , info )
312+ copyCtx .GenerateRootFunctions ( universe , root , info )
288313 }
289314
290315 outBytes := outContent .Bytes ()
@@ -335,7 +360,7 @@ func writeTypes(pkg *loader.Package, out io.Writer, byType map[string][]byte) {
335360// writeFormatted outputs the given code, after gofmt-ing it. If we couldn't gofmt,
336361// we write the unformatted code for debugging purposes.
337362func 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 )
339364 if err != nil {
340365 root .AddError (err )
341366 return
0 commit comments