update dependencies (#6267)

Signed-off-by: hongming <coder.scala@gmail.com>
This commit is contained in:
hongming
2024-11-06 10:27:06 +08:00
committed by GitHub
parent faf255a084
commit cfebd96a1f
4263 changed files with 341374 additions and 132036 deletions

View File

@@ -18,19 +18,22 @@ package args
import (
"fmt"
"path"
"github.com/spf13/pflag"
"k8s.io/gengo/args"
"k8s.io/code-generator/cmd/client-gen/types"
codegenutil "k8s.io/code-generator/pkg/util"
)
var DefaultInputDirs = []string{}
type Args struct {
// The directory for the generated results.
OutputDir string
// The Go import-path of the generated results.
OutputPkg string
// The boilerplate header for Go files.
GoHeaderFile string
// CustomArgs is a wrapper for arguments to client-gen.
type CustomArgs struct {
// A sorted list of group versions to generate. For each of them the package path is found
// in GroupVersionToInputPath.
Groups []types.GroupVersions
@@ -53,69 +56,75 @@ type CustomArgs struct {
// For example 'Endpoints:Endpoints', otherwise the pluralizer will generate 'Endpointes'.
PluralExceptions []string
// ApplyConfigurationPackage is the package of apply builders generated by typebuilder-gen.
// ApplyConfigurationPackage is the package of apply builders generated by
// applyconfiguration-gen.
// If non-empty, Apply functions are generated for each type and reference the apply builders.
// If empty (""), Apply functions are not generated.
ApplyConfigurationPackage string
}
func NewDefaults() (*args.GeneratorArgs, *CustomArgs) {
genericArgs := args.Default().WithoutDefaultFlagParsing()
customArgs := &CustomArgs{
func New() *Args {
return &Args{
ClientsetName: "internalclientset",
ClientsetAPIPath: "/apis",
ClientsetOnly: false,
FakeClient: true,
PluralExceptions: []string{"Endpoints:Endpoints"},
ApplyConfigurationPackage: "",
}
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)
pflag.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...\".")
pflag.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.")
pflag.Var(NewInputBasePathValue(gvsBuilder, inputBase), "input-base", "base path to look for the api group.")
pflag.StringVarP(&ca.ClientsetName, "clientset-name", "n", ca.ClientsetName, "the name of the generated clientset package.")
pflag.StringVarP(&ca.ClientsetAPIPath, "clientset-api-path", "", ca.ClientsetAPIPath, "the value of default API HTTP path, starting with / and without trailing /.")
pflag.BoolVar(&ca.ClientsetOnly, "clientset-only", ca.ClientsetOnly, "when set, client-gen only generates the clientset shell, without generating the individual typed clients")
pflag.BoolVar(&ca.FakeClient, "fake-clientset", ca.FakeClient, "when set, client-gen will generate the fake clientset that can be used in tests")
fs.StringSliceVar(&ca.PluralExceptions, "plural-exceptions", ca.PluralExceptions, "list of comma separated plural exception definitions in Type:PluralizedType form")
fs.StringVar(&ca.ApplyConfigurationPackage, "apply-configuration-package", ca.ApplyConfigurationPackage, "optional package of apply configurations, generated by applyconfiguration-gen, that are required to generate Apply functions for each type in the clientset. By default Apply functions are not generated.")
func (args *Args) AddFlags(fs *pflag.FlagSet, inputBase string) {
gvsBuilder := NewGroupVersionsBuilder(&args.Groups)
fs.StringVar(&args.OutputDir, "output-dir", "",
"the base directory under which to generate results")
fs.StringVar(&args.OutputPkg, "output-pkg", args.OutputPkg,
"the Go import-path of the generated results")
fs.StringVar(&args.GoHeaderFile, "go-header-file", "",
"the path to a file containing boilerplate header text; the string \"YEAR\" will be replaced with the current 4-digit year")
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(&args.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.")
fs.StringVarP(&args.ClientsetName, "clientset-name", "n", args.ClientsetName,
"the name of the generated clientset package.")
fs.StringVarP(&args.ClientsetAPIPath, "clientset-api-path", "", args.ClientsetAPIPath,
"the value of default API HTTP path, starting with / and without trailing /.")
fs.BoolVar(&args.ClientsetOnly, "clientset-only", args.ClientsetOnly,
"when set, client-gen only generates the clientset shell, without generating the individual typed clients")
fs.BoolVar(&args.FakeClient, "fake-clientset", args.FakeClient,
"when set, client-gen will generate the fake clientset that can be used in tests")
fs.StringSliceVar(&args.PluralExceptions, "plural-exceptions", args.PluralExceptions,
"list of comma separated plural exception definitions in Type:PluralizedType form")
fs.StringVar(&args.ApplyConfigurationPackage, "apply-configuration-package", args.ApplyConfigurationPackage,
"optional package of apply configurations, generated by applyconfiguration-gen, that are required to generate Apply functions for each type in the clientset. By default Apply functions are not generated.")
// support old flags
fs.SetNormalizeFunc(mapFlagName("clientset-path", "output-package", fs.GetNormalizeFunc()))
fs.SetNormalizeFunc(mapFlagName("clientset-path", "output-pkg", fs.GetNormalizeFunc()))
}
func Validate(genericArgs *args.GeneratorArgs) error {
customArgs := genericArgs.CustomArgs.(*CustomArgs)
if len(genericArgs.OutputPackagePath) == 0 {
return fmt.Errorf("output package cannot be empty")
func (args *Args) Validate() error {
if len(args.OutputDir) == 0 {
return fmt.Errorf("--output-dir must be specified")
}
if len(customArgs.ClientsetName) == 0 {
return fmt.Errorf("clientset name cannot be empty")
if len(args.OutputPkg) == 0 {
return fmt.Errorf("--output-pkg must be specified")
}
if len(customArgs.ClientsetAPIPath) == 0 {
return fmt.Errorf("clientset API path cannot be empty")
if len(args.ClientsetName) == 0 {
return fmt.Errorf("--clientset-name must be specified")
}
if len(args.ClientsetAPIPath) == 0 {
return fmt.Errorf("--clientset-api-path cannot be empty")
}
return nil
}
// GroupVersionPackages returns a map from GroupVersion to the package with the types.go.
func (ca *CustomArgs) GroupVersionPackages() map[types.GroupVersion]string {
func (args *Args) GroupVersionPackages() map[types.GroupVersion]string {
res := map[types.GroupVersion]string{}
for _, pkg := range ca.Groups {
for _, pkg := range args.Groups {
for _, v := range pkg.Versions {
res[types.GroupVersion{Group: pkg.Group, Version: v.Version}] = v.Package
}

View File

@@ -129,7 +129,9 @@ func (p *groupVersionsBuilder) update() error {
versionPkg := types.PackageVersion{Package: path.Join(p.importBasePath, pth, gv.Group.NonEmpty(), gv.Version.String()), Version: gv.Version}
if group, ok := seenGroups[gv.Group]; ok {
seenGroups[gv.Group].Versions = append(group.Versions, versionPkg)
vers := group.Versions
vers = append(vers, versionPkg)
seenGroups[gv.Group].Versions = vers
} else {
seenGroups[gv.Group] = &types.GroupVersions{
PackageName: gv.Group.NonEmpty(),

View File

@@ -18,21 +18,21 @@ limitations under the License.
package generators
import (
"fmt"
"path"
"path/filepath"
"strings"
clientgenargs "k8s.io/code-generator/cmd/client-gen/args"
"k8s.io/code-generator/cmd/client-gen/args"
"k8s.io/code-generator/cmd/client-gen/generators/fake"
"k8s.io/code-generator/cmd/client-gen/generators/scheme"
"k8s.io/code-generator/cmd/client-gen/generators/util"
"k8s.io/code-generator/cmd/client-gen/path"
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
codegennamer "k8s.io/code-generator/pkg/namer"
genutil "k8s.io/code-generator/pkg/util"
"k8s.io/gengo/args"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
"k8s.io/gengo/v2"
"k8s.io/gengo/v2/generator"
"k8s.io/gengo/v2/namer"
"k8s.io/gengo/v2/types"
"k8s.io/klog/v2"
)
@@ -128,31 +128,35 @@ 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()))
return &generator.DefaultPackage{
PackageName: strings.ToLower(gv.Version.NonEmpty()),
PackagePath: groupVersionClientPackage,
HeaderText: boilerplate,
PackageDocumentation: []byte("// This package has the automatically generated typed clients.\n"),
// GeneratorFunc returns a list of generators. Each generator makes a
func targetForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, clientsetDir, clientsetPkg string, groupPkgName string, groupGoName string, apiPath string, inputPkg string, applyBuilderPkg string, boilerplate []byte) generator.Target {
subdir := []string{"typed", strings.ToLower(groupPkgName), strings.ToLower(gv.Version.NonEmpty())}
gvDir := filepath.Join(clientsetDir, filepath.Join(subdir...))
gvPkg := path.Join(clientsetPkg, path.Join(subdir...))
return &generator.SimpleTarget{
PkgName: strings.ToLower(gv.Version.NonEmpty()),
PkgPath: gvPkg,
PkgDir: gvDir,
HeaderComment: boilerplate,
PkgDocComment: []byte("// This package has the automatically generated typed clients.\n"),
// GeneratorsFunc returns a list of generators. Each generator makes a
// single file.
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
GeneratorsFunc: func(c *generator.Context) (generators []generator.Generator) {
generators = []generator.Generator{
// Always generate a "doc.go" file.
generator.DefaultGen{OptionalName: "doc"},
generator.GoGenerator{OutputFilename: "doc.go"},
}
// Since we want a file per type that we generate a client for, we
// have to provide a function for this.
for _, t := range typeList {
generators = append(generators, &genClientForType{
DefaultGen: generator.DefaultGen{
OptionalName: strings.ToLower(c.Namers["private"].Name(t)),
GoGenerator: generator.GoGenerator{
OutputFilename: strings.ToLower(c.Namers["private"].Name(t)) + ".go",
},
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,
@@ -162,12 +166,12 @@ func packageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, cli
}
generators = append(generators, &genGroup{
DefaultGen: generator.DefaultGen{
OptionalName: groupPackageName + "_client",
GoGenerator: generator.GoGenerator{
OutputFilename: groupPkgName + "_client.go",
},
outputPackage: groupVersionClientPackage,
inputPackage: inputPackage,
clientsetPackage: clientsetPackage,
outputPackage: gvPkg,
inputPackage: inputPkg,
clientsetPackage: clientsetPkg,
group: gv.Group.NonEmpty(),
version: gv.Version.String(),
groupGoName: groupGoName,
@@ -176,11 +180,11 @@ func packageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, cli
imports: generator.NewImportTracker(),
})
expansionFileName := "generated_expansion"
expansionFileName := "generated_expansion.go"
generators = append(generators, &genExpansion{
groupPackagePath: filepath.Join(srcTreePath, groupVersionClientPackage),
DefaultGen: generator.DefaultGen{
OptionalName: expansionFileName,
groupPackagePath: gvDir,
GoGenerator: generator.GoGenerator{
OutputFilename: expansionFileName,
},
types: typeList,
})
@@ -193,23 +197,23 @@ 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 {
return &generator.DefaultPackage{
PackageName: customArgs.ClientsetName,
PackagePath: clientsetPackage,
HeaderText: boilerplate,
// GeneratorFunc returns a list of generators. Each generator generates a
func targetForClientset(args *args.Args, clientsetDir, clientsetPkg string, groupGoNames map[clientgentypes.GroupVersion]string, boilerplate []byte) generator.Target {
return &generator.SimpleTarget{
PkgName: args.ClientsetName,
PkgPath: clientsetPkg,
PkgDir: clientsetDir,
HeaderComment: boilerplate,
// GeneratorsFunc returns a list of generators. Each generator generates a
// single file.
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
GeneratorsFunc: func(c *generator.Context) (generators []generator.Generator) {
generators = []generator.Generator{
&genClientset{
DefaultGen: generator.DefaultGen{
OptionalName: "clientset",
GoGenerator: generator.GoGenerator{
OutputFilename: "clientset.go",
},
groups: customArgs.Groups,
groups: args.Groups,
groupGoNames: groupGoNames,
clientsetPackage: clientsetPackage,
outputPackage: customArgs.ClientsetName,
clientsetPackage: clientsetPkg,
imports: generator.NewImportTracker(),
},
}
@@ -218,13 +222,14 @@ 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 targetForScheme(args *args.Args, clientsetDir, clientsetPkg string, groupGoNames map[clientgentypes.GroupVersion]string, boilerplate []byte) generator.Target {
schemeDir := filepath.Join(clientsetDir, "scheme")
schemePkg := path.Join(clientsetPkg, "scheme")
// create runtime.Registry for internal client because it has to know about group versions
internalClient := false
NextGroup:
for _, group := range customArgs.Groups {
for _, group := range args.Groups {
for _, v := range group.Versions {
if v.String() == "" {
internalClient = true
@@ -233,26 +238,27 @@ NextGroup:
}
}
return &generator.DefaultPackage{
PackageName: "scheme",
PackagePath: schemePackage,
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
return &generator.SimpleTarget{
PkgName: "scheme",
PkgPath: schemePkg,
PkgDir: schemeDir,
HeaderComment: boilerplate,
PkgDocComment: []byte("// This package contains the scheme of the automatically generated clientset.\n"),
// GeneratorsFunc returns a list of generators. Each generator generates a
// single file.
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
GeneratorsFunc: func(c *generator.Context) (generators []generator.Generator) {
generators = []generator.Generator{
// Always generate a "doc.go" file.
generator.DefaultGen{OptionalName: "doc"},
generator.GoGenerator{OutputFilename: "doc.go"},
&scheme.GenScheme{
DefaultGen: generator.DefaultGen{
OptionalName: "register",
GoGenerator: generator.GoGenerator{
OutputFilename: "register.go",
},
InputPackages: customArgs.GroupVersionPackages(),
OutputPackage: schemePackage,
OutputPath: filepath.Join(srcTreePath, schemePackage),
Groups: customArgs.Groups,
InputPackages: args.GroupVersionPackages(),
OutputPkg: schemePkg,
OutputPath: schemeDir,
Groups: args.Groups,
GroupGoNames: groupGoNames,
ImportTracker: generator.NewImportTracker(),
CreateRegistry: internalClient,
@@ -268,12 +274,12 @@ NextGroup:
// first field (somegroup) as the name of the group in Go code, e.g. as the func name in a clientset.
//
// If the first field of the groupName is not unique within the clientset, use "// +groupName=unique
func applyGroupOverrides(universe types.Universe, customArgs *clientgenargs.CustomArgs) {
func applyGroupOverrides(universe types.Universe, args *args.Args) {
// Create a map from "old GV" to "new GV" so we know what changes we need to make.
changes := make(map[clientgentypes.GroupVersion]clientgentypes.GroupVersion)
for gv, inputDir := range customArgs.GroupVersionPackages() {
p := universe.Package(genutil.Vendorless(inputDir))
if override := types.ExtractCommentTags("+", p.Comments)["groupName"]; override != nil {
for gv, inputDir := range args.GroupVersionPackages() {
p := universe.Package(inputDir)
if override := gengo.ExtractCommentTags("+", p.Comments)["groupName"]; override != nil {
newGV := clientgentypes.GroupVersion{
Group: clientgentypes.Group(override[0]),
Version: gv.Version,
@@ -282,9 +288,9 @@ func applyGroupOverrides(universe types.Universe, customArgs *clientgenargs.Cust
}
}
// Modify customArgs.Groups based on the groupName overrides.
newGroups := make([]clientgentypes.GroupVersions, 0, len(customArgs.Groups))
for _, gvs := range customArgs.Groups {
// Modify args.Groups based on the groupName overrides.
newGroups := make([]clientgentypes.GroupVersions, 0, len(args.Groups))
for _, gvs := range args.Groups {
gv := clientgentypes.GroupVersion{
Group: gvs.Group,
Version: gvs.Versions[0].Version, // we only need a version, and the first will do
@@ -302,37 +308,64 @@ func applyGroupOverrides(universe types.Universe, customArgs *clientgenargs.Cust
newGroups = append(newGroups, gvs)
}
}
customArgs.Groups = newGroups
args.Groups = newGroups
}
// Packages makes the client package definition.
func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
boilerplate, err := arguments.LoadGoBoilerplate()
// 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, args *args.Args) error {
for i := range args.Groups {
pkg := &args.Groups[i]
for j := range pkg.Versions {
ver := &pkg.Versions[j]
input := ver.Package
p := context.Universe[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
}
// GetTargets makes the client target definition.
func GetTargets(context *generator.Context, args *args.Args) []generator.Target {
boilerplate, err := gengo.GoBoilerplate(args.GoHeaderFile, "", gengo.StdGeneratedBy)
if err != nil {
klog.Fatalf("Failed loading boilerplate: %v", err)
}
customArgs, ok := arguments.CustomArgs.(*clientgenargs.CustomArgs)
if !ok {
klog.Fatalf("cannot convert arguments.CustomArgs to clientgenargs.CustomArgs")
}
includedTypesOverrides := customArgs.IncludedTypesOverrides
includedTypesOverrides := args.IncludedTypesOverrides
applyGroupOverrides(context.Universe, customArgs)
if err := sanitizePackagePaths(context, args); err != nil {
klog.Fatalf("cannot sanitize inputs: %v", err)
}
applyGroupOverrides(context.Universe, args)
gvToTypes := map[clientgentypes.GroupVersion][]*types.Type{}
groupGoNames := make(map[clientgentypes.GroupVersion]string)
for gv, inputDir := range customArgs.GroupVersionPackages() {
p := context.Universe.Package(path.Vendorless(inputDir))
for gv, inputDir := range args.GroupVersionPackages() {
p := context.Universe.Package(inputDir)
// If there's a comment of the form "// +groupGoName=SomeUniqueShortName", use that as
// the Go group identifier in CamelCase. It defaults
groupGoNames[gv] = namer.IC(strings.Split(gv.Group.NonEmpty(), ".")[0])
if override := types.ExtractCommentTags("+", p.Comments)["groupGoName"]; override != nil {
if override := gengo.ExtractCommentTags("+", p.Comments)["groupGoName"]; override != nil {
groupGoNames[gv] = namer.IC(override[0])
}
// Package are indexed with the vendor prefix stripped
for n, t := range p.Types {
// filter out types which are not included in user specified overrides.
typesOverride, ok := includedTypesOverrides[gv]
@@ -361,33 +394,43 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
}
}
var packageList []generator.Package
clientsetPackage := filepath.Join(arguments.OutputPackagePath, customArgs.ClientsetName)
clientsetDir := filepath.Join(args.OutputDir, args.ClientsetName)
clientsetPkg := path.Join(args.OutputPkg, args.ClientsetName)
packageList = append(packageList, packageForClientset(customArgs, clientsetPackage, groupGoNames, boilerplate))
packageList = append(packageList, packageForScheme(customArgs, clientsetPackage, arguments.OutputBase, groupGoNames, boilerplate))
if customArgs.FakeClient {
packageList = append(packageList, fake.PackageForClientset(customArgs, clientsetPackage, groupGoNames, boilerplate))
var targetList []generator.Target
targetList = append(targetList,
targetForClientset(args, clientsetDir, clientsetPkg, groupGoNames, boilerplate))
targetList = append(targetList,
targetForScheme(args, clientsetDir, clientsetPkg, groupGoNames, boilerplate))
if args.FakeClient {
targetList = append(targetList,
fake.TargetForClientset(args, clientsetDir, clientsetPkg, args.ApplyConfigurationPackage, groupGoNames, boilerplate))
}
// If --clientset-only=true, we don't regenerate the individual typed clients.
if customArgs.ClientsetOnly {
return generator.Packages(packageList)
if args.ClientsetOnly {
return []generator.Target(targetList)
}
orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)}
gvPackages := customArgs.GroupVersionPackages()
for _, group := range customArgs.Groups {
gvPackages := args.GroupVersionPackages()
for _, group := range args.Groups {
for _, version := range group.Versions {
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))
if customArgs.FakeClient {
packageList = append(packageList, fake.PackageForGroup(gv, orderer.OrderTypes(types), clientsetPackage, group.PackageName, groupGoNames[gv], inputPath, customArgs.ApplyConfigurationPackage, boilerplate))
targetList = append(targetList,
targetForGroup(
gv, orderer.OrderTypes(types), clientsetDir, clientsetPkg,
group.PackageName, groupGoNames[gv], args.ClientsetAPIPath,
inputPath, args.ApplyConfigurationPackage, boilerplate))
if args.FakeClient {
targetList = append(targetList,
fake.TargetForGroup(gv, orderer.OrderTypes(types), clientsetDir, clientsetPkg, group.PackageName, groupGoNames[gv], inputPath, args.ApplyConfigurationPackage, boilerplate))
}
}
}
return generator.Packages(packageList)
return targetList
}

View File

@@ -17,45 +17,48 @@ limitations under the License.
package fake
import (
"path"
"path/filepath"
"strings"
"k8s.io/gengo/generator"
"k8s.io/gengo/types"
"k8s.io/gengo/v2/generator"
"k8s.io/gengo/v2/types"
clientgenargs "k8s.io/code-generator/cmd/client-gen/args"
"k8s.io/code-generator/cmd/client-gen/args"
scheme "k8s.io/code-generator/cmd/client-gen/generators/scheme"
"k8s.io/code-generator/cmd/client-gen/generators/util"
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 TargetForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, clientsetDir, clientsetPkg string, groupPkgName string, groupGoName string, inputPkg string, applyBuilderPackage string, boilerplate []byte) generator.Target {
// 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()))
return &generator.DefaultPackage{
PackageName: "fake",
PackagePath: outputPackage,
HeaderText: boilerplate,
PackageDocumentation: []byte(
`// Package fake has the automatically generated clients.
`),
// GeneratorFunc returns a list of generators. Each generator makes a
subdir := []string{"typed", strings.ToLower(groupPkgName), strings.ToLower(gv.Version.NonEmpty())}
outputDir := filepath.Join(clientsetDir, filepath.Join(subdir...), "fake")
outputPkg := path.Join(clientsetPkg, path.Join(subdir...), "fake")
realClientPkg := path.Join(clientsetPkg, path.Join(subdir...))
return &generator.SimpleTarget{
PkgName: "fake",
PkgPath: outputPkg,
PkgDir: outputDir,
HeaderComment: boilerplate,
PkgDocComment: []byte("// Package fake has the automatically generated clients.\n"),
// GeneratorsFunc returns a list of generators. Each generator makes a
// single file.
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
GeneratorsFunc: func(c *generator.Context) (generators []generator.Generator) {
generators = []generator.Generator{
// Always generate a "doc.go" file.
generator.DefaultGen{OptionalName: "doc"},
generator.GoGenerator{OutputFilename: "doc.go"},
}
// Since we want a file per type that we generate a client for, we
// have to provide a function for this.
for _, t := range typeList {
generators = append(generators, &genFakeForType{
DefaultGen: generator.DefaultGen{
OptionalName: "fake_" + strings.ToLower(c.Namers["private"].Name(t)),
GoGenerator: generator.GoGenerator{
OutputFilename: "fake_" + strings.ToLower(c.Namers["private"].Name(t)) + ".go",
},
outputPackage: outputPackage,
inputPackage: inputPackage,
outputPackage: outputPkg,
inputPackage: inputPkg,
group: gv.Group.NonEmpty(),
version: gv.Version.String(),
groupGoName: groupGoName,
@@ -66,11 +69,11 @@ func PackageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, cli
}
generators = append(generators, &genFakeForGroup{
DefaultGen: generator.DefaultGen{
OptionalName: "fake_" + groupPackageName + "_client",
GoGenerator: generator.GoGenerator{
OutputFilename: "fake_" + groupPkgName + "_client.go",
},
outputPackage: outputPackage,
realClientPackage: realClientPackage,
outputPackage: outputPkg,
realClientPackage: realClientPkg,
group: gv.Group.NonEmpty(),
version: gv.Version.String(),
groupGoName: groupGoName,
@@ -85,41 +88,40 @@ 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 {
return &generator.DefaultPackage{
func TargetForClientset(args *args.Args, clientsetDir, clientsetPkg string, applyConfigurationPkg string, groupGoNames map[clientgentypes.GroupVersion]string, boilerplate []byte) generator.Target {
return &generator.SimpleTarget{
// 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"),
HeaderText: boilerplate,
PackageDocumentation: []byte(
`// This package has the automatically generated fake clientset.
`),
// GeneratorFunc returns a list of generators. Each generator generates a
PkgName: "fake",
PkgPath: path.Join(clientsetPkg, "fake"),
PkgDir: filepath.Join(clientsetDir, "fake"),
HeaderComment: boilerplate,
PkgDocComment: []byte("// This package has the automatically generated fake clientset.\n"),
// GeneratorsFunc returns a list of generators. Each generator generates a
// single file.
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
GeneratorsFunc: func(c *generator.Context) (generators []generator.Generator) {
generators = []generator.Generator{
// Always generate a "doc.go" file.
generator.DefaultGen{OptionalName: "doc"},
generator.GoGenerator{OutputFilename: "doc.go"},
&genClientset{
DefaultGen: generator.DefaultGen{
OptionalName: "clientset_generated",
GoGenerator: generator.GoGenerator{
OutputFilename: "clientset_generated.go",
},
groups: customArgs.Groups,
groupGoNames: groupGoNames,
fakeClientsetPackage: clientsetPackage,
outputPackage: "fake",
imports: generator.NewImportTracker(),
realClientsetPackage: clientsetPackage,
groups: args.Groups,
groupGoNames: groupGoNames,
fakeClientsetPackage: clientsetPkg,
imports: generator.NewImportTracker(),
realClientsetPackage: clientsetPkg,
applyConfigurationPackage: applyConfigurationPkg,
},
&scheme.GenScheme{
DefaultGen: generator.DefaultGen{
OptionalName: "register",
GoGenerator: generator.GoGenerator{
OutputFilename: "register.go",
},
InputPackages: customArgs.GroupVersionPackages(),
OutputPackage: clientsetPackage,
Groups: customArgs.Groups,
InputPackages: args.GroupVersionPackages(),
OutputPkg: clientsetPkg,
Groups: args.Groups,
GroupGoNames: groupGoNames,
ImportTracker: generator.NewImportTracker(),
PrivateScheme: true,

View File

@@ -19,33 +19,33 @@ package fake
import (
"fmt"
"io"
"path/filepath"
"path"
"strings"
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
"k8s.io/gengo/v2/generator"
"k8s.io/gengo/v2/namer"
"k8s.io/gengo/v2/types"
)
// genClientset generates a package for a clientset.
type genClientset struct {
generator.DefaultGen
generator.GoGenerator
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
applyConfigurationPackage string
}
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),
}
}
@@ -60,8 +60,8 @@ func (g *genClientset) Imports(c *generator.Context) (imports []string) {
imports = append(imports, g.imports.ImportLines()...)
for _, group := range g.groups {
for _, version := range group.Versions {
groupClientPackage := filepath.Join(g.fakeClientsetPackage, "typed", strings.ToLower(group.PackageName), strings.ToLower(version.NonEmpty()))
fakeGroupClientPackage := filepath.Join(groupClientPackage, "fake")
groupClientPackage := path.Join(g.fakeClientsetPackage, "typed", strings.ToLower(group.PackageName), strings.ToLower(version.NonEmpty()))
fakeGroupClientPackage := path.Join(groupClientPackage, "fake")
groupAlias := strings.ToLower(g.groupGoNames[clientgentypes.GroupVersion{Group: group.Group, Version: version.Version}])
imports = append(imports, fmt.Sprintf("%s%s \"%s\"", groupAlias, strings.ToLower(version.NonEmpty()), groupClientPackage))
@@ -77,12 +77,15 @@ func (g *genClientset) Imports(c *generator.Context) (imports []string) {
"fakediscovery \"k8s.io/client-go/discovery/fake\"",
"k8s.io/apimachinery/pkg/runtime",
"k8s.io/apimachinery/pkg/watch",
"k8s.io/apimachinery/pkg/api/meta/testrestmapper",
)
return
}
func (g *genClientset) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
generateApply := len(g.applyConfigurationPackage) > 0
// TODO: We actually don't need any type information to generate the clientset,
// perhaps we can adapt the go2ild framework to this kind of usage.
sw := generator.NewSnippetWriter(w, c, "$", "$")
@@ -90,6 +93,13 @@ func (g *genClientset) GenerateType(c *generator.Context, t *types.Type, w io.Wr
allGroups := clientgentypes.ToGroupVersionInfo(g.groups, g.groupGoNames)
sw.Do(common, nil)
if generateApply {
sw.Do(managedFieldsClientset, map[string]any{
"newTypeConverter": types.Ref(g.applyConfigurationPackage, "NewTypeConverter"),
})
}
sw.Do(checkImpl, nil)
for _, group := range allGroups {
@@ -108,11 +118,50 @@ func (g *genClientset) GenerateType(c *generator.Context, t *types.Type, w io.Wr
}
// This part of code is version-independent, unchanging.
var common = `
// NewSimpleClientset returns a clientset that will respond with the provided objects.
var managedFieldsClientset = `
// NewClientset returns a clientset that will respond with the provided objects.
// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
// without applying any validations and/or defaults. It shouldn't be considered a replacement
// for a real clientset and is mostly useful in simple unit tests.
func NewClientset(objects ...runtime.Object) *Clientset {
o := testing.NewFieldManagedObjectTracker(
scheme,
codecs.UniversalDecoder(),
$.newTypeConverter|raw$(scheme),
)
for _, obj := range objects {
if err := o.Add(obj); err != nil {
panic(err)
}
}
cs := &Clientset{tracker: o}
cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}
cs.AddReactor("*", "*", testing.ObjectReaction(o))
cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
gvr := action.GetResource()
ns := action.GetNamespace()
watch, err := o.Watch(gvr, ns)
if err != nil {
return false, nil, err
}
return true, watch, nil
})
return cs
}
`
var common = `
// NewSimpleClientset returns a clientset that will respond with the provided objects.
// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
// without applying any field management, validations and/or defaults. It shouldn't be considered a replacement
// for a real clientset and is mostly useful in simple unit tests.
//
// DEPRECATED: NewClientset replaces this with support for field management, which significantly improves
// server side apply testing. NewClientset is only available when apply configurations are generated (e.g.
// via --with-applyconfig).
func NewSimpleClientset(objects ...runtime.Object) *Clientset {
o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
for _, obj := range objects {

View File

@@ -19,21 +19,21 @@ package fake
import (
"fmt"
"io"
"path/filepath"
"path"
"strings"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
"k8s.io/gengo/v2/generator"
"k8s.io/gengo/v2/namer"
"k8s.io/gengo/v2/types"
"k8s.io/code-generator/cmd/client-gen/generators/util"
)
// genFakeForGroup produces a file for a group client, e.g. ExtensionsClient for the extension group.
type genFakeForGroup struct {
generator.DefaultGen
outputPackage string
realClientPackage string
generator.GoGenerator
outputPackage string // must be a Go import-path
realClientPackage string // must be a Go import-path
group string
version string
groupGoName string
@@ -64,7 +64,7 @@ func (g *genFakeForGroup) Namers(c *generator.Context) namer.NameSystems {
func (g *genFakeForGroup) Imports(c *generator.Context) (imports []string) {
imports = g.imports.ImportLines()
if len(g.types) != 0 {
imports = append(imports, fmt.Sprintf("%s \"%s\"", strings.ToLower(filepath.Base(g.realClientPackage)), g.realClientPackage))
imports = append(imports, fmt.Sprintf("%s \"%s\"", strings.ToLower(path.Base(g.realClientPackage)), g.realClientPackage))
}
return imports
}
@@ -90,7 +90,7 @@ func (g *genFakeForGroup) GenerateType(c *generator.Context, t *types.Type, w io
"type": t,
"GroupGoName": g.groupGoName,
"Version": namer.IC(g.version),
"realClientPackage": strings.ToLower(filepath.Base(g.realClientPackage)),
"realClientPackage": strings.ToLower(path.Base(g.realClientPackage)),
}
if tags.NonNamespaced {
sw.Do(getterImplNonNamespaced, wrapper)

View File

@@ -18,21 +18,23 @@ package fake
import (
"io"
gopath "path"
"path/filepath"
"path"
"strings"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
"golang.org/x/text/cases"
"golang.org/x/text/language"
"k8s.io/gengo/v2/generator"
"k8s.io/gengo/v2/namer"
"k8s.io/gengo/v2/types"
"k8s.io/code-generator/cmd/client-gen/generators/util"
)
// genFakeForType produces a file for each top-level type.
type genFakeForType struct {
generator.DefaultGen
outputPackage string
generator.GoGenerator
outputPackage string // Must be a Go import-path
group string
version string
groupGoName string
@@ -44,6 +46,8 @@ type genFakeForType struct {
var _ generator.Generator = &genFakeForType{}
var titler = cases.Title(language.Und)
// Filter ignores all but one type because we're making a single file per type.
func (g *genFakeForType) Filter(c *generator.Context, t *types.Type) bool { return t == g.typeToMatch }
@@ -87,7 +91,7 @@ func hasObjectMeta(t *types.Type) bool {
// GenerateType makes the body of a file implementing the individual typed client for type t.
func (g *genFakeForType) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
sw := generator.NewSnippetWriter(w, c, "$", "$")
pkg := filepath.Base(t.Name.Package)
pkg := path.Base(t.Name.Package)
tags, err := util.ParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
if err != nil {
return err
@@ -120,40 +124,38 @@ func (g *genFakeForType) GenerateType(c *generator.Context, t *types.Type, w io.
"watchInterface": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/watch", Name: "Interface"}),
"jsonMarshal": c.Universe.Type(types.Name{Package: "encoding/json", Name: "Marshal"}),
"NewRootListAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootListAction"}),
"NewListAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewListAction"}),
"NewRootGetAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootGetAction"}),
"NewGetAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewGetAction"}),
"NewRootDeleteAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootDeleteAction"}),
"NewRootDeleteActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootDeleteActionWithOptions"}),
"NewDeleteAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewDeleteAction"}),
"NewDeleteActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewDeleteActionWithOptions"}),
"NewRootDeleteCollectionAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootDeleteCollectionAction"}),
"NewDeleteCollectionAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewDeleteCollectionAction"}),
"NewRootUpdateAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootUpdateAction"}),
"NewUpdateAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewUpdateAction"}),
"NewRootCreateAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootCreateAction"}),
"NewCreateAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewCreateAction"}),
"NewRootWatchAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootWatchAction"}),
"NewWatchAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewWatchAction"}),
"NewCreateSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewCreateSubresourceAction"}),
"NewRootCreateSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootCreateSubresourceAction"}),
"NewUpdateSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewUpdateSubresourceAction"}),
"NewGetSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewGetSubresourceAction"}),
"NewRootGetSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootGetSubresourceAction"}),
"NewRootUpdateSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootUpdateSubresourceAction"}),
"NewRootPatchAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootPatchAction"}),
"NewPatchAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewPatchAction"}),
"NewRootPatchSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootPatchSubresourceAction"}),
"NewPatchSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewPatchSubresourceAction"}),
"ExtractFromListOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "ExtractFromListOptions"}),
"NewRootListActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootListActionWithOptions"}),
"NewListActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewListActionWithOptions"}),
"NewRootGetActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootGetActionWithOptions"}),
"NewGetActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewGetActionWithOptions"}),
"NewRootDeleteActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootDeleteActionWithOptions"}),
"NewDeleteActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewDeleteActionWithOptions"}),
"NewRootDeleteCollectionActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootDeleteCollectionActionWithOptions"}),
"NewDeleteCollectionActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewDeleteCollectionActionWithOptions"}),
"NewRootUpdateActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootUpdateActionWithOptions"}),
"NewUpdateActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewUpdateActionWithOptions"}),
"NewRootCreateActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootCreateActionWithOptions"}),
"NewCreateActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewCreateActionWithOptions"}),
"NewRootWatchActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootWatchActionWithOptions"}),
"NewWatchActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewWatchActionWithOptions"}),
"NewCreateSubresourceActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewCreateSubresourceActionWithOptions"}),
"NewRootCreateSubresourceActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootCreateSubresourceActionWithOptions"}),
"NewUpdateSubresourceActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewUpdateSubresourceActionWithOptions"}),
"NewGetSubresourceActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewGetSubresourceActionWithOptions"}),
"NewRootGetSubresourceActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootGetSubresourceActionWithOptions"}),
"NewRootUpdateSubresourceActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootUpdateSubresourceActionWithOptions"}),
"NewRootPatchActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootPatchActionWithOptions"}),
"NewPatchActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewPatchActionWithOptions"}),
"NewRootPatchSubresourceActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootPatchSubresourceActionWithOptions"}),
"NewPatchSubresourceActionWithOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewPatchSubresourceActionWithOptions"}),
"ExtractFromListOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "ExtractFromListOptions"}),
}
generateApply := len(g.applyConfigurationPackage) > 0
if generateApply {
// Generated apply builder type references required for generated Apply function
_, gvString := util.ParsePathGroupVersion(g.inputPackage)
m["inputApplyConfig"] = types.Ref(gopath.Join(g.applyConfigurationPackage, gvString), t.Name.Name+"ApplyConfiguration")
m["inputApplyConfig"] = types.Ref(path.Join(g.applyConfigurationPackage, gvString), t.Name.Name+"ApplyConfiguration")
}
if tags.NonNamespaced {
@@ -237,7 +239,7 @@ func (g *genFakeForType) GenerateType(c *generator.Context, t *types.Type, w io.
m["resultType"] = &resultType
m["subresourcePath"] = e.SubResourcePath
if e.HasVerb("apply") {
m["inputApplyConfig"] = types.Ref(gopath.Join(g.applyConfigurationPackage, inputGVString), inputType.Name.Name+"ApplyConfiguration")
m["inputApplyConfig"] = types.Ref(path.Join(g.applyConfigurationPackage, inputGVString), inputType.Name.Name+"ApplyConfiguration")
}
if e.HasVerb("get") {
@@ -300,7 +302,7 @@ func (g *genFakeForType) GenerateType(c *generator.Context, t *types.Type, w io.
// TODO: Make the verbs in templates parametrized so the strings.Replace() is
// not needed.
func adjustTemplate(name, verbType, template string) string {
return strings.Replace(template, " "+strings.Title(verbType), " "+name, -1)
return strings.ReplaceAll(template, " "+titler.String(verbType), " "+name)
}
// template for the struct that implements the type's interface
@@ -331,11 +333,12 @@ var $.type|allLowercasePlural$Kind = $.SchemeGroupVersion|raw$.WithKind("$.type|
var listTemplate = `
// List takes label and field selectors, and returns the list of $.type|publicPlural$ that match those selectors.
func (c *Fake$.type|publicPlural$) List(ctx context.Context, opts $.ListOptions|raw$) (result *$.type|raw$List, err error) {
emptyResult := &$.type|raw$List{}
obj, err := c.Fake.
$if .namespaced$Invokes($.NewListAction|raw$($.type|allLowercasePlural$Resource, $.type|allLowercasePlural$Kind, c.ns, opts), &$.type|raw$List{})
$else$Invokes($.NewRootListAction|raw$($.type|allLowercasePlural$Resource, $.type|allLowercasePlural$Kind, opts), &$.type|raw$List{})$end$
$if .namespaced$Invokes($.NewListActionWithOptions|raw$($.type|allLowercasePlural$Resource, $.type|allLowercasePlural$Kind, c.ns, opts), emptyResult)
$else$Invokes($.NewRootListActionWithOptions|raw$($.type|allLowercasePlural$Resource, $.type|allLowercasePlural$Kind, opts), emptyResult)$end$
if obj == nil {
return nil, err
return emptyResult, err
}
return obj.(*$.type|raw$List), err
}
@@ -344,11 +347,12 @@ func (c *Fake$.type|publicPlural$) List(ctx context.Context, opts $.ListOptions|
var listUsingOptionsTemplate = `
// List takes label and field selectors, and returns the list of $.type|publicPlural$ that match those selectors.
func (c *Fake$.type|publicPlural$) List(ctx context.Context, opts $.ListOptions|raw$) (result *$.type|raw$List, err error) {
emptyResult := &$.type|raw$List{}
obj, err := c.Fake.
$if .namespaced$Invokes($.NewListAction|raw$($.type|allLowercasePlural$Resource, $.type|allLowercasePlural$Kind, c.ns, opts), &$.type|raw$List{})
$else$Invokes($.NewRootListAction|raw$($.type|allLowercasePlural$Resource, $.type|allLowercasePlural$Kind, opts), &$.type|raw$List{})$end$
$if .namespaced$Invokes($.NewListActionWithOptions|raw$($.type|allLowercasePlural$Resource, $.type|allLowercasePlural$Kind, c.ns, opts), emptyResult)
$else$Invokes($.NewRootListActionWithOptions|raw$($.type|allLowercasePlural$Resource, $.type|allLowercasePlural$Kind, opts), emptyResult)$end$
if obj == nil {
return nil, err
return emptyResult, err
}
label, _, _ := $.ExtractFromListOptions|raw$(opts)
@@ -368,11 +372,12 @@ func (c *Fake$.type|publicPlural$) List(ctx context.Context, opts $.ListOptions|
var getTemplate = `
// Get takes name of the $.type|private$, and returns the corresponding $.resultType|private$ object, and an error if there is any.
func (c *Fake$.type|publicPlural$) Get(ctx context.Context, name string, options $.GetOptions|raw$) (result *$.resultType|raw$, err error) {
emptyResult := &$.resultType|raw${}
obj, err := c.Fake.
$if .namespaced$Invokes($.NewGetAction|raw$($.type|allLowercasePlural$Resource, c.ns, name), &$.resultType|raw${})
$else$Invokes($.NewRootGetAction|raw$($.type|allLowercasePlural$Resource, name), &$.resultType|raw${})$end$
$if .namespaced$Invokes($.NewGetActionWithOptions|raw$($.type|allLowercasePlural$Resource, c.ns, name, options), emptyResult)
$else$Invokes($.NewRootGetActionWithOptions|raw$($.type|allLowercasePlural$Resource, name, options), emptyResult)$end$
if obj == nil {
return nil, err
return emptyResult, err
}
return obj.(*$.resultType|raw$), err
}
@@ -381,11 +386,12 @@ func (c *Fake$.type|publicPlural$) Get(ctx context.Context, name string, options
var getSubresourceTemplate = `
// Get takes name of the $.type|private$, and returns the corresponding $.resultType|private$ object, and an error if there is any.
func (c *Fake$.type|publicPlural$) Get(ctx context.Context, $.type|private$Name string, options $.GetOptions|raw$) (result *$.resultType|raw$, err error) {
emptyResult := &$.resultType|raw${}
obj, err := c.Fake.
$if .namespaced$Invokes($.NewGetSubresourceAction|raw$($.type|allLowercasePlural$Resource, c.ns, "$.subresourcePath$", $.type|private$Name), &$.resultType|raw${})
$else$Invokes($.NewRootGetSubresourceAction|raw$($.type|allLowercasePlural$Resource, "$.subresourcePath$", $.type|private$Name), &$.resultType|raw${})$end$
$if .namespaced$Invokes($.NewGetSubresourceActionWithOptions|raw$($.type|allLowercasePlural$Resource, c.ns, "$.subresourcePath$", $.type|private$Name, options), emptyResult)
$else$Invokes($.NewRootGetSubresourceActionWithOptions|raw$($.type|allLowercasePlural$Resource, "$.subresourcePath$", $.type|private$Name, options), emptyResult)$end$
if obj == nil {
return nil, err
return emptyResult, err
}
return obj.(*$.resultType|raw$), err
}
@@ -404,8 +410,8 @@ func (c *Fake$.type|publicPlural$) Delete(ctx context.Context, name string, opts
var deleteCollectionTemplate = `
// DeleteCollection deletes a collection of objects.
func (c *Fake$.type|publicPlural$) DeleteCollection(ctx context.Context, opts $.DeleteOptions|raw$, listOpts $.ListOptions|raw$) error {
$if .namespaced$action := $.NewDeleteCollectionAction|raw$($.type|allLowercasePlural$Resource, c.ns, listOpts)
$else$action := $.NewRootDeleteCollectionAction|raw$($.type|allLowercasePlural$Resource, listOpts)
$if .namespaced$action := $.NewDeleteCollectionActionWithOptions|raw$($.type|allLowercasePlural$Resource, c.ns, opts, listOpts)
$else$action := $.NewRootDeleteCollectionActionWithOptions|raw$($.type|allLowercasePlural$Resource, opts, listOpts)
$end$
_, err := c.Fake.Invokes(action, &$.type|raw$List{})
return err
@@ -414,11 +420,12 @@ func (c *Fake$.type|publicPlural$) DeleteCollection(ctx context.Context, opts $.
var createTemplate = `
// Create takes the representation of a $.inputType|private$ and creates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any.
func (c *Fake$.type|publicPlural$) Create(ctx context.Context, $.inputType|private$ *$.inputType|raw$, opts $.CreateOptions|raw$) (result *$.resultType|raw$, err error) {
emptyResult := &$.resultType|raw${}
obj, err := c.Fake.
$if .namespaced$Invokes($.NewCreateAction|raw$($.inputType|allLowercasePlural$Resource, c.ns, $.inputType|private$), &$.resultType|raw${})
$else$Invokes($.NewRootCreateAction|raw$($.inputType|allLowercasePlural$Resource, $.inputType|private$), &$.resultType|raw${})$end$
$if .namespaced$Invokes($.NewCreateActionWithOptions|raw$($.inputType|allLowercasePlural$Resource, c.ns, $.inputType|private$, opts), emptyResult)
$else$Invokes($.NewRootCreateActionWithOptions|raw$($.inputType|allLowercasePlural$Resource, $.inputType|private$, opts), emptyResult)$end$
if obj == nil {
return nil, err
return emptyResult, err
}
return obj.(*$.resultType|raw$), err
}
@@ -427,11 +434,12 @@ func (c *Fake$.type|publicPlural$) Create(ctx context.Context, $.inputType|priva
var createSubresourceTemplate = `
// Create takes the representation of a $.inputType|private$ and creates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any.
func (c *Fake$.type|publicPlural$) Create(ctx context.Context, $.type|private$Name string, $.inputType|private$ *$.inputType|raw$, opts $.CreateOptions|raw$) (result *$.resultType|raw$, err error) {
emptyResult := &$.resultType|raw${}
obj, err := c.Fake.
$if .namespaced$Invokes($.NewCreateSubresourceAction|raw$($.type|allLowercasePlural$Resource, $.type|private$Name, "$.subresourcePath$", c.ns, $.inputType|private$), &$.resultType|raw${})
$else$Invokes($.NewRootCreateSubresourceAction|raw$($.type|allLowercasePlural$Resource, $.type|private$Name, "$.subresourcePath$", $.inputType|private$), &$.resultType|raw${})$end$
$if .namespaced$Invokes($.NewCreateSubresourceActionWithOptions|raw$($.type|allLowercasePlural$Resource, $.type|private$Name, "$.subresourcePath$", c.ns, $.inputType|private$, opts), emptyResult)
$else$Invokes($.NewRootCreateSubresourceActionWithOptions|raw$($.type|allLowercasePlural$Resource, $.type|private$Name, "$.subresourcePath$", $.inputType|private$, opts), emptyResult)$end$
if obj == nil {
return nil, err
return emptyResult, err
}
return obj.(*$.resultType|raw$), err
}
@@ -440,11 +448,12 @@ func (c *Fake$.type|publicPlural$) Create(ctx context.Context, $.type|private$Na
var updateTemplate = `
// Update takes the representation of a $.inputType|private$ and updates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any.
func (c *Fake$.type|publicPlural$) Update(ctx context.Context, $.inputType|private$ *$.inputType|raw$, opts $.UpdateOptions|raw$) (result *$.resultType|raw$, err error) {
emptyResult := &$.resultType|raw${}
obj, err := c.Fake.
$if .namespaced$Invokes($.NewUpdateAction|raw$($.inputType|allLowercasePlural$Resource, c.ns, $.inputType|private$), &$.resultType|raw${})
$else$Invokes($.NewRootUpdateAction|raw$($.inputType|allLowercasePlural$Resource, $.inputType|private$), &$.resultType|raw${})$end$
$if .namespaced$Invokes($.NewUpdateActionWithOptions|raw$($.inputType|allLowercasePlural$Resource, c.ns, $.inputType|private$, opts), emptyResult)
$else$Invokes($.NewRootUpdateActionWithOptions|raw$($.inputType|allLowercasePlural$Resource, $.inputType|private$, opts), emptyResult)$end$
if obj == nil {
return nil, err
return emptyResult, err
}
return obj.(*$.resultType|raw$), err
}
@@ -453,11 +462,12 @@ func (c *Fake$.type|publicPlural$) Update(ctx context.Context, $.inputType|priva
var updateSubresourceTemplate = `
// Update takes the representation of a $.inputType|private$ and updates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any.
func (c *Fake$.type|publicPlural$) Update(ctx context.Context, $.type|private$Name string, $.inputType|private$ *$.inputType|raw$, opts $.UpdateOptions|raw$) (result *$.resultType|raw$, err error) {
emptyResult := &$.resultType|raw${}
obj, err := c.Fake.
$if .namespaced$Invokes($.NewUpdateSubresourceAction|raw$($.type|allLowercasePlural$Resource, "$.subresourcePath$", c.ns, $.inputType|private$), &$.inputType|raw${})
$else$Invokes($.NewRootUpdateSubresourceAction|raw$($.type|allLowercasePlural$Resource, "$.subresourcePath$", $.inputType|private$), &$.resultType|raw${})$end$
$if .namespaced$Invokes($.NewUpdateSubresourceActionWithOptions|raw$($.type|allLowercasePlural$Resource, "$.subresourcePath$", c.ns, $.inputType|private$, opts), &$.inputType|raw${})
$else$Invokes($.NewRootUpdateSubresourceActionWithOptions|raw$($.type|allLowercasePlural$Resource, "$.subresourcePath$", $.inputType|private$, opts), emptyResult)$end$
if obj == nil {
return nil, err
return emptyResult, err
}
return obj.(*$.resultType|raw$), err
}
@@ -466,12 +476,13 @@ func (c *Fake$.type|publicPlural$) Update(ctx context.Context, $.type|private$Na
var updateStatusTemplate = `
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *Fake$.type|publicPlural$) UpdateStatus(ctx context.Context, $.type|private$ *$.type|raw$, opts $.UpdateOptions|raw$) (*$.type|raw$, error) {
func (c *Fake$.type|publicPlural$) UpdateStatus(ctx context.Context, $.type|private$ *$.type|raw$, opts $.UpdateOptions|raw$) (result *$.type|raw$, err error) {
emptyResult := &$.type|raw${}
obj, err := c.Fake.
$if .namespaced$Invokes($.NewUpdateSubresourceAction|raw$($.type|allLowercasePlural$Resource, "status", c.ns, $.type|private$), &$.type|raw${})
$else$Invokes($.NewRootUpdateSubresourceAction|raw$($.type|allLowercasePlural$Resource, "status", $.type|private$), &$.type|raw${})$end$
$if .namespaced$Invokes($.NewUpdateSubresourceActionWithOptions|raw$($.type|allLowercasePlural$Resource, "status", c.ns, $.type|private$, opts), emptyResult)
$else$Invokes($.NewRootUpdateSubresourceActionWithOptions|raw$($.type|allLowercasePlural$Resource, "status", $.type|private$, opts), emptyResult)$end$
if obj == nil {
return nil, err
return emptyResult, err
}
return obj.(*$.type|raw$), err
}
@@ -481,19 +492,20 @@ var watchTemplate = `
// Watch returns a $.watchInterface|raw$ that watches the requested $.type|privatePlural$.
func (c *Fake$.type|publicPlural$) Watch(ctx context.Context, opts $.ListOptions|raw$) ($.watchInterface|raw$, error) {
return c.Fake.
$if .namespaced$InvokesWatch($.NewWatchAction|raw$($.type|allLowercasePlural$Resource, c.ns, opts))
$else$InvokesWatch($.NewRootWatchAction|raw$($.type|allLowercasePlural$Resource, opts))$end$
$if .namespaced$InvokesWatch($.NewWatchActionWithOptions|raw$($.type|allLowercasePlural$Resource, c.ns, opts))
$else$InvokesWatch($.NewRootWatchActionWithOptions|raw$($.type|allLowercasePlural$Resource, opts))$end$
}
`
var patchTemplate = `
// Patch applies the patch and returns the patched $.resultType|private$.
func (c *Fake$.type|publicPlural$) Patch(ctx context.Context, name string, pt $.PatchType|raw$, data []byte, opts $.PatchOptions|raw$, subresources ...string) (result *$.resultType|raw$, err error) {
emptyResult := &$.resultType|raw${}
obj, err := c.Fake.
$if .namespaced$Invokes($.NewPatchSubresourceAction|raw$($.type|allLowercasePlural$Resource, c.ns, name, pt, data, subresources... ), &$.resultType|raw${})
$else$Invokes($.NewRootPatchSubresourceAction|raw$($.type|allLowercasePlural$Resource, name, pt, data, subresources...), &$.resultType|raw${})$end$
$if .namespaced$Invokes($.NewPatchSubresourceActionWithOptions|raw$($.type|allLowercasePlural$Resource, c.ns, name, pt, data, opts, subresources... ), emptyResult)
$else$Invokes($.NewRootPatchSubresourceActionWithOptions|raw$($.type|allLowercasePlural$Resource, name, pt, data, opts, subresources...), emptyResult)$end$
if obj == nil {
return nil, err
return emptyResult, err
}
return obj.(*$.resultType|raw$), err
}
@@ -509,15 +521,16 @@ func (c *Fake$.type|publicPlural$) Apply(ctx context.Context, $.inputType|privat
if err != nil {
return nil, err
}
name := $.inputType|private$.Name
name := $.inputType|private$.Name
if name == nil {
return nil, fmt.Errorf("$.inputType|private$.Name must be provided to Apply")
}
emptyResult := &$.resultType|raw${}
obj, err := c.Fake.
$if .namespaced$Invokes($.NewPatchSubresourceAction|raw$($.type|allLowercasePlural$Resource, c.ns, *name, $.ApplyPatchType|raw$, data), &$.resultType|raw${})
$else$Invokes($.NewRootPatchSubresourceAction|raw$($.type|allLowercasePlural$Resource, *name, $.ApplyPatchType|raw$, data), &$.resultType|raw${})$end$
$if .namespaced$Invokes($.NewPatchSubresourceActionWithOptions|raw$($.type|allLowercasePlural$Resource, c.ns, *name, $.ApplyPatchType|raw$, data, opts.ToPatchOptions()), emptyResult)
$else$Invokes($.NewRootPatchSubresourceActionWithOptions|raw$($.type|allLowercasePlural$Resource, *name, $.ApplyPatchType|raw$, data, opts.ToPatchOptions()), emptyResult)$end$
if obj == nil {
return nil, err
return emptyResult, err
}
return obj.(*$.resultType|raw$), err
}
@@ -534,15 +547,16 @@ func (c *Fake$.type|publicPlural$) ApplyStatus(ctx context.Context, $.inputType|
if err != nil {
return nil, err
}
name := $.inputType|private$.Name
name := $.inputType|private$.Name
if name == nil {
return nil, fmt.Errorf("$.inputType|private$.Name must be provided to Apply")
}
emptyResult := &$.resultType|raw${}
obj, err := c.Fake.
$if .namespaced$Invokes($.NewPatchSubresourceAction|raw$($.type|allLowercasePlural$Resource, c.ns, *name, $.ApplyPatchType|raw$, data, "status"), &$.resultType|raw${})
$else$Invokes($.NewRootPatchSubresourceAction|raw$($.type|allLowercasePlural$Resource, *name, $.ApplyPatchType|raw$, data, "status"), &$.resultType|raw${})$end$
$if .namespaced$Invokes($.NewPatchSubresourceActionWithOptions|raw$($.type|allLowercasePlural$Resource, c.ns, *name, $.ApplyPatchType|raw$, data, opts.ToPatchOptions(), "status"), emptyResult)
$else$Invokes($.NewRootPatchSubresourceActionWithOptions|raw$($.type|allLowercasePlural$Resource, *name, $.ApplyPatchType|raw$, data, opts.ToPatchOptions(), "status"), emptyResult)$end$
if obj == nil {
return nil, err
return emptyResult, err
}
return obj.(*$.resultType|raw$), err
}
@@ -559,11 +573,12 @@ func (c *Fake$.type|publicPlural$) Apply(ctx context.Context, $.type|private$Nam
if err != nil {
return nil, err
}
emptyResult := &$.resultType|raw${}
obj, err := c.Fake.
$if .namespaced$Invokes($.NewPatchSubresourceAction|raw$($.type|allLowercasePlural$Resource, c.ns, $.type|private$Name, $.ApplyPatchType|raw$, data, "status"), &$.resultType|raw${})
$else$Invokes($.NewRootPatchSubresourceAction|raw$($.type|allLowercasePlural$Resource, $.type|private$Name, $.ApplyPatchType|raw$, data, "status"), &$.resultType|raw${})$end$
$if .namespaced$Invokes($.NewPatchSubresourceActionWithOptions|raw$($.type|allLowercasePlural$Resource, c.ns, $.type|private$Name, $.ApplyPatchType|raw$, data, opts.ToPatchOptions(), "$.inputType|private$"), emptyResult)
$else$Invokes($.NewRootPatchSubresourceActionWithOptions|raw$($.type|allLowercasePlural$Resource, $.type|private$Name, $.ApplyPatchType|raw$, data, opts.ToPatchOptions(), "$.inputType|private$"), emptyResult)$end$
if obj == nil {
return nil, err
return emptyResult, err
}
return obj.(*$.resultType|raw$), err
}

View File

@@ -19,22 +19,21 @@ package generators
import (
"fmt"
"io"
"path/filepath"
"path"
"strings"
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
"k8s.io/gengo/v2/generator"
"k8s.io/gengo/v2/namer"
"k8s.io/gengo/v2/types"
)
// genClientset generates a package for a clientset.
type genClientset struct {
generator.DefaultGen
generator.GoGenerator
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),
}
}
@@ -58,7 +57,7 @@ func (g *genClientset) Imports(c *generator.Context) (imports []string) {
imports = append(imports, g.imports.ImportLines()...)
for _, group := range g.groups {
for _, version := range group.Versions {
typedClientPath := filepath.Join(g.clientsetPackage, "typed", strings.ToLower(group.PackageName), strings.ToLower(version.NonEmpty()))
typedClientPath := path.Join(g.clientsetPackage, "typed", strings.ToLower(group.PackageName), strings.ToLower(version.NonEmpty()))
groupAlias := strings.ToLower(g.groupGoNames[clientgentypes.GroupVersion{Group: group.Group, Version: version.Version}])
imports = append(imports, fmt.Sprintf("%s%s \"%s\"", groupAlias, strings.ToLower(version.NonEmpty()), typedClientPath))
}

View File

@@ -22,13 +22,13 @@ import (
"path/filepath"
"strings"
"k8s.io/gengo/generator"
"k8s.io/gengo/types"
"k8s.io/gengo/v2/generator"
"k8s.io/gengo/v2/types"
)
// genExpansion produces a file for a group client, e.g. ExtensionsClient for the extension group.
type genExpansion struct {
generator.DefaultGen
generator.GoGenerator
groupPackagePath string
// types in a group
types []*types.Type

View File

@@ -18,19 +18,19 @@ package generators
import (
"io"
"path/filepath"
"path"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
"k8s.io/gengo/v2"
"k8s.io/gengo/v2/generator"
"k8s.io/gengo/v2/namer"
"k8s.io/gengo/v2/types"
"k8s.io/code-generator/cmd/client-gen/generators/util"
"k8s.io/code-generator/cmd/client-gen/path"
)
// genGroup produces a file for a group client, e.g. ExtensionsClient for the extension group.
type genGroup struct {
generator.DefaultGen
generator.GoGenerator
outputPackage string
group string
version string
@@ -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
}
@@ -64,38 +64,32 @@ func (g *genGroup) Namers(c *generator.Context) namer.NameSystems {
func (g *genGroup) Imports(c *generator.Context) (imports []string) {
imports = append(imports, g.imports.ImportLines()...)
imports = append(imports, filepath.Join(g.clientsetPackage, "scheme"))
imports = append(imports, path.Join(g.clientsetPackage, "scheme"))
return
}
func (g *genGroup) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
sw := generator.NewSnippetWriter(w, c, "$", "$")
apiPath := func(group string) string {
if group == "core" {
return `"/api"`
}
return `"` + g.apiPath + `"`
}
groupName := g.group
if g.group == "core" {
groupName = ""
}
// allow user to define a group name that's different from the one parsed from the directory.
p := c.Universe.Package(path.Vendorless(g.inputPackage))
if override := types.ExtractCommentTags("+", p.Comments)["groupName"]; override != nil {
p := c.Universe.Package(g.inputPackage)
groupName := g.group
if override := gengo.ExtractCommentTags("+", p.Comments)["groupName"]; override != nil {
groupName = override[0]
}
apiPath := `"` + g.apiPath + `"`
if groupName == "" {
apiPath = `"/api"`
}
m := map[string]interface{}{
"group": g.group,
"version": g.version,
"groupName": groupName,
"GroupGoName": g.groupGoName,
"Version": namer.IC(g.version),
"types": g.types,
"apiPath": apiPath(g.group),
"apiPath": apiPath,
"schemaGroupVersion": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/schema", Name: "GroupVersion"}),
"runtimeAPIVersionInternal": c.Universe.Variable(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "APIVersionInternal"}),
"restConfig": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Config"}),
@@ -104,7 +98,7 @@ func (g *genGroup) GenerateType(c *generator.Context, t *types.Type, w io.Writer
"RESTHTTPClientFor": c.Universe.Function(types.Name{Package: "k8s.io/client-go/rest", Name: "HTTPClientFor"}),
"restRESTClientFor": c.Universe.Function(types.Name{Package: "k8s.io/client-go/rest", Name: "RESTClientFor"}),
"restRESTClientForConfigAndClient": c.Universe.Function(types.Name{Package: "k8s.io/client-go/rest", Name: "RESTClientForConfigAndClient"}),
"SchemeGroupVersion": c.Universe.Variable(types.Name{Package: path.Vendorless(g.inputPackage), Name: "SchemeGroupVersion"}),
"SchemeGroupVersion": c.Universe.Variable(types.Name{Package: g.inputPackage, Name: "SchemeGroupVersion"}),
}
sw.Do(groupInterfaceTemplate, m)
sw.Do(groupClientTemplate, m)

View File

@@ -19,23 +19,24 @@ package generators
import (
"io"
"path"
"path/filepath"
"strings"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
"golang.org/x/text/cases"
"golang.org/x/text/language"
"k8s.io/gengo/v2/generator"
"k8s.io/gengo/v2/namer"
"k8s.io/gengo/v2/types"
"k8s.io/code-generator/cmd/client-gen/generators/util"
)
// genClientForType produces a file for each top-level type.
type genClientForType struct {
generator.DefaultGen
outputPackage string
generator.GoGenerator
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
@@ -45,6 +46,8 @@ type genClientForType struct {
var _ generator.Generator = &genClientForType{}
var titler = cases.Title(language.Und)
// Filter ignores all but one type because we're making a single file per type.
func (g *genClientForType) Filter(c *generator.Context, t *types.Type) bool {
return t == g.typeToMatch
@@ -81,7 +84,7 @@ func (g *genClientForType) GenerateType(c *generator.Context, t *types.Type, w i
defaultVerbTemplates := buildDefaultVerbTemplates(generateApply)
subresourceDefaultVerbTemplates := buildSubresourceDefaultVerbTemplates(generateApply)
sw := generator.NewSnippetWriter(w, c, "$", "$")
pkg := filepath.Base(t.Name.Package)
pkg := path.Base(t.Name.Package)
tags, err := util.ParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
if err != nil {
return err
@@ -120,9 +123,9 @@ func (g *genClientForType) GenerateType(c *generator.Context, t *types.Type, w i
}
var updatedVerbtemplate string
if _, exists := subresourceDefaultVerbTemplates[e.VerbType]; e.IsSubresource() && exists {
updatedVerbtemplate = e.VerbName + "(" + strings.TrimPrefix(subresourceDefaultVerbTemplates[e.VerbType], strings.Title(e.VerbType)+"(")
updatedVerbtemplate = e.VerbName + "(" + strings.TrimPrefix(subresourceDefaultVerbTemplates[e.VerbType], titler.String(e.VerbType)+"(")
} else {
updatedVerbtemplate = e.VerbName + "(" + strings.TrimPrefix(defaultVerbTemplates[e.VerbType], strings.Title(e.VerbType)+"(")
updatedVerbtemplate = e.VerbName + "(" + strings.TrimPrefix(defaultVerbTemplates[e.VerbType], titler.String(e.VerbType)+"(")
}
extendedMethod := extendedInterfaceMethod{
template: updatedVerbtemplate,
@@ -145,30 +148,38 @@ func (g *genClientForType) GenerateType(c *generator.Context, t *types.Type, w i
extendedMethods = append(extendedMethods, extendedMethod)
}
m := map[string]interface{}{
"type": t,
"inputType": t,
"resultType": t,
"package": pkg,
"Package": namer.IC(pkg),
"namespaced": !tags.NonNamespaced,
"Group": namer.IC(g.group),
"subresource": false,
"subresourcePath": "",
"GroupGoName": g.groupGoName,
"Version": namer.IC(g.version),
"CreateOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "CreateOptions"}),
"DeleteOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "DeleteOptions"}),
"GetOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "GetOptions"}),
"ListOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "ListOptions"}),
"PatchOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "PatchOptions"}),
"ApplyOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "ApplyOptions"}),
"UpdateOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "UpdateOptions"}),
"PatchType": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/types", Name: "PatchType"}),
"ApplyPatchType": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/types", Name: "ApplyPatchType"}),
"watchInterface": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/watch", Name: "Interface"}),
"RESTClientInterface": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Interface"}),
"schemeParameterCodec": c.Universe.Variable(types.Name{Package: filepath.Join(g.clientsetPackage, "scheme"), Name: "ParameterCodec"}),
"jsonMarshal": c.Universe.Type(types.Name{Package: "encoding/json", Name: "Marshal"}),
"type": t,
"inputType": t,
"resultType": t,
"package": pkg,
"Package": namer.IC(pkg),
"namespaced": !tags.NonNamespaced,
"Group": namer.IC(g.group),
"subresource": false,
"subresourcePath": "",
"GroupGoName": g.groupGoName,
"Version": namer.IC(g.version),
"CreateOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "CreateOptions"}),
"DeleteOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "DeleteOptions"}),
"GetOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "GetOptions"}),
"ListOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "ListOptions"}),
"PatchOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "PatchOptions"}),
"ApplyOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "ApplyOptions"}),
"UpdateOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "UpdateOptions"}),
"PatchType": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/types", Name: "PatchType"}),
"ApplyPatchType": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/types", Name: "ApplyPatchType"}),
"watchInterface": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/watch", Name: "Interface"}),
"RESTClientInterface": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Interface"}),
"schemeParameterCodec": c.Universe.Variable(types.Name{Package: path.Join(g.clientsetPackage, "scheme"), Name: "ParameterCodec"}),
"jsonMarshal": c.Universe.Type(types.Name{Package: "encoding/json", Name: "Marshal"}),
"resourceVersionMatchNotOlderThan": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "ResourceVersionMatchNotOlderThan"}),
"CheckListFromCacheDataConsistencyIfRequested": c.Universe.Function(types.Name{Package: "k8s.io/client-go/util/consistencydetector", Name: "CheckListFromCacheDataConsistencyIfRequested"}),
"CheckWatchListFromCacheDataConsistencyIfRequested": c.Universe.Function(types.Name{Package: "k8s.io/client-go/util/consistencydetector", Name: "CheckWatchListFromCacheDataConsistencyIfRequested"}),
"PrepareWatchListOptionsFromListOptions": c.Universe.Function(types.Name{Package: "k8s.io/client-go/util/watchlist", Name: "PrepareWatchListOptionsFromListOptions"}),
"Client": c.Universe.Type(types.Name{Package: "k8s.io/client-go/gentype", Name: "Client"}),
"ClientWithList": c.Universe.Type(types.Name{Package: "k8s.io/client-go/gentype", Name: "ClientWithList"}),
"ClientWithApply": c.Universe.Type(types.Name{Package: "k8s.io/client-go/gentype", Name: "ClientWithApply"}),
"ClientWithListAndApply": c.Universe.Type(types.Name{Package: "k8s.io/client-go/gentype", Name: "ClientWithListAndApply"}),
}
if generateApply {
@@ -203,53 +214,31 @@ func (g *genClientForType) GenerateType(c *generator.Context, t *types.Type, w i
}
sw.Do(interfaceTemplate4, m)
structNamespaced := namespaced
if tags.NonNamespaced {
sw.Do(structNonNamespaced, m)
sw.Do(newStructNonNamespaced, m)
} else {
sw.Do(structNamespaced, m)
sw.Do(newStructNamespaced, m)
structNamespaced = nonNamespaced
}
if tags.NoVerbs {
sw.Do(structType[noList|noApply], m)
sw.Do(newStruct[structNamespaced|noList|noApply], m)
return sw.Error()
}
if tags.HasVerb("get") {
sw.Do(getTemplate, m)
}
listableOrAppliable := noList | noApply
if tags.HasVerb("list") {
sw.Do(listTemplate, m)
}
if tags.HasVerb("watch") {
sw.Do(watchTemplate, m)
listableOrAppliable |= withList
}
if tags.HasVerb("create") {
sw.Do(createTemplate, m)
}
if tags.HasVerb("update") {
sw.Do(updateTemplate, m)
}
if tags.HasVerb("updateStatus") {
sw.Do(updateStatusTemplate, m)
}
if tags.HasVerb("delete") {
sw.Do(deleteTemplate, m)
}
if tags.HasVerb("deleteCollection") {
sw.Do(deleteCollectionTemplate, m)
}
if tags.HasVerb("patch") {
sw.Do(patchTemplate, m)
}
if tags.HasVerb("apply") && generateApply {
sw.Do(applyTemplate, m)
}
if tags.HasVerb("applyStatus") && generateApply {
sw.Do(applyStatusTemplate, m)
listableOrAppliable |= withApply
}
sw.Do(structType[listableOrAppliable], m)
sw.Do(newStruct[structNamespaced|listableOrAppliable], m)
// generate expansion methods
for _, e := range tags.Extensions {
if e.HasVerb("apply") && !generateApply {
@@ -295,6 +284,8 @@ func (g *genClientForType) GenerateType(c *generator.Context, t *types.Type, w i
sw.Do(adjustTemplate(e.VerbName, e.VerbType, listSubresourceTemplate), m)
} else {
sw.Do(adjustTemplate(e.VerbName, e.VerbType, listTemplate), m)
sw.Do(adjustTemplate(e.VerbName, e.VerbType, privateListTemplate), m)
sw.Do(adjustTemplate(e.VerbName, e.VerbType, watchListTemplate), m)
}
}
@@ -345,7 +336,7 @@ func (g *genClientForType) GenerateType(c *generator.Context, t *types.Type, w i
// TODO: Make the verbs in templates parametrized so the strings.Replace() is
// not needed.
func adjustTemplate(name, verbType, template string) string {
return strings.Replace(template, " "+strings.Title(verbType), " "+name, -1)
return strings.ReplaceAll(template, " "+titler.String(verbType), " "+name)
}
func generateInterface(defaultVerbTemplates map[string]string, tags util.Tags) string {
@@ -374,9 +365,10 @@ func buildSubresourceDefaultVerbTemplates(generateApply bool) map[string]string
func buildDefaultVerbTemplates(generateApply bool) map[string]string {
m := map[string]string{
"create": `Create(ctx context.Context, $.inputType|private$ *$.inputType|raw$, opts $.CreateOptions|raw$) (*$.resultType|raw$, error)`,
"update": `Update(ctx context.Context, $.inputType|private$ *$.inputType|raw$, opts $.UpdateOptions|raw$) (*$.resultType|raw$, error)`,
"updateStatus": `UpdateStatus(ctx context.Context, $.inputType|private$ *$.type|raw$, opts $.UpdateOptions|raw$) (*$.type|raw$, error)`,
"create": `Create(ctx context.Context, $.inputType|private$ *$.inputType|raw$, opts $.CreateOptions|raw$) (*$.resultType|raw$, error)`,
"update": `Update(ctx context.Context, $.inputType|private$ *$.inputType|raw$, opts $.UpdateOptions|raw$) (*$.resultType|raw$, error)`,
"updateStatus": `// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
UpdateStatus(ctx context.Context, $.inputType|private$ *$.type|raw$, opts $.UpdateOptions|raw$) (*$.type|raw$, error)`,
"delete": `Delete(ctx context.Context, name string, opts $.DeleteOptions|raw$) error`,
"deleteCollection": `DeleteCollection(ctx context.Context, opts $.DeleteOptions|raw$, listOpts $.ListOptions|raw$) error`,
"get": `Get(ctx context.Context, name string, opts $.GetOptions|raw$) (*$.resultType|raw$, error)`,
@@ -386,7 +378,8 @@ func buildDefaultVerbTemplates(generateApply bool) map[string]string {
}
if generateApply {
m["apply"] = `Apply(ctx context.Context, $.inputType|private$ *$.inputApplyConfig|raw$, opts $.ApplyOptions|raw$) (result *$.resultType|raw$, err error)`
m["applyStatus"] = `ApplyStatus(ctx context.Context, $.inputType|private$ *$.inputApplyConfig|raw$, opts $.ApplyOptions|raw$) (result *$.resultType|raw$, err error)`
m["applyStatus"] = `// Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus().
ApplyStatus(ctx context.Context, $.inputType|private$ *$.inputApplyConfig|raw$, opts $.ApplyOptions|raw$) (result *$.resultType|raw$, err error)`
}
return m
}
@@ -418,51 +411,204 @@ var interfaceTemplate4 = `
}
`
// template for the struct that implements the type's interface
var structNamespaced = `
// $.type|privatePlural$ implements $.type|public$Interface
type $.type|privatePlural$ struct {
client $.RESTClientInterface|raw$
ns string
}
`
// struct and constructor variants
const (
// The following values are bits in a bitmask.
// The values which can be set indicate namespace support, list support, and apply support;
// to make the declarations easier to read (like a truth table), corresponding zero-values
// are also declared.
namespaced = 0
noList = 0
noApply = 0
nonNamespaced = 1 << iota
withList
withApply
)
// template for the struct that implements the type's interface
var structNonNamespaced = `
// $.type|privatePlural$ implements $.type|public$Interface
type $.type|privatePlural$ struct {
client $.RESTClientInterface|raw$
}
`
// The following string slices are similar to maps, but with combinable keys used as indices.
// Each entry defines whether it supports lists and/or apply, and if namespacedness matters,
// namespaces; each bit is then toggled:
// * noList, noApply: index 0;
// * withList, noApply: index 2;
// * noList, withApply: index 4;
// * withList, withApply: index 6.
// When namespacedness matters, the namespaced variants are the same as the above, and
// the non-namespaced variants are offset by 1.
// Go enforces index unicity in these kinds of declarations.
var newStructNamespaced = `
// new$.type|publicPlural$ returns a $.type|publicPlural$
func new$.type|publicPlural$(c *$.GroupGoName$$.Version$Client, namespace string) *$.type|privatePlural$ {
return &$.type|privatePlural${
client: c.RESTClient(),
ns: namespace,
// struct declarations
// Namespacedness does not matter
var structType = []string{
noList | noApply: `
// $.type|privatePlural$ implements $.type|public$Interface
type $.type|privatePlural$ struct {
*$.Client|raw$[*$.resultType|raw$]
}
}
`
var newStructNonNamespaced = `
// new$.type|publicPlural$ returns a $.type|publicPlural$
func new$.type|publicPlural$(c *$.GroupGoName$$.Version$Client) *$.type|privatePlural$ {
return &$.type|privatePlural${
client: c.RESTClient(),
`,
withList | noApply: `
// $.type|privatePlural$ implements $.type|public$Interface
type $.type|privatePlural$ struct {
*$.ClientWithList|raw$[*$.resultType|raw$, *$.resultType|raw$List]
}
`,
noList | withApply: `
// $.type|privatePlural$ implements $.type|public$Interface
type $.type|privatePlural$ struct {
*$.ClientWithApply|raw$[*$.resultType|raw$, *$.inputApplyConfig|raw$]
}
`,
withList | withApply: `
// $.type|privatePlural$ implements $.type|public$Interface
type $.type|privatePlural$ struct {
*$.ClientWithListAndApply|raw$[*$.resultType|raw$, *$.resultType|raw$List, *$.inputApplyConfig|raw$]
}
`,
}
`
// Constructors for the struct, in all variants
// Namespacedness matters
var newStruct = []string{
namespaced | noList | noApply: `
// new$.type|publicPlural$ returns a $.type|publicPlural$
func new$.type|publicPlural$(c *$.GroupGoName$$.Version$Client, namespace string) *$.type|privatePlural$ {
return &$.type|privatePlural${
gentype.NewClient[*$.resultType|raw$](
"$.type|resource$",
c.RESTClient(),
$.schemeParameterCodec|raw$,
namespace,
func() *$.resultType|raw$ { return &$.resultType|raw${} }),
}
}
`,
namespaced | noList | withApply: `
// new$.type|publicPlural$ returns a $.type|publicPlural$
func new$.type|publicPlural$(c *$.GroupGoName$$.Version$Client, namespace string) *$.type|privatePlural$ {
return &$.type|privatePlural${
gentype.NewClientWithApply[*$.resultType|raw$, *$.inputApplyConfig|raw$](
"$.type|resource$",
c.RESTClient(),
$.schemeParameterCodec|raw$,
namespace,
func() *$.resultType|raw$ { return &$.resultType|raw${} }),
}
}
`,
namespaced | withList | noApply: `
// new$.type|publicPlural$ returns a $.type|publicPlural$
func new$.type|publicPlural$(c *$.GroupGoName$$.Version$Client, namespace string) *$.type|privatePlural$ {
return &$.type|privatePlural${
gentype.NewClientWithList[*$.resultType|raw$, *$.resultType|raw$List](
"$.type|resource$",
c.RESTClient(),
$.schemeParameterCodec|raw$,
namespace,
func() *$.resultType|raw$ { return &$.resultType|raw${} },
func() *$.resultType|raw$List { return &$.resultType|raw$List{} }),
}
}
`,
namespaced | withList | withApply: `
// new$.type|publicPlural$ returns a $.type|publicPlural$
func new$.type|publicPlural$(c *$.GroupGoName$$.Version$Client, namespace string) *$.type|privatePlural$ {
return &$.type|privatePlural${
gentype.NewClientWithListAndApply[*$.resultType|raw$, *$.resultType|raw$List, *$.inputApplyConfig|raw$](
"$.type|resource$",
c.RESTClient(),
$.schemeParameterCodec|raw$,
namespace,
func() *$.resultType|raw$ { return &$.resultType|raw${} },
func() *$.resultType|raw$List { return &$.resultType|raw$List{} }),
}
}
`,
nonNamespaced | noList | noApply: `
// new$.type|publicPlural$ returns a $.type|publicPlural$
func new$.type|publicPlural$(c *$.GroupGoName$$.Version$Client) *$.type|privatePlural$ {
return &$.type|privatePlural${
gentype.NewClient[*$.resultType|raw$](
"$.type|resource$",
c.RESTClient(),
$.schemeParameterCodec|raw$,
"",
func() *$.resultType|raw$ { return &$.resultType|raw${} }),
}
}
`,
nonNamespaced | noList | withApply: `
// new$.type|publicPlural$ returns a $.type|publicPlural$
func new$.type|publicPlural$(c *$.GroupGoName$$.Version$Client) *$.type|privatePlural$ {
return &$.type|privatePlural${
gentype.NewClientWithApply[*$.resultType|raw$, *$.inputApplyConfig|raw$](
"$.type|resource$",
c.RESTClient(),
$.schemeParameterCodec|raw$,
"",
func() *$.resultType|raw$ { return &$.resultType|raw${} }),
}
}
`,
nonNamespaced | withList | noApply: `
// new$.type|publicPlural$ returns a $.type|publicPlural$
func new$.type|publicPlural$(c *$.GroupGoName$$.Version$Client) *$.type|privatePlural$ {
return &$.type|privatePlural${
gentype.NewClientWithList[*$.resultType|raw$, *$.resultType|raw$List](
"$.type|resource$",
c.RESTClient(),
$.schemeParameterCodec|raw$,
"",
func() *$.resultType|raw$ { return &$.resultType|raw${} },
func() *$.resultType|raw$List { return &$.resultType|raw$List{} }),
}
}
`,
nonNamespaced | withList | withApply: `
// new$.type|publicPlural$ returns a $.type|publicPlural$
func new$.type|publicPlural$(c *$.GroupGoName$$.Version$Client) *$.type|privatePlural$ {
return &$.type|privatePlural${
gentype.NewClientWithListAndApply[*$.resultType|raw$, *$.resultType|raw$List, *$.inputApplyConfig|raw$](
"$.type|resource$",
c.RESTClient(),
$.schemeParameterCodec|raw$,
"",
func() *$.resultType|raw$ { return &$.resultType|raw${} },
func() *$.resultType|raw$List { return &$.resultType|raw$List{} }),
}
}
`,
}
var listTemplate = `
// List takes label and field selectors, and returns the list of $.resultType|publicPlural$ that match those selectors.
func (c *$.type|privatePlural$) List(ctx context.Context, opts $.ListOptions|raw$) (result *$.resultType|raw$List, err error) {
func (c *$.type|privatePlural$) List(ctx context.Context, opts $.ListOptions|raw$) (*$.resultType|raw$List, error) {
if watchListOptions, hasWatchListOptionsPrepared, watchListOptionsErr := $.PrepareWatchListOptionsFromListOptions|raw$(opts); watchListOptionsErr != nil {
klog.Warningf("Failed preparing watchlist options for $.type|resource$, falling back to the standard LIST semantics, err = %v", watchListOptionsErr )
} else if hasWatchListOptionsPrepared {
result, err := c.watchList(ctx, watchListOptions)
if err == nil {
$.CheckWatchListFromCacheDataConsistencyIfRequested|raw$(ctx, "watchlist request for $.type|resource$", c.list, opts, result)
return result, nil
}
klog.Warningf("The watchlist request for $.type|resource$ ended with an error, falling back to the standard LIST semantics, err = %v", err)
}
result, err := c.list(ctx, opts)
if err == nil {
$.CheckListFromCacheDataConsistencyIfRequested|raw$(ctx, "list request for $.type|resource$", c.list, opts, result)
}
return result, err
}
`
var privateListTemplate = `
// list takes label and field selectors, and returns the list of $.resultType|publicPlural$ that match those selectors.
func (c *$.type|privatePlural$) list(ctx context.Context, opts $.ListOptions|raw$) (result *$.resultType|raw$List, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil{
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &$.resultType|raw$List{}
err = c.client.Get().
$if .namespaced$Namespace(c.ns).$end$
err = c.GetClient().Get().
$if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$").
VersionedParams(&opts, $.schemeParameterCodec|raw$).
Timeout(timeout).
@@ -480,8 +626,8 @@ func (c *$.type|privatePlural$) List(ctx context.Context, $.type|private$Name st
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &$.resultType|raw$List{}
err = c.client.Get().
$if .namespaced$Namespace(c.ns).$end$
err = c.GetClient().Get().
$if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$").
Name($.type|private$Name).
SubResource("$.subresourcePath$").
@@ -497,8 +643,8 @@ var getTemplate = `
// Get takes name of the $.type|private$, and returns the corresponding $.resultType|private$ object, and an error if there is any.
func (c *$.type|privatePlural$) Get(ctx context.Context, name string, options $.GetOptions|raw$) (result *$.resultType|raw$, err error) {
result = &$.resultType|raw${}
err = c.client.Get().
$if .namespaced$Namespace(c.ns).$end$
err = c.GetClient().Get().
$if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$").
Name(name).
VersionedParams(&options, $.schemeParameterCodec|raw$).
@@ -512,8 +658,8 @@ var getSubresourceTemplate = `
// Get takes name of the $.type|private$, and returns the corresponding $.resultType|raw$ object, and an error if there is any.
func (c *$.type|privatePlural$) Get(ctx context.Context, $.type|private$Name string, options $.GetOptions|raw$) (result *$.resultType|raw$, err error) {
result = &$.resultType|raw${}
err = c.client.Get().
$if .namespaced$Namespace(c.ns).$end$
err = c.GetClient().Get().
$if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$").
Name($.type|private$Name).
SubResource("$.subresourcePath$").
@@ -527,8 +673,8 @@ func (c *$.type|privatePlural$) Get(ctx context.Context, $.type|private$Name str
var deleteTemplate = `
// Delete takes name of the $.type|private$ and deletes it. Returns an error if one occurs.
func (c *$.type|privatePlural$) Delete(ctx context.Context, name string, opts $.DeleteOptions|raw$) error {
return c.client.Delete().
$if .namespaced$Namespace(c.ns).$end$
return c.GetClient().Delete().
$if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$").
Name(name).
Body(&opts).
@@ -537,30 +683,12 @@ func (c *$.type|privatePlural$) Delete(ctx context.Context, name string, opts $.
}
`
var deleteCollectionTemplate = `
// DeleteCollection deletes a collection of objects.
func (c *$.type|privatePlural$) DeleteCollection(ctx context.Context, opts $.DeleteOptions|raw$, listOpts $.ListOptions|raw$) error {
var timeout time.Duration
if listOpts.TimeoutSeconds != nil{
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
}
return c.client.Delete().
$if .namespaced$Namespace(c.ns).$end$
Resource("$.type|resource$").
VersionedParams(&listOpts, $.schemeParameterCodec|raw$).
Timeout(timeout).
Body(&opts).
Do(ctx).
Error()
}
`
var createSubresourceTemplate = `
// Create takes the representation of a $.inputType|private$ and creates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any.
func (c *$.type|privatePlural$) Create(ctx context.Context, $.type|private$Name string, $.inputType|private$ *$.inputType|raw$, opts $.CreateOptions|raw$) (result *$.resultType|raw$, err error) {
result = &$.resultType|raw${}
err = c.client.Post().
$if .namespaced$Namespace(c.ns).$end$
err = c.GetClient().Post().
$if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$").
Name($.type|private$Name).
SubResource("$.subresourcePath$").
@@ -576,8 +704,8 @@ var createTemplate = `
// Create takes the representation of a $.inputType|private$ and creates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any.
func (c *$.type|privatePlural$) Create(ctx context.Context, $.inputType|private$ *$.inputType|raw$, opts $.CreateOptions|raw$) (result *$.resultType|raw$, err error) {
result = &$.resultType|raw${}
err = c.client.Post().
$if .namespaced$Namespace(c.ns).$end$
err = c.GetClient().Post().
$if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$").
VersionedParams(&opts, $.schemeParameterCodec|raw$).
Body($.inputType|private$).
@@ -591,8 +719,8 @@ var updateSubresourceTemplate = `
// Update takes the top resource name and the representation of a $.inputType|private$ and updates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any.
func (c *$.type|privatePlural$) Update(ctx context.Context, $.type|private$Name string, $.inputType|private$ *$.inputType|raw$, opts $.UpdateOptions|raw$) (result *$.resultType|raw$, err error) {
result = &$.resultType|raw${}
err = c.client.Put().
$if .namespaced$Namespace(c.ns).$end$
err = c.GetClient().Put().
$if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$").
Name($.type|private$Name).
SubResource("$.subresourcePath$").
@@ -608,8 +736,8 @@ var updateTemplate = `
// Update takes the representation of a $.inputType|private$ and updates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any.
func (c *$.type|privatePlural$) Update(ctx context.Context, $.inputType|private$ *$.inputType|raw$, opts $.UpdateOptions|raw$) (result *$.resultType|raw$, err error) {
result = &$.resultType|raw${}
err = c.client.Put().
$if .namespaced$Namespace(c.ns).$end$
err = c.GetClient().Put().
$if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$").
Name($.inputType|private$.Name).
VersionedParams(&opts, $.schemeParameterCodec|raw$).
@@ -620,24 +748,6 @@ func (c *$.type|privatePlural$) Update(ctx context.Context, $.inputType|private$
}
`
var updateStatusTemplate = `
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *$.type|privatePlural$) UpdateStatus(ctx context.Context, $.type|private$ *$.type|raw$, opts $.UpdateOptions|raw$) (result *$.type|raw$, err error) {
result = &$.type|raw${}
err = c.client.Put().
$if .namespaced$Namespace(c.ns).$end$
Resource("$.type|resource$").
Name($.type|private$.Name).
SubResource("status").
VersionedParams(&opts, $.schemeParameterCodec|raw$).
Body($.type|private$).
Do(ctx).
Into(result)
return
}
`
var watchTemplate = `
// Watch returns a $.watchInterface|raw$ that watches the requested $.type|privatePlural$.
func (c *$.type|privatePlural$) Watch(ctx context.Context, opts $.ListOptions|raw$) ($.watchInterface|raw$, error) {
@@ -646,12 +756,30 @@ func (c *$.type|privatePlural$) Watch(ctx context.Context, opts $.ListOptions|ra
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
return c.GetClient().Get().
$if .namespaced$Namespace(c.GetNamespace()).$end$
VersionedParams(&opts, $.schemeParameterCodec|raw$).
Timeout(timeout).
Watch(ctx)
}
`
var watchListTemplate = `
// watchList establishes a watch stream with the server and returns the list of $.resultType|publicPlural$
func (c *$.type|privatePlural$) watchList(ctx context.Context, opts $.ListOptions|raw$) (result *$.resultType|raw$List, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil{
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &$.resultType|raw$List{}
err = c.client.Get().
$if .namespaced$Namespace(c.ns).$end$
Resource("$.type|resource$").
VersionedParams(&opts, $.schemeParameterCodec|raw$).
Timeout(timeout).
Watch(ctx)
WatchList(ctx).
Into(result)
return
}
`
@@ -659,8 +787,8 @@ var patchTemplate = `
// Patch applies the patch and returns the patched $.resultType|private$.
func (c *$.type|privatePlural$) Patch(ctx context.Context, name string, pt $.PatchType|raw$, data []byte, opts $.PatchOptions|raw$, subresources ...string) (result *$.resultType|raw$, err error) {
result = &$.resultType|raw${}
err = c.client.Patch(pt).
$if .namespaced$Namespace(c.ns).$end$
err = c.GetClient().Patch(pt).
$if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$").
Name(name).
SubResource(subresources...).
@@ -688,8 +816,8 @@ func (c *$.type|privatePlural$) Apply(ctx context.Context, $.inputType|private$
return nil, fmt.Errorf("$.inputType|private$.Name must be provided to Apply")
}
result = &$.resultType|raw${}
err = c.client.Patch($.ApplyPatchType|raw$).
$if .namespaced$Namespace(c.ns).$end$
err = c.GetClient().Patch($.ApplyPatchType|raw$).
$if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$").
Name(*name).
VersionedParams(&patchOpts, $.schemeParameterCodec|raw$).
@@ -700,38 +828,6 @@ func (c *$.type|privatePlural$) Apply(ctx context.Context, $.inputType|private$
}
`
var applyStatusTemplate = `
// ApplyStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus().
func (c *$.type|privatePlural$) ApplyStatus(ctx context.Context, $.inputType|private$ *$.inputApplyConfig|raw$, opts $.ApplyOptions|raw$) (result *$.resultType|raw$, err error) {
if $.inputType|private$ == nil {
return nil, fmt.Errorf("$.inputType|private$ provided to Apply must not be nil")
}
patchOpts := opts.ToPatchOptions()
data, err := $.jsonMarshal|raw$($.inputType|private$)
if err != nil {
return nil, err
}
name := $.inputType|private$.Name
if name == nil {
return nil, fmt.Errorf("$.inputType|private$.Name must be provided to Apply")
}
result = &$.resultType|raw${}
err = c.client.Patch($.ApplyPatchType|raw$).
$if .namespaced$Namespace(c.ns).$end$
Resource("$.type|resource$").
Name(*name).
SubResource("status").
VersionedParams(&patchOpts, $.schemeParameterCodec|raw$).
Body(data).
Do(ctx).
Into(result)
return
}
`
var applySubresourceTemplate = `
// Apply takes top resource name and the apply declarative configuration for $.subresourcePath$,
// applies it and returns the applied $.resultType|private$, and an error, if there is any.
@@ -746,8 +842,8 @@ func (c *$.type|privatePlural$) Apply(ctx context.Context, $.type|private$Name s
}
result = &$.resultType|raw${}
err = c.client.Patch($.ApplyPatchType|raw$).
$if .namespaced$Namespace(c.ns).$end$
err = c.GetClient().Patch($.ApplyPatchType|raw$).
$if .namespaced$Namespace(c.GetNamespace()).$end$
Resource("$.type|resource$").
Name($.type|private$Name).
SubResource("$.subresourcePath$").

View File

@@ -20,24 +20,24 @@ import (
"fmt"
"io"
"os"
"path"
"path/filepath"
"strings"
"k8s.io/code-generator/cmd/client-gen/path"
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
"k8s.io/gengo/v2/generator"
"k8s.io/gengo/v2/namer"
"k8s.io/gengo/v2/types"
)
// GenScheme produces a package for a clientset with the scheme, codecs and parameter codecs.
type GenScheme struct {
generator.DefaultGen
OutputPackage string
generator.GoGenerator
OutputPkg 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
@@ -46,7 +46,7 @@ type GenScheme struct {
func (g *GenScheme) Namers(c *generator.Context) namer.NameSystems {
return namer.NameSystems{
"raw": namer.NewRawNamer(g.OutputPackage, g.ImportTracker),
"raw": namer.NewRawNamer(g.OutputPkg, g.ImportTracker),
}
}
@@ -66,14 +66,14 @@ func (g *GenScheme) Imports(c *generator.Context) (imports []string) {
if g.CreateRegistry {
// import the install package for internal clientsets instead of the type package with register.go
if version.Version != "" {
packagePath = filepath.Dir(packagePath)
packagePath = path.Dir(packagePath)
}
packagePath = filepath.Join(packagePath, "install")
packagePath = path.Join(packagePath, "install")
imports = append(imports, fmt.Sprintf("%s \"%s\"", groupAlias, path.Vendorless(packagePath)))
imports = append(imports, fmt.Sprintf("%s \"%s\"", groupAlias, packagePath))
break
} else {
imports = append(imports, fmt.Sprintf("%s%s \"%s\"", groupAlias, strings.ToLower(version.Version.NonEmpty()), path.Vendorless(packagePath)))
imports = append(imports, fmt.Sprintf("%s%s \"%s\"", groupAlias, strings.ToLower(version.Version.NonEmpty()), packagePath))
}
}
}

View File

@@ -21,7 +21,7 @@ import (
"fmt"
"strings"
"k8s.io/gengo/types"
"k8s.io/gengo/v2"
)
var supportedTags = []string{
@@ -192,7 +192,7 @@ func MustParseClientGenTags(lines []string) Tags {
// tags are provided.
func ParseClientGenTags(lines []string) (Tags, error) {
ret := Tags{}
values := types.ExtractCommentTags("+", lines)
values := gengo.ExtractCommentTags("+", lines)
var value []string
value, ret.GenerateClient = values["genclient"]
// Check the old format and error when used to avoid generating client when //+genclient=false

View File

@@ -23,40 +23,44 @@ import (
"github.com/spf13/pflag"
"k8s.io/klog/v2"
generatorargs "k8s.io/code-generator/cmd/client-gen/args"
"k8s.io/code-generator/cmd/client-gen/args"
"k8s.io/code-generator/cmd/client-gen/generators"
"k8s.io/code-generator/pkg/util"
"k8s.io/gengo/v2"
"k8s.io/gengo/v2/generator"
)
func main() {
klog.InitFlags(nil)
genericArgs, customArgs := generatorargs.NewDefaults()
args := args.New()
// 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
args.AddFlags(pflag.CommandLine, "k8s.io/kubernetes/pkg/apis") // TODO: move this input path out of client-gen
flag.Set("logtostderr", "true")
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
pflag.Parse()
// add group version package as input dirs for gengo
for _, pkg := range customArgs.Groups {
inputPkgs := []string{}
for _, pkg := range args.Groups {
for _, v := range pkg.Versions {
genericArgs.InputDirs = append(genericArgs.InputDirs, v.Package)
inputPkgs = append(inputPkgs, v.Package)
}
}
if err := generatorargs.Validate(genericArgs); err != nil {
if err := args.Validate(); err != nil {
klog.Fatalf("Error: %v", err)
}
if err := genericArgs.Execute(
generators.NameSystems(util.PluralExceptionListToMapOrDie(customArgs.PluralExceptions)),
myTargets := func(context *generator.Context) []generator.Target {
return generators.GetTargets(context, args)
}
if err := gengo.Execute(
generators.NameSystems(util.PluralExceptionListToMapOrDie(args.PluralExceptions)),
generators.DefaultNameSystem(),
generators.Packages,
myTargets,
gengo.StdBuildTag,
inputPkgs,
); err != nil {
klog.Fatalf("Error: %v", err)
}

View File

@@ -1,31 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package path
import "strings"
// Vendorless removes the longest match of "*/vendor/" from the front of p.
// It is useful if a package locates in vendor/, e.g.,
// k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/apis/meta/v1, because gengo
// indexes the package with its import path, e.g.,
// k8s.io/apimachinery/pkg/apis/meta/v1,
func Vendorless(p string) string {
if pos := strings.LastIndex(p, "/vendor/"); pos != -1 {
return p[pos+len("/vendor/"):]
}
return p
}

View File

@@ -22,7 +22,7 @@ import (
"sort"
"strings"
"k8s.io/gengo/namer"
"k8s.io/gengo/v2/namer"
)
// ToGroupVersion turns "group/version" string into a GroupVersion struct. It reports error
@@ -116,6 +116,6 @@ func ToGroupInstallPackages(groups []GroupVersions, groupGoNames map[GroupVersio
}
// NormalizeGroupVersion calls normalizes the GroupVersion.
//func NormalizeGroupVersion(gv GroupVersion) GroupVersion {
// return GroupVersion{Group: gv.Group.NonEmpty(), Version: gv.Version, NonEmptyVersion: normalization.Version(gv.Version)}
//}
// func NormalizeGroupVersion(gv GroupVersion) GroupVersion {
// return GroupVersion{Group: gv.Group.NonEmpty(), Version: gv.Version, NonEmptyVersion: normalization.Version(gv.Version)}
// }

View File

@@ -42,7 +42,7 @@ func (g Group) String() string {
}
func (g Group) NonEmpty() string {
if g == "api" {
if g == "" {
return "core"
}
return string(g)
@@ -56,6 +56,8 @@ func (g Group) PackageName() string {
return strings.ToLower(parts[0])
}
type Kind string
type PackageVersion struct {
Version
// The fully qualified package, e.g. k8s.io/kubernetes/pkg/apis/apps, where the types.go is found.
@@ -67,14 +69,24 @@ type GroupVersion struct {
Version Version
}
type GroupVersionKind struct {
Group Group
Version Version
Kind Kind
}
func (gv GroupVersion) ToAPIVersion() string {
if len(gv.Group) > 0 && gv.Group.NonEmpty() != "core" {
if len(gv.Group) > 0 && gv.Group != "" {
return gv.Group.String() + "/" + gv.Version.String()
} else {
return gv.Version.String()
}
}
func (gv GroupVersion) WithKind(kind Kind) GroupVersionKind {
return GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: kind}
}
type GroupVersions struct {
// The name of the package for this group, e.g. apps.
PackageName string