Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

client-gen: create private registry in fake clientset #42095

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion cmd/libs/go2idl/client-gen/generators/BUILD
Expand Up @@ -14,14 +14,14 @@ go_library(
"generator_for_clientset.go",
"generator_for_expansion.go",
"generator_for_group.go",
"generator_for_scheme.go",
"generator_for_type.go",
"tags.go",
],
tags = ["automanaged"],
deps = [
"//cmd/libs/go2idl/client-gen/args:go_default_library",
"//cmd/libs/go2idl/client-gen/generators/fake:go_default_library",
"//cmd/libs/go2idl/client-gen/generators/scheme:go_default_library",
"//cmd/libs/go2idl/client-gen/types:go_default_library",
"//vendor:github.com/golang/glog",
"//vendor:k8s.io/gengo/args",
Expand All @@ -43,6 +43,7 @@ filegroup(
srcs = [
":package-srcs",
"//cmd/libs/go2idl/client-gen/generators/fake:all-srcs",
"//cmd/libs/go2idl/client-gen/generators/scheme:all-srcs",
],
tags = ["automanaged"],
)
27 changes: 21 additions & 6 deletions cmd/libs/go2idl/client-gen/generators/client_generator.go
Expand Up @@ -28,6 +28,7 @@ import (
"k8s.io/gengo/types"
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/scheme"
clientgentypes "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types"

"github.com/golang/glog"
Expand Down Expand Up @@ -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 {
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{
PackageName: "scheme",
PackagePath: schemePackage,
Expand All @@ -173,15 +187,16 @@ func packageForScheme(customArgs clientgenargs.Args, clientsetPackage string, sr
// Always generate a "doc.go" file.
generator.DefaultGen{OptionalName: "doc"},

&genScheme{
&scheme.GenScheme{
DefaultGen: generator.DefaultGen{
OptionalName: "register",
},
inputPackages: customArgs.GroupVersionToInputPath,
outputPackage: schemePackage,
outputPath: filepath.Join(srcTreePath, schemePackage),
groups: customArgs.Groups,
imports: generator.NewImportTracker(),
InputPackages: customArgs.GroupVersionToInputPath,
OutputPackage: schemePackage,
OutputPath: filepath.Join(srcTreePath, schemePackage),
Groups: customArgs.Groups,
ImportTracker: generator.NewImportTracker(),
CreateRegistry: internalClient,
},
}
return generators
Expand Down
1 change: 1 addition & 0 deletions cmd/libs/go2idl/client-gen/generators/fake/BUILD
Expand Up @@ -18,6 +18,7 @@ go_library(
tags = ["automanaged"],
deps = [
"//cmd/libs/go2idl/client-gen/args:go_default_library",
"//cmd/libs/go2idl/client-gen/generators/scheme:go_default_library",
"//cmd/libs/go2idl/client-gen/types:go_default_library",
"//vendor:github.com/golang/glog",
"//vendor:k8s.io/gengo/generator",
Expand Down
Expand Up @@ -25,6 +25,7 @@ import (
"k8s.io/gengo/generator"
"k8s.io/gengo/types"
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"
)

Expand Down Expand Up @@ -118,6 +119,17 @@ func PackageForClientset(customArgs clientgenargs.Args, fakeClientsetPackage str
imports: generator.NewImportTracker(),
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
},
Expand Down
Expand Up @@ -70,7 +70,6 @@ func (g *genClientset) Imports(c *generator.Context) (imports []string) {
imports = append(imports, fmt.Sprintf("clientset \"%s\"", g.realClientsetPackage))
// imports for the code in commonTemplate
imports = append(imports,
"k8s.io/kubernetes/pkg/api",
"k8s.io/client-go/testing",
"k8s.io/client-go/discovery",
"fakediscovery \"k8s.io/client-go/discovery/fake\"",
Expand Down Expand Up @@ -109,15 +108,15 @@ var common = `
// 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 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 {
if err := o.Add(obj); err != nil {
panic(err)
}
}

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

Expand Down
33 changes: 33 additions & 0 deletions cmd/libs/go2idl/client-gen/generators/scheme/BUILD
@@ -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"],
)
Expand Up @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package generators
package scheme

import (
"fmt"
Expand All @@ -29,37 +29,38 @@ import (
clientgentypes "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types"
)

// genScheme produces a package for a clientset with the scheme, codecs and parameter codecs.
type genScheme struct {
// GenScheme produces a package for a clientset with the scheme, codecs and parameter codecs.
type GenScheme struct {
generator.DefaultGen
outputPackage string
groups []clientgentypes.GroupVersions
inputPackages map[clientgentypes.GroupVersion]string
outputPath string
imports namer.ImportTracker
OutputPackage string
Groups []clientgentypes.GroupVersions
InputPackages map[clientgentypes.GroupVersion]string
OutputPath string
ImportTracker namer.ImportTracker
PrivateScheme bool
CreateRegistry bool
schemeGenerated bool
}

func (g *genScheme) Namers(c *generator.Context) namer.NameSystems {
func (g *GenScheme) Namers(c *generator.Context) 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.
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
g.schemeGenerated = true
return ret
}

func (g *genScheme) Imports(c *generator.Context) (imports []string) {
imports = append(imports, g.imports.ImportLines()...)
internal := g.internalClientset()
for _, group := range g.groups {
func (g *GenScheme) Imports(c *generator.Context) (imports []string) {
imports = append(imports, g.ImportTracker.ImportLines()...)
for _, group := range g.Groups {
for _, version := range group.Versions {
packagePath := g.inputPackages[clientgentypes.GroupVersion{Group: group.Group, Version: version}]
if internal {
packagePath := g.InputPackages[clientgentypes.GroupVersion{Group: group.Group, Version: version}]
if g.CreateRegistry {
// import the install package for internal clientsets instead of the type package with register.go
if version != "" {
packagePath = filepath.Dir(packagePath)
Expand All @@ -75,11 +76,11 @@ func (g *genScheme) Imports(c *generator.Context) (imports []string) {
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, "$", "$")

allGroupVersions := clientgentypes.ToGroupVersionPackages(g.groups)
allInstallGroups := clientgentypes.ToGroupInstallPackages(g.groups)
allGroupVersions := clientgentypes.ToGroupVersionPackages(g.Groups)
allInstallGroups := clientgentypes.ToGroupInstallPackages(g.Groups)

m := map[string]interface{}{
"allGroupVersions": allGroupVersions,
Expand All @@ -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"}),
"registeredAPIRegistrationManager": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apimachinery/registered", Name: "APIRegistrationManager"}),
}
globals := map[string]string{
"Scheme": "Scheme",
"Codecs": "Codecs",
"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
}
}

sw.Do(globalsTemplate, m)

if _, err := os.Stat(filepath.Join(g.outputPath, strings.ToLower("register_custom.go"))); err == nil {
m["customRegister"] = true
if g.OutputPath != "" {
if _, err := os.Stat(filepath.Join(g.OutputPath, strings.ToLower("register_custom.go"))); err == nil {
m["customRegister"] = true
}
}

if g.internalClientset() {
sw.Do(internalRegistration, m)
if g.CreateRegistry {
sw.Do(registryRegistration, m)
} else {
sw.Do(registration, m)
sw.Do(simpleRegistration, m)
}

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 Scheme = $.runtimeNewScheme|raw$()
var Codecs = $.serializerNewCodecFactory|raw$(Scheme)
var ParameterCodec = $.runtimeNewParameterCodec|raw$(Scheme)
var $.Scheme$ = $.runtimeNewScheme|raw$()
var $.Codecs$ = $.serializerNewCodecFactory|raw$($.Scheme$)
var $.ParameterCodec$ = $.runtimeNewParameterCodec|raw$($.Scheme$)
`

var internalRegistration = `
var Registry = $.registeredNewOrDie|raw$($.osGetenv|raw$("KUBE_API_VERSIONS"))
var GroupFactoryRegistry = make($.announcedAPIGroupFactoryRegistry|raw$)
var registryRegistration = `
var $.Registry$ = $.registeredNewOrDie|raw$($.osGetenv|raw$("KUBE_API_VERSIONS"))
var $.GroupFactoryRegistry$ = make($.announcedAPIGroupFactoryRegistry|raw$)

func init() {
$.metav1AddToGroupVersion|raw$(Scheme, $.schemaGroupVersion|raw${Version: "v1"})
Install(GroupFactoryRegistry, Registry, Scheme)
$.metav1AddToGroupVersion|raw$($.Scheme$, $.schemaGroupVersion|raw${Version: "v1"})
Install($.GroupFactoryRegistry$, $.Registry$, $.Scheme$)
}

// Install registers the API group and adds types to a scheme
Expand All @@ -145,12 +152,12 @@ func Install(groupFactoryRegistry $.announcedAPIGroupFactoryRegistry|raw$, regis
}
`

var registration = `
var simpleRegistration = `


func init() {
$.metav1AddToGroupVersion|raw$(Scheme, $.schemaGroupVersion|raw${Version: "v1"})
AddToScheme(Scheme)
$.metav1AddToGroupVersion|raw$($.Scheme$, $.schemaGroupVersion|raw${Version: "v1"})
AddToScheme($.Scheme$)
}

// AddToScheme adds all types of this clientset into the given scheme. This allows composition
Expand Down
Expand Up @@ -12,14 +12,20 @@ go_library(
srcs = [
"clientset_generated.go",
"doc.go",
"register.go",
],
tags = ["automanaged"],
deps = [
"//cmd/libs/go2idl/client-gen/test_apis/testgroup/install:go_default_library",
"//cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset:go_default_library",
"//cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset/typed/testgroup/internalversion:go_default_library",
"//cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset/typed/testgroup/internalversion/fake:go_default_library",
"//pkg/api:go_default_library",
"//vendor:k8s.io/apimachinery/pkg/apimachinery/announced",
"//vendor:k8s.io/apimachinery/pkg/apimachinery/registered",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/runtime",
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
"//vendor:k8s.io/apimachinery/pkg/runtime/serializer",
"//vendor:k8s.io/apimachinery/pkg/watch",
"//vendor:k8s.io/client-go/discovery",
"//vendor:k8s.io/client-go/discovery/fake",
Expand Down
Expand Up @@ -25,23 +25,22 @@ import (
clientset "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset"
testgroupinternalversion "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset/typed/testgroup/internalversion"
faketestgroupinternalversion "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset/typed/testgroup/internalversion/fake"
"k8s.io/kubernetes/pkg/api"
)

// 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 validations and/or defaults. It shouldn't be considered a replacement
// for a real clientset and is mostly useful in simple unit tests.
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 {
if err := o.Add(obj); err != nil {
panic(err)
}
}

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

Expand Down