Fix client-gen wrt gengo/v2

This commit is contained in:
Tim Hockin 2023-12-21 13:13:42 -08:00
parent 130a9f8426
commit b961b39efa
No known key found for this signature in database
11 changed files with 122 additions and 73 deletions

View File

@ -18,19 +18,20 @@ package args
import (
"fmt"
"path"
"github.com/spf13/pflag"
"k8s.io/gengo/v2/args"
"k8s.io/code-generator/cmd/client-gen/types"
codegenutil "k8s.io/code-generator/pkg/util"
)
var DefaultInputDirs = []string{}
// CustomArgs is a wrapper for arguments to client-gen.
type CustomArgs struct {
// The Go import-path of the generated results.
OutputPackage string
// A sorted list of group versions to generate. For each of them the package path is found
// in GroupVersionToInputPath.
Groups []types.GroupVersions
@ -72,15 +73,12 @@ func NewDefaults() (*args.GeneratorArgs, *CustomArgs) {
genericArgs.CustomArgs = customArgs
genericArgs.InputDirs = DefaultInputDirs
if pkg := codegenutil.CurrentPackage(); len(pkg) != 0 {
genericArgs.OutputPackagePath = path.Join(pkg, "pkg/client/clientset")
}
return genericArgs, customArgs
}
func (ca *CustomArgs) AddFlags(fs *pflag.FlagSet, inputBase string) {
gvsBuilder := NewGroupVersionsBuilder(&ca.Groups)
fs.StringVar(&ca.OutputPackage, "output-package", ca.OutputPackage, "the Go import-path of the generated results")
fs.Var(NewGVPackagesValue(gvsBuilder, nil), "input", "group/versions that client-gen will generate clients for. At most one version per group is allowed. Specified in the format \"group1/version1,group2/version2...\".")
fs.Var(NewGVTypesValue(&ca.IncludedTypesOverrides, []string{}), "included-types-overrides", "list of group/version/type for which client should be generated. By default, client is generated for all types which have genclient in types.go. This overrides that. For each groupVersion in this list, only the types mentioned here will be included. The default check of genclient will be used for other group versions.")
fs.Var(NewInputBasePathValue(gvsBuilder, inputBase), "input-base", "base path to look for the api group.")
@ -97,16 +95,20 @@ func (ca *CustomArgs) AddFlags(fs *pflag.FlagSet, inputBase string) {
}
func Validate(genericArgs *args.GeneratorArgs) error {
if len(genericArgs.OutputBase) == 0 {
return fmt.Errorf("--output-base must be specified")
}
customArgs := genericArgs.CustomArgs.(*CustomArgs)
if len(genericArgs.OutputPackagePath) == 0 {
return fmt.Errorf("output package cannot be empty")
if len(customArgs.OutputPackage) == 0 {
return fmt.Errorf("--output-package must be specified")
}
if len(customArgs.ClientsetName) == 0 {
return fmt.Errorf("clientset name cannot be empty")
return fmt.Errorf("--clientset-name must be specified")
}
if len(customArgs.ClientsetAPIPath) == 0 {
return fmt.Errorf("clientset API path cannot be empty")
return fmt.Errorf("--clientset-api-path cannot be empty")
}
return nil

View File

@ -18,6 +18,7 @@ limitations under the License.
package generators
import (
"fmt"
"path/filepath"
"strings"
@ -128,11 +129,15 @@ func DefaultNameSystem() string {
return "public"
}
func packageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, clientsetPackage string, groupPackageName string, groupGoName string, apiPath string, srcTreePath string, inputPackage string, applyBuilderPackage string, boilerplate []byte) generator.Package {
groupVersionClientPackage := filepath.Join(clientsetPackage, "typed", strings.ToLower(groupPackageName), strings.ToLower(gv.Version.NonEmpty()))
func packageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, clientsetDir, clientsetPkg string, groupPkgName string, groupGoName string, apiPath string, inputPkg string, applyBuilderPkg string, boilerplate []byte) generator.Package {
subdir := filepath.Join("typed", strings.ToLower(groupPkgName), strings.ToLower(gv.Version.NonEmpty()))
gvDir := filepath.Join(clientsetDir, subdir)
gvPkg := filepath.Join(clientsetPkg, subdir)
return &generator.DefaultPackage{
PackageName: strings.ToLower(gv.Version.NonEmpty()),
PackagePath: groupVersionClientPackage,
PackagePath: gvPkg,
Source: gvDir,
HeaderText: boilerplate,
PackageDocumentation: []byte("// This package has the automatically generated typed clients.\n"),
// GeneratorFunc returns a list of generators. Each generator makes a
@ -149,10 +154,10 @@ func packageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, cli
DefaultGen: generator.DefaultGen{
OptionalName: strings.ToLower(c.Namers["private"].Name(t)),
},
outputPackage: groupVersionClientPackage,
inputPackage: inputPackage,
clientsetPackage: clientsetPackage,
applyConfigurationPackage: applyBuilderPackage,
outputPackage: gvPkg,
inputPackage: inputPkg,
clientsetPackage: clientsetPkg,
applyConfigurationPackage: applyBuilderPkg,
group: gv.Group.NonEmpty(),
version: gv.Version.String(),
groupGoName: groupGoName,
@ -163,11 +168,11 @@ func packageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, cli
generators = append(generators, &genGroup{
DefaultGen: generator.DefaultGen{
OptionalName: groupPackageName + "_client",
OptionalName: groupPkgName + "_client",
},
outputPackage: groupVersionClientPackage,
inputPackage: inputPackage,
clientsetPackage: clientsetPackage,
outputPackage: gvPkg,
inputPackage: inputPkg,
clientsetPackage: clientsetPkg,
group: gv.Group.NonEmpty(),
version: gv.Version.String(),
groupGoName: groupGoName,
@ -178,7 +183,7 @@ func packageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, cli
expansionFileName := "generated_expansion"
generators = append(generators, &genExpansion{
groupPackagePath: filepath.Join(srcTreePath, groupVersionClientPackage),
groupPackagePath: gvDir,
DefaultGen: generator.DefaultGen{
OptionalName: expansionFileName,
},
@ -193,10 +198,11 @@ func packageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, cli
}
}
func packageForClientset(customArgs *clientgenargs.CustomArgs, clientsetPackage string, groupGoNames map[clientgentypes.GroupVersion]string, boilerplate []byte) generator.Package {
func packageForClientset(customArgs *clientgenargs.CustomArgs, clientsetDir, clientsetPkg string, groupGoNames map[clientgentypes.GroupVersion]string, boilerplate []byte) generator.Package {
return &generator.DefaultPackage{
PackageName: customArgs.ClientsetName,
PackagePath: clientsetPackage,
PackagePath: clientsetPkg,
Source: clientsetDir,
HeaderText: boilerplate,
// GeneratorFunc returns a list of generators. Each generator generates a
// single file.
@ -208,8 +214,7 @@ func packageForClientset(customArgs *clientgenargs.CustomArgs, clientsetPackage
},
groups: customArgs.Groups,
groupGoNames: groupGoNames,
clientsetPackage: clientsetPackage,
outputPackage: customArgs.ClientsetName,
clientsetPackage: clientsetPkg,
imports: generator.NewImportTracker(),
},
}
@ -218,8 +223,9 @@ func packageForClientset(customArgs *clientgenargs.CustomArgs, clientsetPackage
}
}
func packageForScheme(customArgs *clientgenargs.CustomArgs, clientsetPackage string, srcTreePath string, groupGoNames map[clientgentypes.GroupVersion]string, boilerplate []byte) generator.Package {
schemePackage := filepath.Join(clientsetPackage, "scheme")
func packageForScheme(customArgs *clientgenargs.CustomArgs, clientsetDir, clientsetPkg string, groupGoNames map[clientgentypes.GroupVersion]string, boilerplate []byte) generator.Package {
schemeDir := filepath.Join(clientsetDir, "scheme")
schemePkg := filepath.Join(clientsetPkg, "scheme")
// create runtime.Registry for internal client because it has to know about group versions
internalClient := false
@ -235,7 +241,8 @@ NextGroup:
return &generator.DefaultPackage{
PackageName: "scheme",
PackagePath: schemePackage,
PackagePath: schemePkg,
Source: schemeDir,
HeaderText: boilerplate,
PackageDocumentation: []byte("// This package contains the scheme of the automatically generated clientset.\n"),
// GeneratorFunc returns a list of generators. Each generator generates a
@ -250,8 +257,8 @@ NextGroup:
OptionalName: "register",
},
InputPackages: customArgs.GroupVersionPackages(),
OutputPackage: schemePackage,
OutputPath: filepath.Join(srcTreePath, schemePackage),
OutputPackage: schemePkg,
OutputPath: schemeDir,
Groups: customArgs.Groups,
GroupGoNames: groupGoNames,
ImportTracker: generator.NewImportTracker(),
@ -305,6 +312,35 @@ func applyGroupOverrides(universe types.Universe, customArgs *clientgenargs.Cust
customArgs.Groups = newGroups
}
// Because we try to assemble inputs from an input-base and a set of
// group-version arguments, sometimes that comes in as a filesystem path. This
// function rewrites them all as their canonical Go import-paths.
//
// TODO: Change this tool to just take inputs as Go "patterns" like every other
// gengo tool, then extract GVs from those.
func sanitizePackagePaths(context *generator.Context, ca *clientgenargs.CustomArgs) error {
for i := range ca.Groups {
pkg := &ca.Groups[i]
for j := range pkg.Versions {
ver := &pkg.Versions[j]
input := ver.Package
p := context.Universe[path.Vendorless(input)]
if p == nil || p.Name == "" {
pkgs, err := context.FindPackages(input)
if err != nil {
return fmt.Errorf("can't find input package %q: %w", input, err)
}
p = context.Universe[pkgs[0]]
if p == nil {
return fmt.Errorf("can't find input package %q in universe", input)
}
ver.Package = p.Path
}
}
}
return nil
}
// Packages makes the client package definition.
func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
boilerplate, err := arguments.LoadGoBoilerplate()
@ -318,6 +354,9 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
}
includedTypesOverrides := customArgs.IncludedTypesOverrides
if err := sanitizePackagePaths(context, customArgs); err != nil {
klog.Fatalf("cannot sanitize inputs: %v", err)
}
applyGroupOverrides(context.Universe, customArgs)
gvToTypes := map[clientgentypes.GroupVersion][]*types.Type{}
@ -361,13 +400,18 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
}
}
var packageList []generator.Package
clientsetPackage := filepath.Join(arguments.OutputPackagePath, customArgs.ClientsetName)
clientsetDir := filepath.Join(arguments.OutputBase, customArgs.ClientsetName)
clientsetPkg := filepath.Join(customArgs.OutputPackage, customArgs.ClientsetName)
packageList = append(packageList, packageForClientset(customArgs, clientsetPackage, groupGoNames, boilerplate))
packageList = append(packageList, packageForScheme(customArgs, clientsetPackage, arguments.OutputBase, groupGoNames, boilerplate))
var packageList []generator.Package
packageList = append(packageList,
packageForClientset(customArgs, clientsetDir, clientsetPkg, groupGoNames, boilerplate))
packageList = append(packageList,
packageForScheme(customArgs, clientsetDir, clientsetPkg, groupGoNames, boilerplate))
if customArgs.FakeClient {
packageList = append(packageList, fake.PackageForClientset(customArgs, clientsetPackage, groupGoNames, boilerplate))
packageList = append(packageList,
fake.PackageForClientset(customArgs, clientsetDir, clientsetPkg, groupGoNames, boilerplate))
}
// If --clientset-only=true, we don't regenerate the individual typed clients.
@ -382,9 +426,14 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
gv := clientgentypes.GroupVersion{Group: group.Group, Version: version.Version}
types := gvToTypes[gv]
inputPath := gvPackages[gv]
packageList = append(packageList, packageForGroup(gv, orderer.OrderTypes(types), clientsetPackage, group.PackageName, groupGoNames[gv], customArgs.ClientsetAPIPath, arguments.OutputBase, inputPath, customArgs.ApplyConfigurationPackage, boilerplate))
packageList = append(packageList,
packageForGroup(
gv, orderer.OrderTypes(types), clientsetDir, clientsetPkg,
group.PackageName, groupGoNames[gv], customArgs.ClientsetAPIPath,
inputPath, customArgs.ApplyConfigurationPackage, boilerplate))
if customArgs.FakeClient {
packageList = append(packageList, fake.PackageForGroup(gv, orderer.OrderTypes(types), clientsetPackage, group.PackageName, groupGoNames[gv], inputPath, customArgs.ApplyConfigurationPackage, boilerplate))
packageList = append(packageList,
fake.PackageForGroup(gv, orderer.OrderTypes(types), clientsetDir, clientsetPkg, group.PackageName, groupGoNames[gv], inputPath, customArgs.ApplyConfigurationPackage, boilerplate))
}
}
}

View File

@ -29,13 +29,17 @@ import (
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
)
func PackageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, clientsetPackage string, groupPackageName string, groupGoName string, inputPackage string, applyBuilderPackage string, boilerplate []byte) generator.Package {
outputPackage := filepath.Join(clientsetPackage, "typed", strings.ToLower(groupPackageName), strings.ToLower(gv.Version.NonEmpty()), "fake")
func PackageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, clientsetDir, clientsetPkg string, groupPkgName string, groupGoName string, inputPkg string, applyBuilderPackage string, boilerplate []byte) generator.Package {
// TODO: should make this a function, called by here and in client-generator.go
realClientPackage := filepath.Join(clientsetPackage, "typed", strings.ToLower(groupPackageName), strings.ToLower(gv.Version.NonEmpty()))
subdir := filepath.Join("typed", strings.ToLower(groupPkgName), strings.ToLower(gv.Version.NonEmpty()))
outputDir := filepath.Join(clientsetDir, subdir, "fake")
outputPkg := filepath.Join(clientsetPkg, subdir, "fake")
realClientPkg := filepath.Join(clientsetPkg, subdir)
return &generator.DefaultPackage{
PackageName: "fake",
PackagePath: outputPackage,
PackagePath: outputPkg,
Source: outputDir,
HeaderText: boilerplate,
PackageDocumentation: []byte(
`// Package fake has the automatically generated clients.
@ -54,8 +58,8 @@ func PackageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, cli
DefaultGen: generator.DefaultGen{
OptionalName: "fake_" + strings.ToLower(c.Namers["private"].Name(t)),
},
outputPackage: outputPackage,
inputPackage: inputPackage,
outputPackage: outputPkg,
inputPackage: inputPkg,
group: gv.Group.NonEmpty(),
version: gv.Version.String(),
groupGoName: groupGoName,
@ -67,10 +71,10 @@ func PackageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, cli
generators = append(generators, &genFakeForGroup{
DefaultGen: generator.DefaultGen{
OptionalName: "fake_" + groupPackageName + "_client",
OptionalName: "fake_" + groupPkgName + "_client",
},
outputPackage: outputPackage,
realClientPackage: realClientPackage,
outputPackage: outputPkg,
realClientPackage: realClientPkg,
group: gv.Group.NonEmpty(),
version: gv.Version.String(),
groupGoName: groupGoName,
@ -85,12 +89,13 @@ func PackageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, cli
}
}
func PackageForClientset(customArgs *clientgenargs.CustomArgs, clientsetPackage string, groupGoNames map[clientgentypes.GroupVersion]string, boilerplate []byte) generator.Package {
func PackageForClientset(customArgs *clientgenargs.CustomArgs, clientsetDir, clientsetPkg string, groupGoNames map[clientgentypes.GroupVersion]string, boilerplate []byte) generator.Package {
return &generator.DefaultPackage{
// TODO: we'll generate fake clientset for different release in the future.
// Package name and path are hard coded for now.
PackageName: "fake",
PackagePath: filepath.Join(clientsetPackage, "fake"),
PackagePath: filepath.Join(clientsetPkg, "fake"),
Source: filepath.Join(clientsetDir, "fake"),
HeaderText: boilerplate,
PackageDocumentation: []byte(
`// This package has the automatically generated fake clientset.
@ -108,17 +113,16 @@ func PackageForClientset(customArgs *clientgenargs.CustomArgs, clientsetPackage
},
groups: customArgs.Groups,
groupGoNames: groupGoNames,
fakeClientsetPackage: clientsetPackage,
outputPackage: "fake",
fakeClientsetPackage: clientsetPkg,
imports: generator.NewImportTracker(),
realClientsetPackage: clientsetPackage,
realClientsetPackage: clientsetPkg,
},
&scheme.GenScheme{
DefaultGen: generator.DefaultGen{
OptionalName: "register",
},
InputPackages: customArgs.GroupVersionPackages(),
OutputPackage: clientsetPackage,
OutputPackage: clientsetPkg,
Groups: customArgs.Groups,
GroupGoNames: groupGoNames,
ImportTracker: generator.NewImportTracker(),

View File

@ -33,19 +33,18 @@ type genClientset struct {
generator.DefaultGen
groups []clientgentypes.GroupVersions
groupGoNames map[clientgentypes.GroupVersion]string
fakeClientsetPackage string
outputPackage string
fakeClientsetPackage string // must be a Go import-path
imports namer.ImportTracker
clientsetGenerated bool
// the import path of the generated real clientset.
realClientsetPackage string
realClientsetPackage string // must be a Go import-path
}
var _ generator.Generator = &genClientset{}
func (g *genClientset) Namers(c *generator.Context) namer.NameSystems {
return namer.NameSystems{
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
"raw": namer.NewRawNamer(g.fakeClientsetPackage, g.imports),
}
}

View File

@ -32,8 +32,8 @@ import (
// genFakeForGroup produces a file for a group client, e.g. ExtensionsClient for the extension group.
type genFakeForGroup struct {
generator.DefaultGen
outputPackage string
realClientPackage string
outputPackage string // must be a Go import-path
realClientPackage string // must be a Go import-path
group string
version string
groupGoName string

View File

@ -32,7 +32,7 @@ import (
// genFakeForType produces a file for each top-level type.
type genFakeForType struct {
generator.DefaultGen
outputPackage string
outputPackage string // Must be a Go import-path
group string
version string
groupGoName string

View File

@ -33,8 +33,7 @@ type genClientset struct {
generator.DefaultGen
groups []clientgentypes.GroupVersions
groupGoNames map[clientgentypes.GroupVersion]string
clientsetPackage string
outputPackage string
clientsetPackage string // must be a Go import-path
imports namer.ImportTracker
clientsetGenerated bool
}
@ -43,7 +42,7 @@ var _ generator.Generator = &genClientset{}
func (g *genClientset) Namers(c *generator.Context) namer.NameSystems {
return namer.NameSystems{
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
"raw": namer.NewRawNamer(g.clientsetPackage, g.imports),
}
}

View File

@ -40,7 +40,7 @@ type genGroup struct {
types []*types.Type
imports namer.ImportTracker
inputPackage string
clientsetPackage string
clientsetPackage string // must be a Go import-path
// If the genGroup has been called. This generator should only execute once.
called bool
}

View File

@ -32,10 +32,10 @@ import (
// genClientForType produces a file for each top-level type.
type genClientForType struct {
generator.DefaultGen
outputPackage string
outputPackage string // must be a Go import-path
inputPackage string
clientsetPackage string
applyConfigurationPackage string
clientsetPackage string // must be a Go import-path
applyConfigurationPackage string // must be a Go import-path
group string
version string
groupGoName string

View File

@ -33,11 +33,11 @@ import (
// GenScheme produces a package for a clientset with the scheme, codecs and parameter codecs.
type GenScheme struct {
generator.DefaultGen
OutputPackage string
OutputPackage string // Must be a Go import-path
OutputPath string // optional
Groups []clientgentypes.GroupVersions
GroupGoNames map[clientgentypes.GroupVersion]string
InputPackages map[clientgentypes.GroupVersion]string
OutputPath string
ImportTracker namer.ImportTracker
PrivateScheme bool
CreateRegistry bool

View File

@ -32,10 +32,6 @@ func main() {
klog.InitFlags(nil)
genericArgs, customArgs := generatorargs.NewDefaults()
// Override defaults.
// TODO: move this out of client-gen
genericArgs.OutputPackagePath = "k8s.io/kubernetes/pkg/client/clientset_generated/"
genericArgs.AddFlags(pflag.CommandLine)
customArgs.AddFlags(pflag.CommandLine, "k8s.io/kubernetes/pkg/apis") // TODO: move this input path out of client-gen
flag.Set("logtostderr", "true")