client-gen: create private registry for fake clientset

pull/6/head
Dr. Stefan Schimanski 2017-02-25 09:52:11 +01:00
parent 49d1814b3a
commit ee8ce696d6
6 changed files with 124 additions and 68 deletions

View File

@ -28,6 +28,7 @@ import (
"k8s.io/gengo/types" "k8s.io/gengo/types"
clientgenargs "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/args" clientgenargs "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/args"
"k8s.io/kubernetes/cmd/libs/go2idl/client-gen/generators/fake" "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/generators/fake"
"k8s.io/kubernetes/cmd/libs/go2idl/client-gen/generators/scheme"
clientgentypes "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types" clientgentypes "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types"
"github.com/golang/glog" "github.com/golang/glog"
@ -158,6 +159,19 @@ func packageForClientset(customArgs clientgenargs.Args, clientsetPackage string,
func packageForScheme(customArgs clientgenargs.Args, clientsetPackage string, srcTreePath string, boilerplate []byte, generatedBy string) generator.Package { func packageForScheme(customArgs clientgenargs.Args, clientsetPackage string, srcTreePath string, boilerplate []byte, generatedBy string) generator.Package {
schemePackage := filepath.Join(clientsetPackage, "scheme") schemePackage := filepath.Join(clientsetPackage, "scheme")
// create runtime.Registry for internal client because it has to know about group versions
internalClient := false
NextGroup:
for _, group := range customArgs.Groups {
for _, v := range group.Versions {
if v == "" {
internalClient = true
break NextGroup
}
}
}
return &generator.DefaultPackage{ return &generator.DefaultPackage{
PackageName: "scheme", PackageName: "scheme",
PackagePath: schemePackage, PackagePath: schemePackage,
@ -173,15 +187,16 @@ func packageForScheme(customArgs clientgenargs.Args, clientsetPackage string, sr
// Always generate a "doc.go" file. // Always generate a "doc.go" file.
generator.DefaultGen{OptionalName: "doc"}, generator.DefaultGen{OptionalName: "doc"},
&genScheme{ &scheme.GenScheme{
DefaultGen: generator.DefaultGen{ DefaultGen: generator.DefaultGen{
OptionalName: "register", OptionalName: "register",
}, },
inputPackages: customArgs.GroupVersionToInputPath, InputPackages: customArgs.GroupVersionToInputPath,
outputPackage: schemePackage, OutputPackage: schemePackage,
outputPath: filepath.Join(srcTreePath, schemePackage), OutputPath: filepath.Join(srcTreePath, schemePackage),
groups: customArgs.Groups, Groups: customArgs.Groups,
imports: generator.NewImportTracker(), ImportTracker: generator.NewImportTracker(),
CreateRegistry: internalClient,
}, },
} }
return generators return generators

View File

@ -25,6 +25,7 @@ import (
"k8s.io/gengo/generator" "k8s.io/gengo/generator"
"k8s.io/gengo/types" "k8s.io/gengo/types"
clientgenargs "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/args" clientgenargs "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/args"
scheme "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/generators/scheme"
clientgentypes "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types" clientgentypes "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types"
) )
@ -118,6 +119,17 @@ func PackageForClientset(customArgs clientgenargs.Args, fakeClientsetPackage str
imports: generator.NewImportTracker(), imports: generator.NewImportTracker(),
realClientsetPackage: filepath.Join(customArgs.ClientsetOutputPath, customArgs.ClientsetName), realClientsetPackage: filepath.Join(customArgs.ClientsetOutputPath, customArgs.ClientsetName),
}, },
&scheme.GenScheme{
DefaultGen: generator.DefaultGen{
OptionalName: "register",
},
InputPackages: customArgs.GroupVersionToInputPath,
OutputPackage: fakeClientsetPackage,
Groups: customArgs.Groups,
ImportTracker: generator.NewImportTracker(),
PrivateScheme: true,
CreateRegistry: true, // needed to know about root resources and for RESTMapper
},
} }
return generators return generators
}, },

View File

