1
0
mirror of https://github.com/kubernetes-sigs/descheduler.git synced 2026-01-28 06:29:29 +01:00

bump k8s.io libs to v0.31.0

Signed-off-by: Amir Alavi <amiralavi7@gmail.com>
This commit is contained in:
Amir Alavi
2024-08-14 14:41:03 -04:00
parent f6fe8fd0bd
commit 33a747096b
2514 changed files with 155767 additions and 88208 deletions

View File

@@ -2,6 +2,7 @@
approvers:
- deads2k
- jpbetz
- wojtek-t
- sttts
reviewers:

View File

@@ -35,6 +35,7 @@ type applyConfigurationGenerator struct {
generator.GoGenerator
// outPkgBase is the base package, under which the "internal" and GV-specific subdirs live
outPkgBase string // must be a Go import-path
localPkg string
groupVersion clientgentypes.GroupVersion
applyConfig applyConfig
imports namer.ImportTracker
@@ -49,9 +50,8 @@ func (g *applyConfigurationGenerator) Filter(_ *generator.Context, t *types.Type
}
func (g *applyConfigurationGenerator) Namers(*generator.Context) namer.NameSystems {
localPkg := path.Join(g.outPkgBase, g.groupVersion.Group.PackageName(), g.groupVersion.Version.PackageName())
return namer.NameSystems{
"raw": namer.NewRawNamer(localPkg, g.imports),
"raw": namer.NewRawNamer(g.localPkg, g.imports),
"singularKind": namer.NewPublicNamer(0),
}
}
@@ -115,6 +115,7 @@ func (g *applyConfigurationGenerator) GenerateType(c *generator.Context, t *type
}
}
g.generateWithFuncs(t, typeParams, sw, nil)
g.generateGetters(t, typeParams, sw, nil)
return sw.Error()
}
@@ -141,6 +142,40 @@ func blocklisted(t *types.Type, member types.Member) bool {
return false
}
func needsGetter(t *types.Type, member types.Member) bool {
// Needed when applying an ApplyConfiguration
return objectMeta.Name == t.Name && member.Name == "Name"
}
func (g *applyConfigurationGenerator) generateGetters(t *types.Type, typeParams TypeParams, sw *generator.SnippetWriter, embed *memberParams) {
for _, member := range t.Members {
if blocklisted(t, member) {
continue
}
memberType := g.refGraph.applyConfigForType(member.Type)
if g.refGraph.isApplyConfig(member.Type) {
memberType = &types.Type{Kind: types.Pointer, Elem: memberType}
}
if jsonTags, ok := lookupJSONTags(member); ok {
memberParams := memberParams{
TypeParams: typeParams,
Member: member,
MemberType: memberType,
JSONTags: jsonTags,
EmbeddedIn: embed,
}
if memberParams.Member.Embedded {
g.generateGetters(member.Type, typeParams, sw, &memberParams)
continue
}
if needsGetter(t, member) {
g.generateMemberGetter(sw, memberParams)
}
}
}
}
func (g *applyConfigurationGenerator) generateWithFuncs(t *types.Type, typeParams TypeParams, sw *generator.SnippetWriter, embed *memberParams) {
for _, member := range t.Members {
if blocklisted(t, member) {
@@ -195,7 +230,7 @@ func (g *applyConfigurationGenerator) generateWithFuncs(t *types.Type, typeParam
}
func (g *applyConfigurationGenerator) generateStruct(sw *generator.SnippetWriter, typeParams TypeParams) {
sw.Do("// $.ApplyConfig.ApplyConfiguration|public$ represents an declarative configuration of the $.ApplyConfig.Type|public$ type for use\n", typeParams)
sw.Do("// $.ApplyConfig.ApplyConfiguration|public$ represents a declarative configuration of the $.ApplyConfig.Type|public$ type for use\n", typeParams)
sw.Do("// with apply.\n", typeParams)
sw.Do("type $.ApplyConfig.ApplyConfiguration|public$ struct {\n", typeParams)
for _, structMember := range typeParams.Struct.Members {
@@ -244,7 +279,7 @@ func (g *applyConfigurationGenerator) generateMemberWith(sw *generator.SnippetWr
sw.Do("// and returns the receiver, so that objects can be built by chaining \"With\" function invocations.\n", memberParams)
sw.Do("// If called multiple times, the $.Member.Name$ field is set to the value of the last call.\n", memberParams)
sw.Do("func (b *$.ApplyConfig.ApplyConfiguration|public$) With$.Member.Name$(value $.MemberType|raw$) *$.ApplyConfig.ApplyConfiguration|public$ {\n", memberParams)
g.ensureEnbedExistsIfApplicable(sw, memberParams)
g.ensureEmbedExistsIfApplicable(sw, memberParams)
if g.refGraph.isApplyConfig(memberParams.Member.Type) || isNillable(memberParams.Member.Type) {
sw.Do("b.$.Member.Name$ = value\n", memberParams)
} else {
@@ -254,6 +289,18 @@ func (g *applyConfigurationGenerator) generateMemberWith(sw *generator.SnippetWr
sw.Do("}\n", memberParams)
}
func (g *applyConfigurationGenerator) generateMemberGetter(sw *generator.SnippetWriter, memberParams memberParams) {
sw.Do("// Get$.Member.Name$ retrieves the value of the $.Member.Name$ field in the declarative configuration.\n", memberParams)
if g.refGraph.isApplyConfig(memberParams.Member.Type) || isNillable(memberParams.Member.Type) {
sw.Do("func (b *$.ApplyConfig.ApplyConfiguration|public$) Get$.Member.Name$() $.MemberType|raw$ {\n", memberParams)
} else {
sw.Do("func (b *$.ApplyConfig.ApplyConfiguration|public$) Get$.Member.Name$() *$.MemberType|raw$ {\n", memberParams)
}
g.ensureEmbedExistsIfApplicable(sw, memberParams)
sw.Do(" return b.$.Member.Name$\n", memberParams)
sw.Do("}\n", memberParams)
}
func (g *applyConfigurationGenerator) generateMemberWithForSlice(sw *generator.SnippetWriter, member types.Member, memberParams memberParams) {
memberIsPointerToSlice := member.Type.Kind == types.Pointer
if memberIsPointerToSlice {
@@ -264,7 +311,7 @@ func (g *applyConfigurationGenerator) generateMemberWithForSlice(sw *generator.S
sw.Do("// and returns the receiver, so that objects can be build by chaining \"With\" function invocations.\n", memberParams)
sw.Do("// If called multiple times, values provided by each call will be appended to the $.Member.Name$ field.\n", memberParams)
sw.Do("func (b *$.ApplyConfig.ApplyConfiguration|public$) With$.Member.Name$(values ...$.ArgType|raw$) *$.ApplyConfig.ApplyConfiguration|public$ {\n", memberParams)
g.ensureEnbedExistsIfApplicable(sw, memberParams)
g.ensureEmbedExistsIfApplicable(sw, memberParams)
if memberIsPointerToSlice {
sw.Do("b.ensure$.MemberType.Elem|public$Exists()\n", memberParams)
@@ -299,7 +346,7 @@ func (g *applyConfigurationGenerator) generateMemberWithForMap(sw *generator.Sni
sw.Do("// If called multiple times, the entries provided by each call will be put on the $.Member.Name$ field,\n", memberParams)
sw.Do("// overwriting an existing map entries in $.Member.Name$ field with the same key.\n", memberParams)
sw.Do("func (b *$.ApplyConfig.ApplyConfiguration|public$) With$.Member.Name$(entries $.MemberType|raw$) *$.ApplyConfig.ApplyConfiguration|public$ {\n", memberParams)
g.ensureEnbedExistsIfApplicable(sw, memberParams)
g.ensureEmbedExistsIfApplicable(sw, memberParams)
sw.Do(" if b.$.Member.Name$ == nil && len(entries) > 0 {\n", memberParams)
sw.Do(" b.$.Member.Name$ = make($.MemberType|raw$, len(entries))\n", memberParams)
sw.Do(" }\n", memberParams)
@@ -310,7 +357,7 @@ func (g *applyConfigurationGenerator) generateMemberWithForMap(sw *generator.Sni
sw.Do("}\n", memberParams)
}
func (g *applyConfigurationGenerator) ensureEnbedExistsIfApplicable(sw *generator.SnippetWriter, memberParams memberParams) {
func (g *applyConfigurationGenerator) ensureEmbedExistsIfApplicable(sw *generator.SnippetWriter, memberParams memberParams) {
// Embedded types that are not inlined must be nillable so they are not included in the apply configuration
// when all their fields are omitted.
if memberParams.EmbeddedIn != nil && !memberParams.EmbeddedIn.JSONTags.inline {
@@ -335,8 +382,8 @@ func (b *$.ApplyConfig.ApplyConfiguration|public$) ensure$.MemberType.Elem|publi
`
var clientgenTypeConstructorNamespaced = `
// $.ApplyConfig.Type|public$ constructs an declarative configuration of the $.ApplyConfig.Type|public$ type for use with
// apply.
// $.ApplyConfig.Type|public$ constructs a declarative configuration of the $.ApplyConfig.Type|public$ type for use with
// apply.
func $.ApplyConfig.Type|public$(name, namespace string) *$.ApplyConfig.ApplyConfiguration|public$ {
b := &$.ApplyConfig.ApplyConfiguration|public${}
b.WithName(name)
@@ -348,7 +395,7 @@ func $.ApplyConfig.Type|public$(name, namespace string) *$.ApplyConfig.ApplyConf
`
var clientgenTypeConstructorNonNamespaced = `
// $.ApplyConfig.Type|public$ constructs an declarative configuration of the $.ApplyConfig.Type|public$ type for use with
// $.ApplyConfig.Type|public$ constructs a declarative configuration of the $.ApplyConfig.Type|public$ type for use with
// apply.
func $.ApplyConfig.Type|public$(name string) *$.ApplyConfig.ApplyConfiguration|public$ {
b := &$.ApplyConfig.ApplyConfiguration|public${}
@@ -360,7 +407,7 @@ func $.ApplyConfig.Type|public$(name string) *$.ApplyConfig.ApplyConfiguration|p
`
var constructorWithTypeMeta = `
// $.ApplyConfig.ApplyConfiguration|public$ constructs an declarative configuration of the $.ApplyConfig.Type|public$ type for use with
// $.ApplyConfig.ApplyConfiguration|public$ constructs a declarative configuration of the $.ApplyConfig.Type|public$ type for use with
// apply.
func $.ApplyConfig.Type|public$() *$.ApplyConfig.ApplyConfiguration|public$ {
b := &$.ApplyConfig.ApplyConfiguration|public${}
@@ -371,7 +418,7 @@ func $.ApplyConfig.Type|public$() *$.ApplyConfig.ApplyConfiguration|public$ {
`
var constructor = `
// $.ApplyConfig.ApplyConfiguration|public$ constructs an declarative configuration of the $.ApplyConfig.Type|public$ type for use with
// $.ApplyConfig.ApplyConfiguration|public$ constructs a declarative configuration of the $.ApplyConfig.Type|public$ type for use with
// apply.
func $.ApplyConfig.Type|public$() *$.ApplyConfig.ApplyConfiguration|public$ {
return &$.ApplyConfig.ApplyConfiguration|public${}

View File

@@ -23,6 +23,8 @@ import (
"strings"
openapiv2 "github.com/google/gnostic-models/openapiv2"
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
"k8s.io/gengo/v2/types"
utilproto "k8s.io/kube-openapi/pkg/util/proto"
"k8s.io/kube-openapi/pkg/validation/spec"
@@ -30,11 +32,7 @@ import (
type typeModels struct {
models utilproto.Models
gvkToOpenAPIType map[gvk]string
}
type gvk struct {
group, version, kind string
gvkToOpenAPIType map[clientgentypes.GroupVersionKind]string
}
func newTypeModels(openAPISchemaFilePath string, pkgTypes map[string]*types.Package) (*typeModels, error) {
@@ -56,7 +54,7 @@ func newTypeModels(openAPISchemaFilePath string, pkgTypes map[string]*types.Pack
// Build a mapping from openAPI type name to GVK.
// Find the root types needed by by client-go for apply.
gvkToOpenAPIType := map[gvk]string{}
gvkToOpenAPIType := map[clientgentypes.GroupVersionKind]string{}
rootDefs := map[string]spec.Schema{}
for _, p := range pkgTypes {
gv := groupVersion(p)
@@ -65,11 +63,7 @@ func newTypeModels(openAPISchemaFilePath string, pkgTypes map[string]*types.Pack
hasApply := tags.HasVerb("apply") || tags.HasVerb("applyStatus")
if tags.GenerateClient && hasApply {
openAPIType := friendlyName(typeName(t))
gvk := gvk{
group: gv.Group.String(),
version: gv.Version.String(),
kind: t.Name.Name,
}
gvk := gv.WithKind(clientgentypes.Kind(t.Name.Name))
rootDefs[openAPIType] = openAPISchema.Definitions[openAPIType]
gvkToOpenAPIType[gvk] = openAPIType
}
@@ -94,7 +88,7 @@ func newTypeModels(openAPISchemaFilePath string, pkgTypes map[string]*types.Pack
var emptyModels = &typeModels{
models: &utilproto.Definitions{},
gvkToOpenAPIType: map[gvk]string{},
gvkToOpenAPIType: map[clientgentypes.GroupVersionKind]string{},
}
func toValidatedModels(openAPISchema *spec.Swagger) (utilproto.Models, error) {

View File

@@ -86,10 +86,14 @@ func GetTargets(context *generator.Context, args *args.Args) []generator.Target
klog.V(5).Infof("skipping type %v because does not have ObjectMeta", t)
continue
}
gvk := gv.WithKind(clientgentypes.Kind(t.Name.Name))
openAPIName := typeModels.gvkToOpenAPIType[gvk]
if typePkg, ok := refs[t.Name]; ok {
toGenerate = append(toGenerate, applyConfig{
Type: t,
ApplyConfiguration: types.Ref(typePkg, t.Name.Name+ApplyConfigurationTypeSuffix),
OpenAPIName: openAPIName,
})
}
}
@@ -132,7 +136,7 @@ func GetTargets(context *generator.Context, args *args.Args) []generator.Target
// generate ForKind() utility function
targetList = append(targetList,
targetForUtils(args.OutputDir, args.OutputPkg,
boilerplate, groupVersions, applyConfigsForGroupVersion, groupGoNames))
boilerplate, groupVersions, applyConfigsForGroupVersion, groupGoNames, typeModels))
// generate internal embedded schema, required for generated Extract functions
targetList = append(targetList,
targetForInternal(args.OutputDir, args.OutputPkg,
@@ -171,11 +175,7 @@ func targetForApplyConfigurationsPackage(outputDirBase, outputPkgBase, pkgSubdir
GeneratorsFunc: func(c *generator.Context) (generators []generator.Generator) {
for _, toGenerate := range typesToGenerate {
var openAPIType *string
gvk := gvk{
group: gv.Group.String(),
version: gv.Version.String(),
kind: toGenerate.Type.Name.Name,
}
gvk := gv.WithKind(clientgentypes.Kind(toGenerate.Type.Name.Name))
if v, ok := models.gvkToOpenAPIType[gvk]; ok {
openAPIType = &v
}
@@ -185,6 +185,7 @@ func targetForApplyConfigurationsPackage(outputDirBase, outputPkgBase, pkgSubdir
OutputFilename: strings.ToLower(toGenerate.Type.Name.Name) + ".go",
},
outPkgBase: outputPkgBase,
localPkg: outputPkg,
groupVersion: gv,
applyConfig: toGenerate,
imports: generator.NewImportTracker(),
@@ -197,7 +198,8 @@ func targetForApplyConfigurationsPackage(outputDirBase, outputPkgBase, pkgSubdir
}
}
func targetForUtils(outputDirBase, outputPkgBase string, boilerplate []byte, groupVersions map[string]clientgentypes.GroupVersions, applyConfigsForGroupVersion map[clientgentypes.GroupVersion][]applyConfig, groupGoNames map[string]string) generator.Target {
func targetForUtils(outputDirBase, outputPkgBase string, boilerplate []byte, groupVersions map[string]clientgentypes.GroupVersions,
applyConfigsForGroupVersion map[clientgentypes.GroupVersion][]applyConfig, groupGoNames map[string]string, models *typeModels) generator.Target {
return &generator.SimpleTarget{
PkgName: path.Base(outputPkgBase),
PkgPath: outputPkgBase,
@@ -213,6 +215,7 @@ func targetForUtils(outputDirBase, outputPkgBase string, boilerplate []byte, gro
groupVersions: groupVersions,
typesForGroupVersion: applyConfigsForGroupVersion,
groupGoNames: groupGoNames,
typeModels: models,
})
return generators
},

View File

@@ -19,15 +19,17 @@ package generators
import "k8s.io/gengo/v2/types"
var (
applyConfiguration = types.Ref("k8s.io/apimachinery/pkg/runtime", "ApplyConfiguration")
groupVersionKind = types.Ref("k8s.io/apimachinery/pkg/runtime/schema", "GroupVersionKind")
typeMeta = types.Ref("k8s.io/apimachinery/pkg/apis/meta/v1", "TypeMeta")
objectMeta = types.Ref("k8s.io/apimachinery/pkg/apis/meta/v1", "ObjectMeta")
rawExtension = types.Ref("k8s.io/apimachinery/pkg/runtime", "RawExtension")
unknown = types.Ref("k8s.io/apimachinery/pkg/runtime", "Unknown")
extractInto = types.Ref("k8s.io/apimachinery/pkg/util/managedfields", "ExtractInto")
smdNewParser = types.Ref("sigs.k8s.io/structured-merge-diff/v4/typed", "NewParser")
smdParser = types.Ref("sigs.k8s.io/structured-merge-diff/v4/typed", "Parser")
yamlObject = types.Ref("sigs.k8s.io/structured-merge-diff/v4/typed", "YAMLObject")
yamlUnmarshal = types.Ref("gopkg.in/yaml.v2", "Unmarshal")
applyConfiguration = types.Ref("k8s.io/apimachinery/pkg/runtime", "ApplyConfiguration")
groupVersionKind = types.Ref("k8s.io/apimachinery/pkg/runtime/schema", "GroupVersionKind")
typeMeta = types.Ref("k8s.io/apimachinery/pkg/apis/meta/v1", "TypeMeta")
objectMeta = types.Ref("k8s.io/apimachinery/pkg/apis/meta/v1", "ObjectMeta")
rawExtension = types.Ref("k8s.io/apimachinery/pkg/runtime", "RawExtension")
unknown = types.Ref("k8s.io/apimachinery/pkg/runtime", "Unknown")
extractInto = types.Ref("k8s.io/apimachinery/pkg/util/managedfields", "ExtractInto")
runtimeScheme = types.Ref("k8s.io/apimachinery/pkg/runtime", "Scheme")
smdNewParser = types.Ref("sigs.k8s.io/structured-merge-diff/v4/typed", "NewParser")
smdParser = types.Ref("sigs.k8s.io/structured-merge-diff/v4/typed", "Parser")
testingTypeConverter = types.Ref("k8s.io/client-go/testing", "TypeConverter")
yamlObject = types.Ref("sigs.k8s.io/structured-merge-diff/v4/typed", "YAMLObject")
yamlUnmarshal = types.Ref("gopkg.in/yaml.v2", "Unmarshal")
)

View File

@@ -18,6 +18,7 @@ package generators
import (
"io"
"path"
"sort"
"strings"
@@ -37,6 +38,7 @@ type utilGenerator struct {
groupGoNames map[string]string
typesForGroupVersion map[clientgentypes.GroupVersion][]applyConfig
filtered bool
typeModels *typeModels
}
var _ generator.Generator = &utilGenerator{}
@@ -92,6 +94,7 @@ func (v versionSort) Swap(i, j int) { v[i], v[j] = v[j], v[i] }
type applyConfig struct {
Type *types.Type
ApplyConfiguration *types.Type
OpenAPIName string
}
type applyConfigSort []applyConfig
@@ -133,16 +136,26 @@ func (g *utilGenerator) GenerateType(c *generator.Context, _ *types.Type, w io.W
sort.Sort(groupSort(groups))
m := map[string]interface{}{
"applyConfiguration": applyConfiguration,
"groups": groups,
"internalParser": types.Ref(path.Join(g.outputPackage, "internal"), "Parser"),
"runtimeScheme": runtimeScheme,
"schemeGVs": schemeGVs,
"schemaGroupVersionKind": groupVersionKind,
"applyConfiguration": applyConfiguration,
"testingTypeConverter": testingTypeConverter,
}
sw.Do(forKindFunc, m)
sw.Do(typeConverter, m)
return sw.Error()
}
var typeConverter = `
func NewTypeConverter(scheme *{{.runtimeScheme|raw}}) *{{.testingTypeConverter|raw}} {
return &{{.testingTypeConverter|raw}}{Scheme: scheme, TypeResolver: {{.internalParser|raw}}()}
}
`
var forKindFunc = `
// ForKind returns an apply configuration type for the given GroupVersionKind, or nil if no
// apply configuration type exists for the given GroupVersionKind.

View File

@@ -405,7 +405,7 @@ func GetTargets(context *generator.Context, args *args.Args) []generator.Target
targetForScheme(args, clientsetDir, clientsetPkg, groupGoNames, boilerplate))
if args.FakeClient {
targetList = append(targetList,
fake.TargetForClientset(args, clientsetDir, clientsetPkg, groupGoNames, boilerplate))
fake.TargetForClientset(args, clientsetDir, clientsetPkg, args.ApplyConfigurationPackage, groupGoNames, boilerplate))
}
// If --clientset-only=true, we don't regenerate the individual typed clients.

View File

@@ -88,7 +88,7 @@ func TargetForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, clie
}
}
func TargetForClientset(args *args.Args, clientsetDir, clientsetPkg string, groupGoNames map[clientgentypes.GroupVersion]string, boilerplate []byte) generator.Target {
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.
@@ -108,11 +108,12 @@ func TargetForClientset(args *args.Args, clientsetDir, clientsetPkg string, grou
GoGenerator: generator.GoGenerator{
OutputFilename: "clientset_generated.go",
},
groups: args.Groups,
groupGoNames: groupGoNames,
fakeClientsetPackage: clientsetPkg,
imports: generator.NewImportTracker(),
realClientsetPackage: clientsetPkg,
groups: args.Groups,
groupGoNames: groupGoNames,
fakeClientsetPackage: clientsetPkg,
imports: generator.NewImportTracker(),
realClientsetPackage: clientsetPkg,
applyConfigurationPackage: applyConfigurationPkg,
},
&scheme.GenScheme{
GoGenerator: generator.GoGenerator{

View File

@@ -37,7 +37,8 @@ type genClientset struct {
imports namer.ImportTracker
clientsetGenerated bool
// the import path of the generated real clientset.
realClientsetPackage string // must be a Go import-path
realClientsetPackage string // must be a Go import-path
applyConfigurationPackage string
}
var _ generator.Generator = &genClientset{}
@@ -76,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, "$", "$")
@@ -89,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 {
@@ -107,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

@@ -21,6 +21,9 @@ import (
"path"
"strings"
"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"
@@ -43,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 }
@@ -119,33 +124,31 @@ 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
@@ -299,9 +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 {
//nolint:staticcheck
// TODO: convert this to use golang.org/x/text/cases
return strings.ReplaceAll(template, " "+strings.Title(verbType), " "+name)
return strings.ReplaceAll(template, " "+titler.String(verbType), " "+name)
}
// template for the struct that implements the type's interface
@@ -332,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
}
@@ -345,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)
@@ -369,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
}
@@ -382,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
}
@@ -405,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
@@ -415,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
}
@@ -428,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
}
@@ -441,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
}
@@ -454,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
}
@@ -467,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
}
@@ -482,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
}
@@ -510,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
}
@@ -535,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
}
@@ -560,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

@@ -71,31 +71,25 @@ func (g *genGroup) Imports(c *generator.Context) (imports []string) {
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(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"}),

View File

@@ -21,6 +21,8 @@ import (
"path"
"strings"
"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"
@@ -44,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
@@ -119,13 +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 {
//nolint:staticcheck
// TODO: convert this to use golang.org/x/text/cases
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 {
//nolint:staticcheck
// TODO: convert this to use golang.org/x/text/cases
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,
@@ -148,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: path.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 {
@@ -206,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 {
@@ -298,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)
}
}
@@ -348,9 +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 {
//nolint:staticcheck
// TODO: convert this to use golang.org/x/text/cases
return strings.ReplaceAll(template, " "+strings.Title(verbType), " "+name)
return strings.ReplaceAll(template, " "+titler.String(verbType), " "+name)
}
func generateInterface(defaultVerbTemplates map[string]string, tags util.Tags) string {
@@ -379,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)`,
@@ -391,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
}
@@ -423,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).
@@ -485,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$").
@@ -502,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$).
@@ -517,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$").
@@ -532,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).
@@ -542,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$").
@@ -581,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$).
@@ -596,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$").
@@ -613,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$).
@@ -625,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) {
@@ -651,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
}
`
@@ -664,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...).
@@ -693,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$).
@@ -705,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.
@@ -751,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

@@ -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

View File

@@ -37,6 +37,11 @@ func (n localNamer) Name(t *types.Type) string {
if len(n.localPackage.Package) != 0 && n.localPackage.Package == t.Name.Package {
return t.Name.Name
}
// For non-local and non-fundamental types, use an absolute reference
// see https://protobuf.com/docs/language-spec#type-references
if strings.Contains(t.Name.Package, ".") {
return fmt.Sprintf(".%s", t.Name)
}
return t.Name.String()
}

View File

@@ -299,7 +299,8 @@ type SharedInformerFactory interface {
// Start initializes all requested informers. They are handled in goroutines
// which run until the stop channel gets closed.
Start(stopCh <-chan struct{})
// Warning: Start does not block. When run in a go-routine, it will race with a later WaitForCacheSync.
Start(stopCh <-chan struct{})
// Shutdown marks a factory as shutting down. At that point no new
// informers can be started anymore and Start will return without

View File

@@ -215,6 +215,7 @@ func (g *listerGenerator) Imports(c *generator.Context) (imports []string) {
imports = append(imports, g.imports.ImportLines()...)
imports = append(imports, "k8s.io/apimachinery/pkg/api/errors")
imports = append(imports, "k8s.io/apimachinery/pkg/labels")
imports = append(imports, "k8s.io/client-go/listers")
// for Indexer
imports = append(imports, "k8s.io/client-go/tools/cache")
return
@@ -243,18 +244,14 @@ func (g *listerGenerator) GenerateType(c *generator.Context, t *types.Type, w io
sw.Do(typeListerStruct, m)
sw.Do(typeListerConstructor, m)
sw.Do(typeListerList, m)
if tags.NonNamespaced {
sw.Do(typeListerNonNamespacedGet, m)
return sw.Error()
}
sw.Do(typeListerNamespaceLister, m)
sw.Do(namespaceListerInterface, m)
sw.Do(namespaceListerStruct, m)
sw.Do(namespaceListerList, m)
sw.Do(namespaceListerGet, m)
return sw.Error()
}
@@ -286,48 +283,27 @@ type $.type|public$Lister interface {
}
`
// This embeds a typed resource indexer instead of aliasing, so that the struct
// is available as a receiver for methods specific to the generated type
// (from the corresponding expansion interface).
var typeListerStruct = `
// $.type|private$Lister implements the $.type|public$Lister interface.
type $.type|private$Lister struct {
indexer cache.Indexer
listers.ResourceIndexer[*$.type|raw$]
}
`
var typeListerConstructor = `
// New$.type|public$Lister returns a new $.type|public$Lister.
func New$.type|public$Lister(indexer cache.Indexer) $.type|public$Lister {
return &$.type|private$Lister{indexer: indexer}
}
`
var typeListerList = `
// List lists all $.type|publicPlural$ in the indexer.
func (s *$.type|private$Lister) List(selector labels.Selector) (ret []*$.type|raw$, err error) {
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
ret = append(ret, m.(*$.type|raw$))
})
return ret, err
return &$.type|private$Lister{listers.New[*$.type|raw$](indexer, $.Resource|raw$("$.type|lowercaseSingular$"))}
}
`
var typeListerNamespaceLister = `
// $.type|publicPlural$ returns an object that can list and get $.type|publicPlural$.
func (s *$.type|private$Lister) $.type|publicPlural$(namespace string) $.type|public$NamespaceLister {
return $.type|private$NamespaceLister{indexer: s.indexer, namespace: namespace}
}
`
var typeListerNonNamespacedGet = `
// Get retrieves the $.type|public$ from the index for a given name.
func (s *$.type|private$Lister) Get(name string) (*$.type|raw$, error) {
obj, exists, err := s.indexer.GetByKey(name)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound($.Resource|raw$("$.type|lowercaseSingular$"), name)
}
return obj.(*$.type|raw$), nil
return $.type|private$NamespaceLister{listers.NewNamespaced[*$.type|raw$](s.ResourceIndexer, namespace)}
}
`
@@ -345,35 +321,13 @@ type $.type|public$NamespaceLister interface {
}
`
// This embeds a typed namespaced resource indexer instead of aliasing, so that the struct
// is available as a receiver for methods specific to the generated type
// (from the corresponding expansion interface).
var namespaceListerStruct = `
// $.type|private$NamespaceLister implements the $.type|public$NamespaceLister
// interface.
type $.type|private$NamespaceLister struct {
indexer cache.Indexer
namespace string
}
`
var namespaceListerList = `
// List lists all $.type|publicPlural$ in the indexer for a given namespace.
func (s $.type|private$NamespaceLister) List(selector labels.Selector) (ret []*$.type|raw$, err error) {
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
ret = append(ret, m.(*$.type|raw$))
})
return ret, err
}
`
var namespaceListerGet = `
// Get retrieves the $.type|public$ from the indexer for a given namespace and name.
func (s $.type|private$NamespaceLister) Get(name string) (*$.type|raw$, error) {
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound($.Resource|raw$("$.type|lowercaseSingular$"), name)
}
return obj.(*$.type|raw$), nil
listers.ResourceIndexer[*$.type|raw$]
}
`

View File

@@ -121,7 +121,7 @@ function kube::codegen::gen_helpers() {
input_pkgs+=("${pkg}")
done < <(
( kube::codegen::internal::grep -l --null \
-e '+k8s:deepcopy-gen=' \
-e '^\s*//\s*+k8s:deepcopy-gen=' \
-r "${in_dir}" \
--include '*.go' \
|| true \
@@ -153,7 +153,7 @@ function kube::codegen::gen_helpers() {
input_pkgs+=("${pkg}")
done < <(
( kube::codegen::internal::grep -l --null \
-e '+k8s:defaulter-gen=' \
-e '^\s*//\s*+k8s:defaulter-gen=' \
-r "${in_dir}" \
--include '*.go' \
|| true \
@@ -185,7 +185,7 @@ function kube::codegen::gen_helpers() {
input_pkgs+=("${pkg}")
done < <(
( kube::codegen::internal::grep -l --null \
-e '+k8s:conversion-gen=' \
-e '^\s*//\s*+k8s:conversion-gen=' \
-r "${in_dir}" \
--include '*.go' \
|| true \
@@ -338,7 +338,7 @@ function kube::codegen::gen_openapi() {
input_pkgs+=("${pkg}")
done < <(
( kube::codegen::internal::grep -l --null \
-e '+k8s:openapi-gen=' \
-e '^\s*//\s*+k8s:openapi-gen=' \
-r "${in_dir}" \
--include '*.go' \
|| true \
@@ -443,6 +443,7 @@ function kube::codegen::gen_client() {
local applyconfig="false"
local applyconfig_subdir="applyconfiguration"
local applyconfig_external=""
local applyconfig_openapi_schema=""
local watchable="false"
local listers_subdir="listers"
local informers_subdir="informers"
@@ -488,6 +489,10 @@ function kube::codegen::gen_client() {
applyconfig_external="$2"
shift 2
;;
"--applyconfig-openapi-schema")
applyconfig_openapi_schema="$2"
shift 2
;;
"--with-watch")
watchable="true"
shift
@@ -563,7 +568,7 @@ function kube::codegen::gen_client() {
fi
done < <(
( kube::codegen::internal::grep -l --null \
-e '+genclient' \
-e '^\s*//\s*+genclient' \
-r "${in_dir}${one_input_api}" \
--include '*.go' \
|| true \
@@ -594,6 +599,7 @@ function kube::codegen::gen_client() {
--output-dir "${out_dir}/${applyconfig_subdir}" \
--output-pkg "${applyconfig_pkg}" \
--external-applyconfigurations "${applyconfig_external}" \
--openapi-schema "${applyconfig_openapi_schema}" \
"${input_pkgs[@]}"
fi
@@ -659,3 +665,95 @@ function kube::codegen::gen_client() {
"${input_pkgs[@]}"
fi
}
# Generate register code
#
# USAGE: kube::codegen::gen_register [FLAGS] <input-dir>
#
# <input-dir>
# The root directory under which to search for Go files which request code to
# be generated. This must be a local path, not a Go package.
#
# See note at the top about package structure below that.
#
# FLAGS:
#
# --boilerplate <string = path_to_kube_codegen_boilerplate>
# An optional override for the header file to insert into generated files.
#
function kube::codegen::gen_register() {
local in_dir=""
local boilerplate="${KUBE_CODEGEN_ROOT}/hack/boilerplate.go.txt"
local v="${KUBE_VERBOSE:-0}"
while [ "$#" -gt 0 ]; do
case "$1" in
"--boilerplate")
boilerplate="$2"
shift 2
;;
*)
if [[ "$1" =~ ^-- ]]; then
echo "unknown argument: $1" >&2
return 1
fi
if [ -n "$in_dir" ]; then
echo "too many arguments: $1 (already have $in_dir)" >&2
return 1
fi
in_dir="$1"
shift
;;
esac
done
if [ -z "${in_dir}" ]; then
echo "input-dir argument is required" >&2
return 1
fi
(
# To support running this from anywhere, first cd into this directory,
# and then install with forced module mode on and fully qualified name.
cd "${KUBE_CODEGEN_ROOT}"
BINS=(
register-gen
)
# shellcheck disable=2046 # printf word-splitting is intentional
GO111MODULE=on go install $(printf "k8s.io/code-generator/cmd/%s " "${BINS[@]}")
)
# Go installs in $GOBIN if defined, and $GOPATH/bin otherwise
gobin="${GOBIN:-$(go env GOPATH)/bin}"
# Register
#
local input_pkgs=()
while read -r dir; do
pkg="$(cd "${dir}" && GO111MODULE=on go list -find .)"
input_pkgs+=("${pkg}")
done < <(
( kube::codegen::internal::grep -l --null \
-e '^\s*//\s*+groupName' \
-r "${in_dir}" \
--include '*.go' \
|| true \
) | while read -r -d $'\0' F; do dirname "${F}"; done \
| LC_ALL=C sort -u
)
if [ "${#input_pkgs[@]}" != 0 ]; then
echo "Generating register code for ${#input_pkgs[@]} targets"
kube::codegen::internal::findz \
"${in_dir}" \
-type f \
-name zz_generated.register.go \
| xargs -0 rm -f
"${gobin}/register-gen" \
-v "${v}" \
--output-file zz_generated.register.go \
--go-header-file "${boilerplate}" \
"${input_pkgs[@]}"
fi
}

View File

@@ -31,4 +31,5 @@ import (
_ "k8s.io/code-generator/cmd/informer-gen"
_ "k8s.io/code-generator/cmd/lister-gen"
_ "k8s.io/code-generator/cmd/register-gen"
_ "k8s.io/kube-openapi/cmd/openapi-gen"
)