From 5ddd6772a4cbd1ab9db1b3eaaa090349327c3d72 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Thu, 21 Dec 2023 11:58:42 -0800 Subject: [PATCH] Fix applyconfiguration-gen wrt gengo/v2 --- .../cmd/applyconfiguration-gen/args/args.go | 21 +++--- .../generators/applyconfiguration.go | 20 +++--- .../generators/packages.go | 69 ++++++++++++------- 3 files changed, 67 insertions(+), 43 deletions(-) diff --git a/staging/src/k8s.io/code-generator/cmd/applyconfiguration-gen/args/args.go b/staging/src/k8s.io/code-generator/cmd/applyconfiguration-gen/args/args.go index f7ff8bda0f1..28a71092805 100644 --- a/staging/src/k8s.io/code-generator/cmd/applyconfiguration-gen/args/args.go +++ b/staging/src/k8s.io/code-generator/cmd/applyconfiguration-gen/args/args.go @@ -18,17 +18,16 @@ package args import ( "fmt" - "path" "github.com/spf13/pflag" "k8s.io/gengo/v2/args" "k8s.io/gengo/v2/types" - - codegenutil "k8s.io/code-generator/pkg/util" ) // CustomArgs is a wrapper for arguments to applyconfiguration-gen. type CustomArgs struct { + OutputPackage string // must be a Go import-path + // ExternalApplyConfigurations provides the locations of externally generated // apply configuration types for types referenced by the go structs provided as input. // Locations are provided as a comma separated list of .: @@ -62,14 +61,11 @@ func NewDefaults() (*args.GeneratorArgs, *CustomArgs) { } genericArgs.CustomArgs = customArgs - if pkg := codegenutil.CurrentPackage(); len(pkg) != 0 { - genericArgs.OutputPackagePath = path.Join(pkg, "pkg/client/applyconfigurations") - } - return genericArgs, customArgs } func (ca *CustomArgs) AddFlags(fs *pflag.FlagSet, inputBase string) { + fs.StringVar(&ca.OutputPackage, "output-package", ca.OutputPackage, "the Go import-path of the generated results") fs.Var(NewExternalApplyConfigurationValue(&ca.ExternalApplyConfigurations, nil), "external-applyconfigurations", "list of comma separated external apply configurations locations in .: form."+ "For example: k8s.io/api/apps/v1.Deployment:k8s.io/client-go/applyconfigurations/apps/v1") @@ -79,8 +75,15 @@ func (ca *CustomArgs) AddFlags(fs *pflag.FlagSet, inputBase string) { // Validate checks the given arguments. func Validate(genericArgs *args.GeneratorArgs) error { - if len(genericArgs.OutputPackagePath) == 0 { - return fmt.Errorf("output package cannot be empty") + if len(genericArgs.OutputBase) == 0 { + return fmt.Errorf("--output-base must be specified") } + + customArgs := genericArgs.CustomArgs.(*CustomArgs) + + if len(customArgs.OutputPackage) == 0 { + return fmt.Errorf("--output-package must be specified") + } + return nil } diff --git a/staging/src/k8s.io/code-generator/cmd/applyconfiguration-gen/generators/applyconfiguration.go b/staging/src/k8s.io/code-generator/cmd/applyconfiguration-gen/generators/applyconfiguration.go index 9ce8c0fa63e..3051435a23a 100644 --- a/staging/src/k8s.io/code-generator/cmd/applyconfiguration-gen/generators/applyconfiguration.go +++ b/staging/src/k8s.io/code-generator/cmd/applyconfiguration-gen/generators/applyconfiguration.go @@ -18,6 +18,7 @@ package generators import ( "io" + "path/filepath" "strings" "k8s.io/gengo/v2/generator" @@ -32,13 +33,13 @@ import ( // applyConfigurationGenerator produces apply configurations for a given GroupVersion and type. type applyConfigurationGenerator struct { generator.DefaultGen - outputPackage string - localPackage types.Name - groupVersion clientgentypes.GroupVersion - applyConfig applyConfig - imports namer.ImportTracker - refGraph refGraph - openAPIType *string // if absent, extraction function cannot be generated + // outPkgBase is the base package, under which the "internal" and GV-specific subdirs live + outPkgBase string // must be a Go import-path + groupVersion clientgentypes.GroupVersion + applyConfig applyConfig + imports namer.ImportTracker + refGraph refGraph + openAPIType *string // if absent, extraction function cannot be generated } var _ generator.Generator = &applyConfigurationGenerator{} @@ -48,8 +49,9 @@ func (g *applyConfigurationGenerator) Filter(_ *generator.Context, t *types.Type } func (g *applyConfigurationGenerator) Namers(*generator.Context) namer.NameSystems { + localPkg := filepath.Join(g.outPkgBase, g.groupVersion.Group.PackageName(), g.groupVersion.Version.PackageName()) return namer.NameSystems{ - "raw": namer.NewRawNamer(g.localPackage.Package, g.imports), + "raw": namer.NewRawNamer(localPkg, g.imports), "singularKind": namer.NewPublicNamer(0), } } @@ -90,7 +92,7 @@ func (g *applyConfigurationGenerator) GenerateType(c *generator.Context, t *type Tags: genclientTags(t), APIVersion: g.groupVersion.ToAPIVersion(), ExtractInto: extractInto, - ParserFunc: types.Ref(g.outputPackage+"/internal", "Parser"), + ParserFunc: types.Ref(filepath.Join(g.outPkgBase, "internal"), "Parser"), OpenAPIType: g.openAPIType, } diff --git a/staging/src/k8s.io/code-generator/cmd/applyconfiguration-gen/generators/packages.go b/staging/src/k8s.io/code-generator/cmd/applyconfiguration-gen/generators/packages.go index 8440ed75a79..e5bb2fae301 100644 --- a/staging/src/k8s.io/code-generator/cmd/applyconfiguration-gen/generators/packages.go +++ b/staging/src/k8s.io/code-generator/cmd/applyconfiguration-gen/generators/packages.go @@ -61,8 +61,9 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat klog.Fatalf("Failed loading boilerplate: %v", err) } - pkgTypes := packageTypesForInputDirs(context, arguments.InputDirs, arguments.OutputPackagePath) customArgs := arguments.CustomArgs.(*applygenargs.CustomArgs) + + pkgTypes := packageTypesForInputDirs(context, arguments.InputDirs, customArgs.OutputPackage) initialTypes := customArgs.ExternalApplyConfigurations refs := refGraphForReachableTypes(context.Universe, pkgTypes, initialTypes) typeModels, err := newTypeModels(customArgs.OpenAPISchemaFilePath, pkgTypes) @@ -78,8 +79,6 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat for pkg, p := range pkgTypes { gv := groupVersion(p) - pkgType := types.Name{Name: gv.Group.PackageName(), Package: pkg} - var toGenerate []applyConfig for _, t := range p.Types { // If we don't have an ObjectMeta field, we lack the information required to make the Apply or ApplyStatus call @@ -101,8 +100,17 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat } sort.Sort(applyConfigSort(toGenerate)) + // Apparently we allow the groupName to be overridden in a way that it + // no longer maps to a Go package by name. So we have to figure out + // the offset of this particular output package (pkg) from the base + // output package (customArgs.OutputPackage). + pkgSubdir := strings.TrimPrefix(pkg, customArgs.OutputPackage+"/") + // generate the apply configurations - packageList = append(packageList, generatorForApplyConfigurationsPackage(arguments.OutputPackagePath, boilerplate, pkgType, gv, toGenerate, refs, typeModels)) + packageList = append(packageList, + generatorForApplyConfigurationsPackage( + arguments.OutputBase, customArgs.OutputPackage, pkgSubdir, + boilerplate, gv, toGenerate, refs, typeModels)) // group all the generated apply configurations by gv so ForKind() can be generated groupPackageName := gv.Group.NonEmpty() @@ -124,9 +132,13 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat } // generate ForKind() utility function - packageList = append(packageList, generatorForUtils(arguments.OutputPackagePath, boilerplate, groupVersions, applyConfigsForGroupVersion, groupGoNames)) + packageList = append(packageList, + generatorForUtils(arguments.OutputBase, customArgs.OutputPackage, + boilerplate, groupVersions, applyConfigsForGroupVersion, groupGoNames)) // generate internal embedded schema, required for generated Extract functions - packageList = append(packageList, generatorForInternal(filepath.Join(arguments.OutputPackagePath, "internal"), boilerplate, typeModels)) + packageList = append(packageList, + generatorForInternal(arguments.OutputBase, customArgs.OutputPackage, + boilerplate, typeModels)) return packageList } @@ -152,10 +164,14 @@ func typeName(t *types.Type) string { return fmt.Sprintf("%s.%s", typePackage, t.Name.Name) } -func generatorForApplyConfigurationsPackage(outputPackagePath string, boilerplate []byte, packageName types.Name, gv clientgentypes.GroupVersion, typesToGenerate []applyConfig, refs refGraph, models *typeModels) *generator.DefaultPackage { +func generatorForApplyConfigurationsPackage(outputDirBase, outputPkgBase, pkgSubdir string, boilerplate []byte, gv clientgentypes.GroupVersion, typesToGenerate []applyConfig, refs refGraph, models *typeModels) *generator.DefaultPackage { + outputDir := filepath.Join(outputDirBase, pkgSubdir) + outputPkg := filepath.Join(outputPkgBase, pkgSubdir) + return &generator.DefaultPackage{ PackageName: gv.Version.PackageName(), - PackagePath: packageName.Package, + PackagePath: outputPkg, + Source: outputDir, HeaderText: boilerplate, GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { for _, toGenerate := range typesToGenerate { @@ -173,13 +189,12 @@ func generatorForApplyConfigurationsPackage(outputPackagePath string, boilerplat DefaultGen: generator.DefaultGen{ OptionalName: strings.ToLower(toGenerate.Type.Name.Name), }, - outputPackage: outputPackagePath, - localPackage: packageName, - groupVersion: gv, - applyConfig: toGenerate, - imports: generator.NewImportTracker(), - refGraph: refs, - openAPIType: openAPIType, + outPkgBase: outputPkgBase, + groupVersion: gv, + applyConfig: toGenerate, + imports: generator.NewImportTracker(), + refGraph: refs, + openAPIType: openAPIType, }) } return generators @@ -187,17 +202,18 @@ func generatorForApplyConfigurationsPackage(outputPackagePath string, boilerplat } } -func generatorForUtils(outPackagePath string, boilerplate []byte, groupVersions map[string]clientgentypes.GroupVersions, applyConfigsForGroupVersion map[clientgentypes.GroupVersion][]applyConfig, groupGoNames map[string]string) *generator.DefaultPackage { +func generatorForUtils(outputDirBase, outputPkgBase string, boilerplate []byte, groupVersions map[string]clientgentypes.GroupVersions, applyConfigsForGroupVersion map[clientgentypes.GroupVersion][]applyConfig, groupGoNames map[string]string) *generator.DefaultPackage { return &generator.DefaultPackage{ - PackageName: filepath.Base(outPackagePath), - PackagePath: outPackagePath, + PackageName: filepath.Base(outputPkgBase), + PackagePath: outputPkgBase, + Source: outputDirBase, HeaderText: boilerplate, GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { generators = append(generators, &utilGenerator{ DefaultGen: generator.DefaultGen{ OptionalName: "utils", }, - outputPackage: outPackagePath, + outputPackage: outputPkgBase, imports: generator.NewImportTracker(), groupVersions: groupVersions, typesForGroupVersion: applyConfigsForGroupVersion, @@ -208,17 +224,20 @@ func generatorForUtils(outPackagePath string, boilerplate []byte, groupVersions } } -func generatorForInternal(outPackagePath string, boilerplate []byte, models *typeModels) *generator.DefaultPackage { +func generatorForInternal(outputDirBase, outputPkgBase string, boilerplate []byte, models *typeModels) *generator.DefaultPackage { + outputDir := filepath.Join(outputDirBase, "internal") + outputPkg := filepath.Join(outputPkgBase, "internal") return &generator.DefaultPackage{ - PackageName: filepath.Base(outPackagePath), - PackagePath: outPackagePath, + PackageName: filepath.Base(outputPkg), + PackagePath: outputPkg, + Source: outputDir, HeaderText: boilerplate, GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { generators = append(generators, &internalGenerator{ DefaultGen: generator.DefaultGen{ OptionalName: "internal", }, - outputPackage: outPackagePath, + outputPackage: outputPkgBase, imports: generator.NewImportTracker(), typeModels: models, }) @@ -235,7 +254,7 @@ func goName(gv clientgentypes.GroupVersion, p *types.Package) string { return goName } -func packageTypesForInputDirs(context *generator.Context, inputDirs []string, outputPath string) map[string]*types.Package { +func packageTypesForInputDirs(context *generator.Context, inputDirs []string, outPkgBase string) map[string]*types.Package { pkgTypes := map[string]*types.Package{} for _, inputDir := range inputDirs { p := context.Universe.Package(inputDir) @@ -249,7 +268,7 @@ func packageTypesForInputDirs(context *generator.Context, inputDirs []string, ou // For example, if openshift/api/cloudnetwork/v1 contains an apigroup cloud.network.openshift.io, the client-gen // builds a package called cloudnetwork/v1 to contain it. This change makes the applyconfiguration-gen use the same. _, gvPackageString := util.ParsePathGroupVersion(p.Path) - pkg := filepath.Join(outputPath, strings.ToLower(gvPackageString)) + pkg := filepath.Join(outPkgBase, strings.ToLower(gvPackageString)) pkgTypes[pkg] = p } return pkgTypes