@ -70,7 +70,6 @@ func (g *genClientset) Imports(c *generator.Context) (imports []string) {
imports = append(imports, fmt.Sprintf("clientset \"%s\"", g.realClientsetPackage)) imports = append(imports, fmt.Sprintf("clientset \"%s\"", g.realClientsetPackage))
// imports for the code in commonTemplate // imports for the code in commonTemplate
imports = append(imports, imports = append(imports,
"k8s.io/kubernetes/pkg/api",
"k8s.io/client-go/testing", "k8s.io/client-go/testing",
"k8s.io/client-go/discovery", "k8s.io/client-go/discovery",
"fakediscovery \"k8s.io/client-go/discovery/fake\"", "fakediscovery \"k8s.io/client-go/discovery/fake\"",
@ -109,7 +108,7 @@ var common = `
// without applying any validations and/or defaults. It shouldn't be considered a replacement // 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. // for a real clientset and is mostly useful in simple unit tests.
func NewSimpleClientset(objects ...runtime.Object) *Clientset { func NewSimpleClientset(objects ...runtime.Object) *Clientset {
o := testing.NewObjectTracker(api.Registry, api.Scheme, api.Codecs.UniversalDecoder()) o := testing.NewObjectTracker(registry, scheme, codecs.UniversalDecoder())
for _, obj := range objects { for _, obj := range objects {
if err := o.Add(obj); err != nil { if err := o.Add(obj); err != nil {
panic(err) panic(err)
@ -117,7 +116,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset {
} }
fakePtr := testing.Fake{} fakePtr := testing.Fake{}
fakePtr.AddReactor("*", "*", testing.ObjectReaction(o, api.Registry.RESTMapper())) fakePtr.AddReactor("*", "*", testing.ObjectReaction(o, registry.RESTMapper()))
fakePtr.AddWatchReactor("*", testing.DefaultWatchReactor(watch.NewFake(), nil)) fakePtr.AddWatchReactor("*", testing.DefaultWatchReactor(watch.NewFake(), nil))

View File

@ -0,0 +1,33 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["generator_for_scheme.go"],
tags = ["automanaged"],
deps = [
"//cmd/libs/go2idl/client-gen/types:go_default_library",
"//vendor:k8s.io/gengo/generator",
"//vendor:k8s.io/gengo/namer",
"//vendor:k8s.io/gengo/types",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package generators package scheme
import ( import (
"fmt" "fmt"
@ -29,37 +29,38 @@ import (
clientgentypes "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types" clientgentypes "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types"
) )
// genScheme produces a package for a clientset with the scheme, codecs and parameter codecs. // GenScheme produces a package for a clientset with the scheme, codecs and parameter codecs.
type genScheme struct { type GenScheme struct {
generator.DefaultGen generator.DefaultGen
outputPackage string OutputPackage string
groups []clientgentypes.GroupVersions Groups []clientgentypes.GroupVersions
inputPackages map[clientgentypes.GroupVersion]string InputPackages map[clientgentypes.GroupVersion]string
outputPath string OutputPath string
imports namer.ImportTracker ImportTracker namer.ImportTracker
PrivateScheme bool
CreateRegistry bool
schemeGenerated bool schemeGenerated bool
} }
func (g *genScheme) Namers(c *generator.Context) namer.NameSystems { func (g *GenScheme) Namers(c *generator.Context) namer.NameSystems {
return namer.NameSystems{ return namer.NameSystems{
"raw": namer.NewRawNamer(g.outputPackage, g.imports), "raw": namer.NewRawNamer(g.OutputPackage, g.ImportTracker),
} }
} }
// We only want to call GenerateType() once. // We only want to call GenerateType() once.
func (g *genScheme) Filter(c *generator.Context, t *types.Type) bool { func (g *GenScheme) Filter(c *generator.Context, t *types.Type) bool {
ret := !g.schemeGenerated ret := !g.schemeGenerated
g.schemeGenerated = true g.schemeGenerated = true
return ret return ret
} }
func (g *genScheme) Imports(c *generator.Context) (imports []string) { func (g *GenScheme) Imports(c *generator.Context) (imports []string) {
imports = append(imports, g.imports.ImportLines()...) imports = append(imports, g.ImportTracker.ImportLines()...)
internal := g.internalClientset() for _, group := range g.Groups {
for _, group := range g.groups {
for _, version := range group.Versions { for _, version := range group.Versions {
packagePath := g.inputPackages[clientgentypes.GroupVersion{Group: group.Group, Version: version}] packagePath := g.InputPackages[clientgentypes.GroupVersion{Group: group.Group, Version: version}]
if internal { if g.CreateRegistry {
// import the install package for internal clientsets instead of the type package with register.go // import the install package for internal clientsets instead of the type package with register.go
if version != "" { if version != "" {
packagePath = filepath.Dir(packagePath) packagePath = filepath.Dir(packagePath)
@ -75,11 +76,11 @@ func (g *genScheme) Imports(c *generator.Context) (imports []string) {
return return
} }
func (g *genScheme) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { func (g *GenScheme) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
sw := generator.NewSnippetWriter(w, c, "$", "$") sw := generator.NewSnippetWriter(w, c, "$", "$")
allGroupVersions := clientgentypes.ToGroupVersionPackages(g.groups) allGroupVersions := clientgentypes.ToGroupVersionPackages(g.Groups)
allInstallGroups := clientgentypes.ToGroupInstallPackages(g.groups) allInstallGroups := clientgentypes.ToGroupInstallPackages(g.Groups)
m := map[string]interface{}{ m := map[string]interface{}{
"allGroupVersions": allGroupVersions, "allGroupVersions": allGroupVersions,
@ -96,45 +97,51 @@ func (g *genScheme) GenerateType(c *generator.Context, t *types.Type, w io.Write
"registeredNewOrDie": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/apimachinery/registered", Name: "NewOrDie"}), "registeredNewOrDie": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/apimachinery/registered", Name: "NewOrDie"}),
"registeredAPIRegistrationManager": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apimachinery/registered", Name: "APIRegistrationManager"}), "registeredAPIRegistrationManager": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apimachinery/registered", Name: "APIRegistrationManager"}),
} }
sw.Do(globalsTemplate, m) globals := map[string]string{
"Scheme": "Scheme",
if _, err := os.Stat(filepath.Join(g.outputPath, strings.ToLower("register_custom.go"))); err == nil { "Codecs": "Codecs",
m["customRegister"] = true "ParameterCodec": "ParameterCodec",
"Registry": "Registry",
"GroupFactoryRegistry": "GroupFactoryRegistry",
}
for k, v := range globals {
if g.PrivateScheme {
m[k] = strings.ToLower(v[0:1]) + v[1:]
} else {
m[k] = v
}
} }
if g.internalClientset() { sw.Do(globalsTemplate, m)
sw.Do(internalRegistration, m)
if g.OutputPath != "" {
if _, err := os.Stat(filepath.Join(g.OutputPath, strings.ToLower("register_custom.go"))); err == nil {
m["customRegister"] = true
}
}
if g.CreateRegistry {
sw.Do(registryRegistration, m)
} else { } else {
sw.Do(registration, m) sw.Do(simpleRegistration, m)
} }
return sw.Error() return sw.Error()
} }
func (g *genScheme) internalClientset() bool {
for _, group := range g.groups {
for _, v := range group.Versions {
if v == "" {
return true
}
}
}
return false
}
var globalsTemplate = ` var globalsTemplate = `
var Scheme = $.runtimeNewScheme|raw$() var $.Scheme$ = $.runtimeNewScheme|raw$()
var Codecs = $.serializerNewCodecFactory|raw$(Scheme) var $.Codecs$ = $.serializerNewCodecFactory|raw$($.Scheme$)
var ParameterCodec = $.runtimeNewParameterCodec|raw$(Scheme) var $.ParameterCodec$ = $.runtimeNewParameterCodec|raw$($.Scheme$)
` `
var internalRegistration = ` var registryRegistration = `
var Registry = $.registeredNewOrDie|raw$($.osGetenv|raw$("KUBE_API_VERSIONS")) var $.Registry$ = $.registeredNewOrDie|raw$($.osGetenv|raw$("KUBE_API_VERSIONS"))
var GroupFactoryRegistry = make($.announcedAPIGroupFactoryRegistry|raw$) var $.GroupFactoryRegistry$ = make($.announcedAPIGroupFactoryRegistry|raw$)
func init() { func init() {
$.metav1AddToGroupVersion|raw$(Scheme, $.schemaGroupVersion|raw${Version: "v1"}) $.metav1AddToGroupVersion|raw$($.Scheme$, $.schemaGroupVersion|raw${Version: "v1"})
Install(GroupFactoryRegistry, Registry, Scheme) Install($.GroupFactoryRegistry$, $.Registry$, $.Scheme$)
} }
// Install registers the API group and adds types to a scheme // Install registers the API group and adds types to a scheme
@ -145,12 +152,12 @@ func Install(groupFactoryRegistry $.announcedAPIGroupFactoryRegistry|raw$, regis
} }
` `
var registration = ` var simpleRegistration = `
func init() { func init() {
$.metav1AddToGroupVersion|raw$(Scheme, $.schemaGroupVersion|raw${Version: "v1"}) $.metav1AddToGroupVersion|raw$($.Scheme$, $.schemaGroupVersion|raw${Version: "v1"})
AddToScheme(Scheme) AddToScheme($.Scheme$)
} }
// AddToScheme adds all types of this clientset into the given scheme. This allows composition // AddToScheme adds all types of this clientset into the given scheme. This allows composition

View File

@ -77,13 +77,3 @@ ${informergen} \
--listers-package k8s.io/kube-aggregator/pkg/client/listers \ --listers-package k8s.io/kube-aggregator/pkg/client/listers \
--output-package k8s.io/kube-aggregator/pkg/client/informers --output-package k8s.io/kube-aggregator/pkg/client/informers
"$@" "$@"
# this is a temporary hack until we manage to update codegen to accept a scheme instead of hardcoding it
echo "rewriting imports"
grep -R -H "\"k8s.io/kubernetes/pkg" "${KUBE_ROOT}/vendor/k8s.io/kube-aggregator/pkg/client" | cut -d: -f1 | sort | uniq | \
grep "\.go" | \
xargs ${SED} -i "s|\"k8s.io/kubernetes/pkg|\"k8s.io/client-go/pkg|g"
echo "running gofmt"
find "${KUBE_ROOT}/vendor/k8s.io/kube-aggregator/pkg/client" -type f -name "*.go" -print0 | xargs -0 gofmt -w