Skip to content

Commit

Permalink
Update based on feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
Jefftree committed May 4, 2021
1 parent 02d8008 commit a299774
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 10,209 deletions.
102 changes: 65 additions & 37 deletions pkg/applyconfigurations/gen.go
Expand Up @@ -24,7 +24,6 @@ import (
"go/types"
"io"
"path/filepath"
"regexp"
"sort"
"strings"

Expand All @@ -37,12 +36,16 @@ import (
// Based on deepcopy gen but with legacy marker support removed.

var (

enablePkgMarker = markers.Must(markers.MakeDefinition("kubebuilder:ac:generate", markers.DescribesPackage, false))
enableTypeMarker = markers.Must(markers.MakeDefinition("kubebuilder:ac:generate", markers.DescribesType, false))
isObjectMarker = markers.Must(markers.MakeDefinition("kubebuilder:ac:root", markers.DescribesType, false))
)

var importMapping = map[string]string{"k8s.io/apimachinery/pkg/apis/": "k8s.io/client-go/applyconfigurations/", "k8s.io/api/": "k8s.io/client-go/applyconfigurations/"}

const importPathSuffix = "ac"
const packageFileName = "zz_generated.applyconfigurations.go"

// +controllertools:marker:generateHelp

// Generator generates code containing apply configuration type implementations.
Expand Down Expand Up @@ -108,18 +111,29 @@ func groupAndPackageVersion(pkg string) string {
return parts[len(parts)-2] + "/" + parts[len(parts)-1]
}

func createApplyConfigPackage(universe Universe, pkg *loader.Package) *loader.Package {
func createApplyConfigPackage(universe *Universe, pkg *loader.Package) *loader.Package {
newPkg := &loader.Package{Package: &packages.Package{}}

if filepath.Dir(pkg.CompiledGoFiles[0]) == universe.baseFilePath {
newPkg.CompiledGoFiles = append(newPkg.CompiledGoFiles, universe.baseFilePath+"/"+universe.importPathSuffix+"/")
newPkg.CompiledGoFiles = append(newPkg.CompiledGoFiles, universe.baseFilePath+"/"+importPathSuffix+"/")
} else {
desiredPath := universe.baseFilePath + "/" + universe.importPathSuffix + "/" + groupAndPackageVersion(pkg.PkgPath) + "/"
desiredPath := universe.baseFilePath + "/" + importPathSuffix + "/" + groupAndPackageVersion(pkg.PkgPath) + "/"
newPkg.CompiledGoFiles = append(newPkg.CompiledGoFiles, desiredPath)
}
return newPkg
}

type PkgInfo struct {
objGenCtx *ObjectGenCtx
pkg *loader.Package
used bool
typeInfo []types.Type
}

func (p *PkgInfo) GenerateTypes() {
p.typeInfo = p.objGenCtx.generateEligibleTypes(p.pkg)
}

func (d Generator) Generate(ctx *genall.GenerationContext) error {
var headerText string

Expand All @@ -139,50 +153,55 @@ func (d Generator) Generate(ctx *genall.GenerationContext) error {
}

var pkgList []*loader.Package
var generatedList []*loader.Package

//TODO|jefftree: This might cause problems if multiple packages are provided
crdRoot := ctx.Roots[0]

for _, root := range ctx.Roots {
pkgList = append(pkgList, root)
generatedList = append(generatedList, root)
}

visited := make(map[string]*loader.Package)
visited := make(map[string]*PkgInfo)
for len(pkgList) != 0 {
pkg := pkgList[0]
pkgList = pkgList[1:]
if _, ok := visited[pkg.PkgPath]; ok {
continue
}

visited[pkg.PkgPath] = pkg
importPkgInfo := &PkgInfo{
objGenCtx: &objGenCtx,
pkg: pkg,
used: false,
}

visited[pkg.PkgPath] = importPkgInfo

for _, imp := range pkg.Imports() {
// Only index k8s types
match, _ := regexp.MatchString("k8s.io/.*apis?/.+", imp.PkgPath)
if !match {
continue
}
pkgList = append(pkgList, imp)
}
}

var eligibleTypes []types.Type
for _, pkg := range visited {
eligibleTypes = append(eligibleTypes, objGenCtx.generateEligibleTypes(pkg)...)
eligibleTypes = append(eligibleTypes, objGenCtx.generateEligibleTypes(pkg.pkg)...)
}

universe := Universe{
eligibleTypes: eligibleTypes,
baseImportPath: crdRoot.PkgPath,
importPathSuffix: "ac",
baseFilePath: filepath.Dir(crdRoot.CompiledGoFiles[0]),
importMapping: map[string]string{"k8s.io/apimachinery/pkg/apis/meta/v1": "k8s.io/client-go/applyconfigurations/meta/v1", "k8s.io/api/core/v1": "k8s.io/client-go/applyconfigurations/core/v1"},
universe := &Universe{
eligibleTypes: eligibleTypes,
baseImportPath: crdRoot.PkgPath,
baseFilePath: filepath.Dir(crdRoot.CompiledGoFiles[0]),
importMapping: importMapping,
visited: visited,
crawlPaths: generatedList,
}

// universe.baseImportPath = "k8s.io/client-go/applyconfigurations"
for len(universe.crawlPaths) != 0 {
pkg := universe.crawlPaths[0]
universe.crawlPaths = universe.crawlPaths[1:]

for _, pkg := range visited {
outContents := objGenCtx.generateForPackage(universe, pkg)
if outContents == nil {
continue
Expand Down Expand Up @@ -247,40 +266,49 @@ type Universe struct {
baseImportPath string
importPathSuffix string
baseFilePath string
importMapping map[string]string
importMapping map[string]string
visited map[string]*PkgInfo
crawlPaths []*loader.Package
}

func (u *Universe) existingApplyConfig(typeInfo *types.Named, pkgPath string) (string, bool) {
if path, ok := u.importMapping[pkgPath]; ok {
return path, true
for prefix, replacePath := range u.importMapping {
if strings.HasPrefix(pkgPath, prefix) {
path := replacePath + strings.TrimPrefix(pkgPath, prefix)
return path, true
}
}
return "", false
}

func (u *Universe) IsApplyConfigGenerated(typeInfo *types.Named, pkgPath string) bool {
exists := false
for _, b := range u.eligibleTypes {
if typeInfo.Obj().Name() == "ObjectMeta" || typeInfo.Obj().Name() == "TypeMeta" || typeInfo.Obj().Name() == "ListMeta" {
exists = false
break
}
if b == typeInfo {
exists = true

if _, ok := u.visited[pkgPath]; ok {
if u.visited[pkgPath].used == false {
u.visited[pkgPath].used = true
u.crawlPaths = append(u.crawlPaths, u.visited[pkgPath].pkg)
}
}

break
}
}
return exists
}

func (u *Universe) GetApplyConfigPath(typeInfo *types.Named, pkgPath string) (string, bool) {
if !u.IsApplyConfigGenerated(typeInfo, pkgPath) {
return pkgPath, false
}

if path, ok := u.existingApplyConfig(typeInfo, pkgPath); ok {
return path, ok
}

if !u.IsApplyConfigGenerated(typeInfo, pkgPath) {
return pkgPath, false
}

path := loader.NonVendorPath(pkgPath)
path = groupAndPackageVersion(path)
return u.baseImportPath + "/" + u.importPathSuffix + "/" + path, true
Expand All @@ -289,7 +317,7 @@ func (u *Universe) GetApplyConfigPath(typeInfo *types.Named, pkgPath string) (st
// generateForPackage generates apply configuration implementations for
// types in the given package, writing the formatted result to given writer.
// May return nil if source could not be generated.
func (ctx *ObjectGenCtx) generateForPackage(universe Universe, root *loader.Package) []byte {
func (ctx *ObjectGenCtx) generateForPackage(universe *Universe, root *loader.Package) []byte {
byType := make(map[string][]byte)
imports := &importsList{
byPath: make(map[string]string),
Expand All @@ -313,17 +341,17 @@ func (ctx *ObjectGenCtx) generateForPackage(universe Universe, root *loader.Pack
codeWriter: &codeWriter{out: outContent},
}

copyCtx.GenerateTypesFor(&universe, root, info)
copyCtx.GenerateTypesFor(universe, root, info)
for _, field := range info.Fields {
if field.Name != "" {
copyCtx.GenerateMemberSet(&universe, field, root, info)
copyCtx.GenerateMemberSet(universe, field, root, info)
}
}

copyCtx.GenerateStructConstructor(root, info)

if isRootType(info) {
copyCtx.GenerateTypeGetter(&universe, root, info)
copyCtx.GenerateRootFunctions(universe, root, info)
}

outBytes := outContent.Bytes()
Expand Down Expand Up @@ -374,7 +402,7 @@ func writeTypes(pkg *loader.Package, out io.Writer, byType map[string][]byte) {
// writeFormatted outputs the given code, after gofmt-ing it. If we couldn't gofmt,
// we write the unformatted code for debugging purposes.
func writeOut(ctx *genall.GenerationContext, root *loader.Package, outBytes []byte) {
outputFile, err := ctx.Open(root, "zz_generated.applyconfigurations.go")
outputFile, err := ctx.Open(root, packageFileName)
if err != nil {
root.AddError(err)
return
Expand Down

0 comments on commit a299774

Please sign in to comment.