1
0
Fork 0
forked from barak/tarpoon

Add glide.yaml and vendor deps

This commit is contained in:
Dalton Hubble 2016-12-03 22:43:32 -08:00
parent db918f12ad
commit 5b3d5e81bd
18880 changed files with 5166045 additions and 1 deletions

View file

@ -0,0 +1,13 @@
{
"Rules": [
{
"SelectorRegexp": "k8s[.]io",
"AllowedPrefixes": [
"k8s.io/kubernetes/cmd/libs/go2idl",
"k8s.io/gengo",
"k8s.io/kubernetes/third_party",
"k8s.io/kubernetes/pkg/util/sets"
]
}
]
}

3
vendor/k8s.io/kubernetes/cmd/libs/go2idl/OWNERS generated vendored Normal file
View file

@ -0,0 +1,3 @@
assignees:
- lavalamp
- wojtek-t

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1,25 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_binary(
name = "client-gen",
srcs = ["main.go"],
tags = ["automanaged"],
deps = [
"//cmd/libs/go2idl/client-gen/args:go_default_library",
"//cmd/libs/go2idl/client-gen/generators:go_default_library",
"//cmd/libs/go2idl/client-gen/types:go_default_library",
"//vendor:github.com/golang/glog",
"//vendor:github.com/spf13/pflag",
"//vendor:k8s.io/gengo/args",
],
)

View file

@ -0,0 +1,4 @@
assignees:
- lavalamp
- wojtek-t
- caesarxuchao

View file

@ -0,0 +1,4 @@
See [generating-clientset.md](../../../../docs/devel/generating-clientset.md)
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/cmd/libs/go2idl/client-gen/README.md?pixel)]()

View file

@ -0,0 +1,18 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_library(
name = "go_default_library",
srcs = ["args.go"],
tags = ["automanaged"],
deps = ["//cmd/libs/go2idl/client-gen/types:go_default_library"],
)

View file

@ -0,0 +1,49 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package args
import "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types"
// ClientGenArgs is a wrapper for arguments to client-gen.
type Args struct {
Groups []types.GroupVersions
// GroupVersionToInputPath is a map between GroupVersion and the path to
// the respective types.go. We still need GroupVersions in the struct because
// we need an order.
GroupVersionToInputPath map[types.GroupVersion]string
// Overrides for which types should be included in the client.
IncludedTypesOverrides map[types.GroupVersion][]string
// ClientsetName is the name of the clientset to be generated. It's
// populated from command-line arguments.
ClientsetName string
// ClientsetOutputPath is the path the clientset will be generated at. It's
// populated from command-line arguments.
ClientsetOutputPath string
// ClientsetAPIPath is the default API path for generated clients.
ClientsetAPIPath string
// ClientsetOnly determines if we should generate the clients for groups and
// types along with the clientset. It's populated from command-line
// arguments.
ClientsetOnly bool
// FakeClient determines if client-gen generates the fake clients.
FakeClient bool
// CmdArgs is the command line arguments supplied when the client-gen is called.
CmdArgs string
}

View file

@ -0,0 +1,34 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_library(
name = "go_default_library",
srcs = [
"client_generator.go",
"generator_for_clientset.go",
"generator_for_expansion.go",
"generator_for_group.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/types:go_default_library",
"//vendor:github.com/golang/glog",
"//vendor:k8s.io/gengo/args",
"//vendor:k8s.io/gengo/generator",
"//vendor:k8s.io/gengo/namer",
"//vendor:k8s.io/gengo/types",
],
)

View file

@ -0,0 +1,230 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package generators has the generators for the client-gen utility.
package generators
import (
"fmt"
"path/filepath"
"strings"
"k8s.io/gengo/args"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
clientgenargs "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/args"
"k8s.io/kubernetes/cmd/libs/go2idl/client-gen/generators/fake"
clientgentypes "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types"
"github.com/golang/glog"
)
// NameSystems returns the name system used by the generators in this package.
func NameSystems() namer.NameSystems {
pluralExceptions := map[string]string{
"Endpoints": "Endpoints",
}
return namer.NameSystems{
"public": namer.NewPublicNamer(0),
"private": namer.NewPrivateNamer(0),
"raw": namer.NewRawNamer("", nil),
"publicPlural": namer.NewPublicPluralNamer(pluralExceptions),
"privatePlural": namer.NewPrivatePluralNamer(pluralExceptions),
"allLowercasePlural": namer.NewAllLowercasePluralNamer(pluralExceptions),
}
}
// DefaultNameSystem returns the default name system for ordering the types to be
// processed by the generators in this package.
func DefaultNameSystem() string {
return "public"
}
func generatedBy(customArgs clientgenargs.Args) string {
if len(customArgs.CmdArgs) != 0 {
return fmt.Sprintf("\n// This package is generated by client-gen with arguments: %s\n\n", customArgs.CmdArgs)
}
return fmt.Sprintf("\n// This package is generated by client-gen with the default arguments.\n\n")
}
func packageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, packageBasePath string, apiPath string, srcTreePath string, inputPath string, boilerplate []byte, generatedBy string) generator.Package {
outputPackagePath := strings.ToLower(filepath.Join(packageBasePath, gv.Group.NonEmpty(), gv.Version.NonEmpty()))
return &generator.DefaultPackage{
PackageName: strings.ToLower(gv.Version.NonEmpty()),
PackagePath: outputPackagePath,
HeaderText: boilerplate,
PackageDocumentation: []byte(
generatedBy +
`// This package has the automatically generated typed clients.
`),
// GeneratorFunc returns a list of generators. Each generator makes a
// single file.
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
generators = []generator.Generator{
// Always generate a "doc.go" file.
generator.DefaultGen{OptionalName: "doc"},
}
// Since we want a file per type that we generate a client for, we
// have to provide a function for this.
for _, t := range typeList {
generators = append(generators, &genClientForType{
DefaultGen: generator.DefaultGen{
OptionalName: strings.ToLower(c.Namers["private"].Name(t)),
},
outputPackage: outputPackagePath,
group: gv.Group.NonEmpty(),
version: gv.Version.String(),
typeToMatch: t,
imports: generator.NewImportTracker(),
})
}
generators = append(generators, &genGroup{
DefaultGen: generator.DefaultGen{
OptionalName: gv.Group.NonEmpty() + "_client",
},
outputPackage: outputPackagePath,
inputPacakge: inputPath,
group: gv.Group.NonEmpty(),
version: gv.Version.String(),
apiPath: apiPath,
types: typeList,
imports: generator.NewImportTracker(),
})
expansionFileName := "generated_expansion"
generators = append(generators, &genExpansion{
groupPath: filepath.Join(srcTreePath, outputPackagePath),
DefaultGen: generator.DefaultGen{
OptionalName: expansionFileName,
},
types: typeList,
})
return generators
},
FilterFunc: func(c *generator.Context, t *types.Type) bool {
return extractBoolTagOrDie("genclient", t.SecondClosestCommentLines) == true
},
}
}
func packageForClientset(customArgs clientgenargs.Args, typedClientBasePath string, boilerplate []byte, generatedBy string) generator.Package {
return &generator.DefaultPackage{
PackageName: customArgs.ClientsetName,
PackagePath: filepath.Join(customArgs.ClientsetOutputPath, customArgs.ClientsetName),
HeaderText: boilerplate,
PackageDocumentation: []byte(
generatedBy +
`// This package has the automatically generated clientset.
`),
// GeneratorFunc returns a list of generators. Each generator generates a
// single file.
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
generators = []generator.Generator{
// Always generate a "doc.go" file.
generator.DefaultGen{OptionalName: "doc"},
&genClientset{
DefaultGen: generator.DefaultGen{
OptionalName: "clientset",
},
groups: customArgs.Groups,
typedClientPath: typedClientBasePath,
outputPackage: customArgs.ClientsetName,
imports: generator.NewImportTracker(),
},
}
return generators
},
}
}
// Packages makes the client package definition.
func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
boilerplate, err := arguments.LoadGoBoilerplate()
if err != nil {
glog.Fatalf("Failed loading boilerplate: %v", err)
}
customArgs, ok := arguments.CustomArgs.(clientgenargs.Args)
if !ok {
glog.Fatalf("cannot convert arguments.CustomArgs to clientgenargs.Args")
}
includedTypesOverrides := customArgs.IncludedTypesOverrides
generatedBy := generatedBy(customArgs)
gvToTypes := map[clientgentypes.GroupVersion][]*types.Type{}
for gv, inputDir := range customArgs.GroupVersionToInputPath {
p := context.Universe.Package(inputDir)
for n, t := range p.Types {
// filter out types which are not included in user specified overrides.
typesOverride, ok := includedTypesOverrides[gv]
if ok {
found := false
for _, typeStr := range typesOverride {
if typeStr == n {
found = true
break
}
}
if !found {
continue
}
} else {
// User has not specified any override for this group version.
// filter out types which dont have genclient=true.
if extractBoolTagOrDie("genclient", t.SecondClosestCommentLines) == false {
continue
}
}
if _, found := gvToTypes[gv]; !found {
gvToTypes[gv] = []*types.Type{}
}
gvToTypes[gv] = append(gvToTypes[gv], t)
}
}
var packageList []generator.Package
typedClientBasePath := filepath.Join(customArgs.ClientsetOutputPath, customArgs.ClientsetName, "typed")
packageList = append(packageList, packageForClientset(customArgs, typedClientBasePath, boilerplate, generatedBy))
if customArgs.FakeClient {
packageList = append(packageList, fake.PackageForClientset(customArgs, typedClientBasePath, boilerplate, generatedBy))
}
// If --clientset-only=true, we don't regenerate the individual typed clients.
if customArgs.ClientsetOnly {
return generator.Packages(packageList)
}
orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)}
for _, group := range customArgs.Groups {
for _, version := range group.Versions {
gv := clientgentypes.GroupVersion{Group: group.Group, Version: version}
types := gvToTypes[gv]
inputPath := customArgs.GroupVersionToInputPath[gv]
packageList = append(packageList, packageForGroup(gv, orderer.OrderTypes(types), typedClientBasePath, customArgs.ClientsetAPIPath, arguments.OutputBase, inputPath, boilerplate, generatedBy))
if customArgs.FakeClient {
packageList = append(packageList, fake.PackageForGroup(gv, orderer.OrderTypes(types), typedClientBasePath, arguments.OutputBase, inputPath, boilerplate, generatedBy))
}
}
}
return generator.Packages(packageList)
}

View file

@ -0,0 +1,30 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_library(
name = "go_default_library",
srcs = [
"fake_client_generator.go",
"generator_fake_for_clientset.go",
"generator_fake_for_group.go",
"generator_fake_for_type.go",
],
tags = ["automanaged"],
deps = [
"//cmd/libs/go2idl/client-gen/args:go_default_library",
"//cmd/libs/go2idl/client-gen/types:go_default_library",
"//vendor:github.com/golang/glog",
"//vendor:k8s.io/gengo/generator",
"//vendor:k8s.io/gengo/namer",
"//vendor:k8s.io/gengo/types",
],
)

View file

@ -0,0 +1,125 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fake
import (
"path/filepath"
"strings"
"github.com/golang/glog"
"k8s.io/gengo/generator"
"k8s.io/gengo/types"
clientgenargs "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/args"
clientgentypes "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types"
)
func PackageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, packageBasePath string, srcTreePath string, inputPath string, boilerplate []byte, generatedBy string) generator.Package {
outputPackagePath := strings.ToLower(filepath.Join(packageBasePath, gv.Group.NonEmpty(), gv.Version.NonEmpty(), "fake"))
// TODO: should make this a function, called by here and in client-generator.go
realClientPath := filepath.Join(packageBasePath, gv.Group.NonEmpty(), gv.Version.NonEmpty())
return &generator.DefaultPackage{
PackageName: "fake",
PackagePath: outputPackagePath,
HeaderText: boilerplate,
PackageDocumentation: []byte(
generatedBy +
`// Package fake has the automatically generated clients.
`),
// GeneratorFunc returns a list of generators. Each generator makes a
// single file.
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
generators = []generator.Generator{
// Always generate a "doc.go" file.
generator.DefaultGen{OptionalName: "doc"},
}
// Since we want a file per type that we generate a client for, we
// have to provide a function for this.
for _, t := range typeList {
generators = append(generators, &genFakeForType{
DefaultGen: generator.DefaultGen{
OptionalName: "fake_" + strings.ToLower(c.Namers["private"].Name(t)),
},
outputPackage: outputPackagePath,
group: gv.Group.NonEmpty(),
version: gv.Version.String(),
inputPackage: inputPath,
typeToMatch: t,
imports: generator.NewImportTracker(),
})
}
generators = append(generators, &genFakeForGroup{
DefaultGen: generator.DefaultGen{
OptionalName: "fake_" + gv.Group.NonEmpty() + "_client",
},
outputPackage: outputPackagePath,
realClientPath: realClientPath,
group: gv.Group.NonEmpty(),
version: gv.Version.String(),
types: typeList,
imports: generator.NewImportTracker(),
})
return generators
},
FilterFunc: func(c *generator.Context, t *types.Type) bool {
return extractBoolTagOrDie("genclient", t.SecondClosestCommentLines) == true
},
}
}
func extractBoolTagOrDie(key string, lines []string) bool {
val, err := types.ExtractSingleBoolCommentTag("+", key, false, lines)
if err != nil {
glog.Fatalf(err.Error())
}
return val
}
func PackageForClientset(customArgs clientgenargs.Args, typedClientBasePath string, boilerplate []byte, generatedBy string) generator.Package {
return &generator.DefaultPackage{
// TODO: we'll generate fake clientset for different release in the future.
// Package name and path are hard coded for now.
PackageName: "fake",
PackagePath: filepath.Join(customArgs.ClientsetOutputPath, customArgs.ClientsetName, "fake"),
HeaderText: boilerplate,
PackageDocumentation: []byte(
generatedBy +
`// This package has the automatically generated fake clientset.
`),
// GeneratorFunc returns a list of generators. Each generator generates a
// single file.
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
generators = []generator.Generator{
// Always generate a "doc.go" file.
generator.DefaultGen{OptionalName: "doc"},
&genClientset{
DefaultGen: generator.DefaultGen{
OptionalName: "clientset_generated",
},
groups: customArgs.Groups,
typedClientPath: typedClientBasePath,
outputPackage: "fake",
imports: generator.NewImportTracker(),
clientsetPath: filepath.Join(customArgs.ClientsetOutputPath, customArgs.ClientsetName),
},
}
return generators
},
}
}

View file

@ -0,0 +1,156 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fake
import (
"fmt"
"io"
"path/filepath"
"strings"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
clientgentypes "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types"
)
// genClientset generates a package for a clientset.
type genClientset struct {
generator.DefaultGen
groups []clientgentypes.GroupVersions
typedClientPath string
outputPackage string
imports namer.ImportTracker
clientsetGenerated bool
// the import path of the generated real clientset.
clientsetPath string
}
var _ generator.Generator = &genClientset{}
func (g *genClientset) Namers(c *generator.Context) namer.NameSystems {
return namer.NameSystems{
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
}
}
// We only want to call GenerateType() once.
func (g *genClientset) Filter(c *generator.Context, t *types.Type) bool {
ret := !g.clientsetGenerated
g.clientsetGenerated = true
return ret
}
func (g *genClientset) Imports(c *generator.Context) (imports []string) {
imports = append(imports, g.imports.ImportLines()...)
for _, group := range g.groups {
for _, version := range group.Versions {
typedClientPath := filepath.Join(g.typedClientPath, group.Group.NonEmpty(), version.NonEmpty())
imports = append(imports, strings.ToLower(fmt.Sprintf("%s%s \"%s\"", version.NonEmpty(), group.Group.NonEmpty(), typedClientPath)))
fakeTypedClientPath := filepath.Join(typedClientPath, "fake")
imports = append(imports, strings.ToLower(fmt.Sprintf("fake%s%s \"%s\"", version.NonEmpty(), group.Group.NonEmpty(), fakeTypedClientPath)))
}
}
// the package that has the clientset Interface
imports = append(imports, fmt.Sprintf("clientset \"%s\"", g.clientsetPath))
// imports for the code in commonTemplate
imports = append(imports,
"k8s.io/kubernetes/pkg/api",
"k8s.io/kubernetes/pkg/apimachinery/registered",
"k8s.io/kubernetes/pkg/client/testing/core",
"k8s.io/kubernetes/pkg/client/typed/discovery",
"fakediscovery \"k8s.io/kubernetes/pkg/client/typed/discovery/fake\"",
"k8s.io/kubernetes/pkg/runtime",
"k8s.io/kubernetes/pkg/watch",
)
return
}
func (g *genClientset) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
// 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, "$", "$")
sw.Do(common, nil)
sw.Do(checkImpl, nil)
allGroups := clientgentypes.ToGroupVersionPackages(g.groups)
for _, g := range allGroups {
sw.Do(clientsetInterfaceImplTemplate, g)
// don't generated the default method if generating internalversion clientset
if g.IsDefaultVersion && g.Version != "" {
sw.Do(clientsetInterfaceDefaultVersionImpl, g)
}
}
return sw.Error()
}
// This part of code is version-independent, unchanging.
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 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 := core.NewObjectTracker(api.Scheme, api.Codecs.UniversalDecoder())
for _, obj := range objects {
if err := o.Add(obj); err != nil {
panic(err)
}
}
fakePtr := core.Fake{}
fakePtr.AddReactor("*", "*", core.ObjectReaction(o, registered.RESTMapper()))
fakePtr.AddWatchReactor("*", core.DefaultWatchReactor(watch.NewFake(), nil))
return &Clientset{fakePtr}
}
// Clientset implements clientset.Interface. Meant to be embedded into a
// struct to get a default implementation. This makes faking out just the method
// you want to test easier.
type Clientset struct {
core.Fake
}
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
return &fakediscovery.FakeDiscovery{Fake: &c.Fake}
}
`
var checkImpl = `
var _ clientset.Interface = &Clientset{}
`
var clientsetInterfaceImplTemplate = `
// $.GroupVersion$ retrieves the $.GroupVersion$Client
func (c *Clientset) $.GroupVersion$() $.PackageName$.$.GroupVersion$Interface {
return &fake$.PackageName$.Fake$.GroupVersion${Fake: &c.Fake}
}
`
var clientsetInterfaceDefaultVersionImpl = `
// $.Group$ retrieves the $.GroupVersion$Client
func (c *Clientset) $.Group$() $.PackageName$.$.GroupVersion$Interface {
return &fake$.PackageName$.Fake$.GroupVersion${Fake: &c.Fake}
}
`

View file

@ -0,0 +1,115 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fake
import (
"fmt"
"io"
"path/filepath"
"strings"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
)
// genFakeForGroup produces a file for a group client, e.g. ExtensionsClient for the extension group.
type genFakeForGroup struct {
generator.DefaultGen
outputPackage string
realClientPath string
group string
version string
// types in this group
types []*types.Type
imports namer.ImportTracker
}
var _ generator.Generator = &genFakeForGroup{}
// We only want to call GenerateType() once per group.
func (g *genFakeForGroup) Filter(c *generator.Context, t *types.Type) bool {
return t == g.types[0]
}
func (g *genFakeForGroup) Namers(c *generator.Context) namer.NameSystems {
return namer.NameSystems{
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
}
}
func (g *genFakeForGroup) Imports(c *generator.Context) (imports []string) {
imports = append(g.imports.ImportLines(), strings.ToLower(fmt.Sprintf("%s \"%s\"", filepath.Base(g.realClientPath), g.realClientPath)))
return imports
}
func (g *genFakeForGroup) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
sw := generator.NewSnippetWriter(w, c, "$", "$")
const pkgTestingCore = "k8s.io/kubernetes/pkg/client/testing/core"
const pkgRESTClient = "k8s.io/kubernetes/pkg/client/restclient"
m := map[string]interface{}{
"group": g.group,
"GroupVersion": namer.IC(g.group) + namer.IC(g.version),
"Fake": c.Universe.Type(types.Name{Package: pkgTestingCore, Name: "Fake"}),
"RESTClientInterface": c.Universe.Type(types.Name{Package: pkgRESTClient, Name: "Interface"}),
"RESTClient": c.Universe.Type(types.Name{Package: pkgRESTClient, Name: "RESTClient"}),
}
sw.Do(groupClientTemplate, m)
for _, t := range g.types {
wrapper := map[string]interface{}{
"type": t,
"GroupVersion": namer.IC(g.group) + namer.IC(g.version),
"realClientPackage": strings.ToLower(filepath.Base(g.realClientPath)),
}
namespaced := !extractBoolTagOrDie("nonNamespaced", t.SecondClosestCommentLines)
if namespaced {
sw.Do(getterImplNamespaced, wrapper)
} else {
sw.Do(getterImplNonNamespaced, wrapper)
}
}
sw.Do(getRESTClient, m)
return sw.Error()
}
var groupClientTemplate = `
type Fake$.GroupVersion$ struct {
*$.Fake|raw$
}
`
var getterImplNamespaced = `
func (c *Fake$.GroupVersion$) $.type|publicPlural$(namespace string) $.realClientPackage$.$.type|public$Interface {
return &Fake$.type|publicPlural${c, namespace}
}
`
var getterImplNonNamespaced = `
func (c *Fake$.GroupVersion$) $.type|publicPlural$() $.realClientPackage$.$.type|public$Interface {
return &Fake$.type|publicPlural${c}
}
`
var getRESTClient = `
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *Fake$.GroupVersion$) RESTClient() $.RESTClientInterface|raw$ {
var ret *$.RESTClient|raw$
return ret
}
`

View file

@ -0,0 +1,319 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fake
import (
"io"
"path/filepath"
"strings"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
)
// genFakeForType produces a file for each top-level type.
type genFakeForType struct {
generator.DefaultGen
outputPackage string
group string
version string
inputPackage string
typeToMatch *types.Type
imports namer.ImportTracker
}
var _ generator.Generator = &genFakeForType{}
// 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 }
func (g *genFakeForType) Namers(c *generator.Context) namer.NameSystems {
return namer.NameSystems{
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
}
}
func (g *genFakeForType) Imports(c *generator.Context) (imports []string) {
return g.imports.ImportLines()
}
// Ideally, we'd like hasStatus to return true if there is a subresource path
// registered for "status" in the API server, but we do not have that
// information, so hasStatus returns true if the type has a status field.
func hasStatus(t *types.Type) bool {
for _, m := range t.Members {
if m.Name == "Status" && strings.Contains(m.Tags, `json:"status`) {
return true
}
}
return false
}
// hasObjectMeta returns true if the type has a ObjectMeta field.
func hasObjectMeta(t *types.Type) bool {
for _, m := range t.Members {
if m.Embedded == true && m.Name == "ObjectMeta" {
return true
}
}
return false
}
// GenerateType makes the body of a file implementing the individual typed client for type t.
func (g *genFakeForType) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
sw := generator.NewSnippetWriter(w, c, "$", "$")
pkg := filepath.Base(t.Name.Package)
const pkgTestingCore = "k8s.io/kubernetes/pkg/client/testing/core"
namespaced := !extractBoolTagOrDie("nonNamespaced", t.SecondClosestCommentLines)
canonicalGroup := g.group
if canonicalGroup == "core" {
canonicalGroup = ""
}
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)
if override := types.ExtractCommentTags("+", p.DocComments)["groupName"]; override != nil {
groupName = override[0]
}
m := map[string]interface{}{
"type": t,
"package": pkg,
"Package": namer.IC(pkg),
"namespaced": namespaced,
"Group": namer.IC(g.group),
"GroupVersion": namer.IC(g.group) + namer.IC(g.version),
"group": canonicalGroup,
"groupName": groupName,
"version": g.version,
"watchInterface": c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/watch", Name: "Interface"}),
"GroupVersionResource": c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/runtime/schema", Name: "GroupVersionResource"}),
"PatchType": c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api", Name: "PatchType"}),
"Everything": c.Universe.Function(types.Name{Package: "k8s.io/kubernetes/pkg/labels", Name: "Everything"}),
"NewRootListAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewRootListAction"}),
"NewListAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewListAction"}),
"NewRootGetAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewRootGetAction"}),
"NewGetAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewGetAction"}),
"NewRootDeleteAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewRootDeleteAction"}),
"NewDeleteAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewDeleteAction"}),
"NewRootDeleteCollectionAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewRootDeleteCollectionAction"}),
"NewDeleteCollectionAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewDeleteCollectionAction"}),
"NewRootUpdateAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewRootUpdateAction"}),
"NewUpdateAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewUpdateAction"}),
"NewRootCreateAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewRootCreateAction"}),
"NewCreateAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewCreateAction"}),
"NewRootWatchAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewRootWatchAction"}),
"NewWatchAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewWatchAction"}),
"NewUpdateSubresourceAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewUpdateSubresourceAction"}),
"NewRootUpdateSubresourceAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewRootUpdateSubresourceAction"}),
"NewRootPatchAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewRootPatchAction"}),
"NewPatchAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewPatchAction"}),
"NewRootPatchSubresourceAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewRootPatchSubresourceAction"}),
"NewPatchSubresourceAction": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "NewPatchSubresourceAction"}),
"ExtractFromListOptions": c.Universe.Function(types.Name{Package: pkgTestingCore, Name: "ExtractFromListOptions"}),
}
if g.version == "" {
m["DeleteOptions"] = c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api", Name: "DeleteOptions"})
m["ListOptions"] = c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api", Name: "ListOptions"})
} else {
m["DeleteOptions"] = c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api/v1", Name: "DeleteOptions"})
m["ListOptions"] = c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api/v1", Name: "ListOptions"})
}
noMethods := extractBoolTagOrDie("noMethods", t.SecondClosestCommentLines) == true
if namespaced {
sw.Do(structNamespaced, m)
} else {
sw.Do(structNonNamespaced, m)
}
if !noMethods {
sw.Do(resource, m)
sw.Do(createTemplate, m)
sw.Do(updateTemplate, m)
// Generate the UpdateStatus method if the type has a status
if hasStatus(t) {
sw.Do(updateStatusTemplate, m)
}
sw.Do(deleteTemplate, m)
sw.Do(deleteCollectionTemplate, m)
sw.Do(getTemplate, m)
if hasObjectMeta(t) {
sw.Do(listUsingOptionsTemplate, m)
} else {
sw.Do(listTemplate, m)
}
sw.Do(watchTemplate, m)
sw.Do(patchTemplate, m)
}
return sw.Error()
}
// template for the struct that implements the type's interface
var structNamespaced = `
// Fake$.type|publicPlural$ implements $.type|public$Interface
type Fake$.type|publicPlural$ struct {
Fake *Fake$.GroupVersion$
ns string
}
`
// template for the struct that implements the type's interface
var structNonNamespaced = `
// Fake$.type|publicPlural$ implements $.type|public$Interface
type Fake$.type|publicPlural$ struct {
Fake *Fake$.GroupVersion$
}
`
var resource = `
var $.type|allLowercasePlural$Resource = $.GroupVersionResource|raw${Group: "$.groupName$", Version: "$.version$", Resource: "$.type|allLowercasePlural$"}
`
var listTemplate = `
func (c *Fake$.type|publicPlural$) List(opts $.ListOptions|raw$) (result *$.type|raw$List, err error) {
obj, err := c.Fake.
$if .namespaced$Invokes($.NewListAction|raw$($.type|allLowercasePlural$Resource, c.ns, opts), &$.type|raw$List{})
$else$Invokes($.NewRootListAction|raw$($.type|allLowercasePlural$Resource, opts), &$.type|raw$List{})$end$
if obj == nil {
return nil, err
}
return obj.(*$.type|raw$List), err
}
`
var listUsingOptionsTemplate = `
func (c *Fake$.type|publicPlural$) List(opts $.ListOptions|raw$) (result *$.type|raw$List, err error) {
obj, err := c.Fake.
$if .namespaced$Invokes($.NewListAction|raw$($.type|allLowercasePlural$Resource, c.ns, opts), &$.type|raw$List{})
$else$Invokes($.NewRootListAction|raw$($.type|allLowercasePlural$Resource, opts), &$.type|raw$List{})$end$
if obj == nil {
return nil, err
}
label, _, _ := $.ExtractFromListOptions|raw$(opts)
if label == nil {
label = $.Everything|raw$()
}
list := &$.type|raw$List{}
for _, item := range obj.(*$.type|raw$List).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
`
var getTemplate = `
func (c *Fake$.type|publicPlural$) Get(name string) (result *$.type|raw$, err error) {
obj, err := c.Fake.
$if .namespaced$Invokes($.NewGetAction|raw$($.type|allLowercasePlural$Resource, c.ns, name), &$.type|raw${})
$else$Invokes($.NewRootGetAction|raw$($.type|allLowercasePlural$Resource, name), &$.type|raw${})$end$
if obj == nil {
return nil, err
}
return obj.(*$.type|raw$), err
}
`
var deleteTemplate = `
func (c *Fake$.type|publicPlural$) Delete(name string, options *$.DeleteOptions|raw$) error {
_, err := c.Fake.
$if .namespaced$Invokes($.NewDeleteAction|raw$($.type|allLowercasePlural$Resource, c.ns, name), &$.type|raw${})
$else$Invokes($.NewRootDeleteAction|raw$($.type|allLowercasePlural$Resource, name), &$.type|raw${})$end$
return err
}
`
var deleteCollectionTemplate = `
func (c *Fake$.type|publicPlural$) DeleteCollection(options *$.DeleteOptions|raw$, listOptions $.ListOptions|raw$) error {
$if .namespaced$action := $.NewDeleteCollectionAction|raw$($.type|allLowercasePlural$Resource, c.ns, listOptions)
$else$action := $.NewRootDeleteCollectionAction|raw$($.type|allLowercasePlural$Resource, listOptions)
$end$
_, err := c.Fake.Invokes(action, &$.type|raw$List{})
return err
}
`
var createTemplate = `
func (c *Fake$.type|publicPlural$) Create($.type|private$ *$.type|raw$) (result *$.type|raw$, err error) {
obj, err := c.Fake.
$if .namespaced$Invokes($.NewCreateAction|raw$($.type|allLowercasePlural$Resource, c.ns, $.type|private$), &$.type|raw${})
$else$Invokes($.NewRootCreateAction|raw$($.type|allLowercasePlural$Resource, $.type|private$), &$.type|raw${})$end$
if obj == nil {
return nil, err
}
return obj.(*$.type|raw$), err
}
`
var updateTemplate = `
func (c *Fake$.type|publicPlural$) Update($.type|private$ *$.type|raw$) (result *$.type|raw$, err error) {
obj, err := c.Fake.
$if .namespaced$Invokes($.NewUpdateAction|raw$($.type|allLowercasePlural$Resource, c.ns, $.type|private$), &$.type|raw${})
$else$Invokes($.NewRootUpdateAction|raw$($.type|allLowercasePlural$Resource, $.type|private$), &$.type|raw${})$end$
if obj == nil {
return nil, err
}
return obj.(*$.type|raw$), err
}
`
var updateStatusTemplate = `
func (c *Fake$.type|publicPlural$) UpdateStatus($.type|private$ *$.type|raw$) (*$.type|raw$, error) {
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 obj == nil {
return nil, err
}
return obj.(*$.type|raw$), err
}
`
var watchTemplate = `
// Watch returns a $.watchInterface|raw$ that watches the requested $.type|privatePlural$.
func (c *Fake$.type|publicPlural$) Watch(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$
}
`
var patchTemplate = `
// Patch applies the patch and returns the patched $.type|private$.
func (c *Fake$.type|publicPlural$) Patch(name string, pt $.PatchType|raw$, data []byte, subresources ...string) (result *$.type|raw$, err error) {
obj, err := c.Fake.
$if .namespaced$Invokes($.NewPatchSubresourceAction|raw$($.type|allLowercasePlural$Resource, c.ns, name, data, subresources... ), &$.type|raw${})
$else$Invokes($.NewRootPatchSubresourceAction|raw$($.type|allLowercasePlural$Resource, name, data, subresources...), &$.type|raw${})$end$
if obj == nil {
return nil, err
}
return obj.(*$.type|raw$), err
}
`

View file

@ -0,0 +1,200 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package generators
import (
"fmt"
"io"
"path/filepath"
"strings"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
clientgentypes "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types"
)
// genClientset generates a package for a clientset.
type genClientset struct {
generator.DefaultGen
groups []clientgentypes.GroupVersions
typedClientPath string
outputPackage string
imports namer.ImportTracker
clientsetGenerated bool
}
var _ generator.Generator = &genClientset{}
func (g *genClientset) Namers(c *generator.Context) namer.NameSystems {
return namer.NameSystems{
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
}
}
// We only want to call GenerateType() once.
func (g *genClientset) Filter(c *generator.Context, t *types.Type) bool {
ret := !g.clientsetGenerated
g.clientsetGenerated = true
return ret
}
func (g *genClientset) Imports(c *generator.Context) (imports []string) {
imports = append(imports, g.imports.ImportLines()...)
for _, group := range g.groups {
for _, version := range group.Versions {
typedClientPath := filepath.Join(g.typedClientPath, group.Group.NonEmpty(), version.NonEmpty())
imports = append(imports, strings.ToLower(fmt.Sprintf("%s%s \"%s\"", version.NonEmpty(), group.Group.NonEmpty(), typedClientPath)))
}
}
imports = append(imports, "github.com/golang/glog")
imports = append(imports, "k8s.io/kubernetes/pkg/util/flowcontrol")
// import solely to initialize client auth plugins.
imports = append(imports, "_ \"k8s.io/kubernetes/plugin/pkg/client/auth\"")
return
}
func (g *genClientset) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
// 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, "$", "$")
const pkgDiscovery = "k8s.io/kubernetes/pkg/client/typed/discovery"
const pkgRESTClient = "k8s.io/kubernetes/pkg/client/restclient"
allGroups := clientgentypes.ToGroupVersionPackages(g.groups)
m := map[string]interface{}{
"allGroups": allGroups,
"Config": c.Universe.Type(types.Name{Package: pkgRESTClient, Name: "Config"}),
"DefaultKubernetesUserAgent": c.Universe.Function(types.Name{Package: pkgRESTClient, Name: "DefaultKubernetesUserAgent"}),
"RESTClientInterface": c.Universe.Type(types.Name{Package: pkgRESTClient, Name: "Interface"}),
"DiscoveryInterface": c.Universe.Type(types.Name{Package: pkgDiscovery, Name: "DiscoveryInterface"}),
"DiscoveryClient": c.Universe.Type(types.Name{Package: pkgDiscovery, Name: "DiscoveryClient"}),
"NewDiscoveryClientForConfig": c.Universe.Function(types.Name{Package: pkgDiscovery, Name: "NewDiscoveryClientForConfig"}),
"NewDiscoveryClientForConfigOrDie": c.Universe.Function(types.Name{Package: pkgDiscovery, Name: "NewDiscoveryClientForConfigOrDie"}),
"NewDiscoveryClient": c.Universe.Function(types.Name{Package: pkgDiscovery, Name: "NewDiscoveryClient"}),
}
sw.Do(clientsetInterface, m)
sw.Do(clientsetTemplate, m)
for _, g := range allGroups {
sw.Do(clientsetInterfaceImplTemplate, g)
// don't generated the default method if generating internalversion clientset
if g.IsDefaultVersion && g.Version != "" {
sw.Do(clientsetInterfaceDefaultVersionImpl, g)
}
}
sw.Do(getDiscoveryTemplate, m)
sw.Do(newClientsetForConfigTemplate, m)
sw.Do(newClientsetForConfigOrDieTemplate, m)
sw.Do(newClientsetForRESTClientTemplate, m)
return sw.Error()
}
var clientsetInterface = `
type Interface interface {
Discovery() $.DiscoveryInterface|raw$
$range .allGroups$$.GroupVersion$() $.PackageName$.$.GroupVersion$Interface
$if .IsDefaultVersion$// Deprecated: please explicitly pick a version if possible.
$.Group$() $.PackageName$.$.GroupVersion$Interface$end$
$end$
}
`
var clientsetTemplate = `
// Clientset contains the clients for groups. Each group has exactly one
// version included in a Clientset.
type Clientset struct {
*$.DiscoveryClient|raw$
$range .allGroups$*$.PackageName$.$.GroupVersion$Client
$end$
}
`
var clientsetInterfaceImplTemplate = `
// $.GroupVersion$ retrieves the $.GroupVersion$Client
func (c *Clientset) $.GroupVersion$() $.PackageName$.$.GroupVersion$Interface {
if c == nil {
return nil
}
return c.$.GroupVersion$Client
}
`
var clientsetInterfaceDefaultVersionImpl = `
// Deprecated: $.Group$ retrieves the default version of $.Group$Client.
// Please explicitly pick a version.
func (c *Clientset) $.Group$() $.PackageName$.$.GroupVersion$Interface {
if c == nil {
return nil
}
return c.$.GroupVersion$Client
}
`
var getDiscoveryTemplate = `
// Discovery retrieves the DiscoveryClient
func (c *Clientset) Discovery() $.DiscoveryInterface|raw$ {
return c.DiscoveryClient
}
`
var newClientsetForConfigTemplate = `
// NewForConfig creates a new Clientset for the given config.
func NewForConfig(c *$.Config|raw$) (*Clientset, error) {
configShallowCopy := *c
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
}
var clientset Clientset
var err error
$range .allGroups$ clientset.$.GroupVersion$Client, err =$.PackageName$.NewForConfig(&configShallowCopy)
if err!=nil {
return nil, err
}
$end$
clientset.DiscoveryClient, err = $.NewDiscoveryClientForConfig|raw$(&configShallowCopy)
if err!=nil {
glog.Errorf("failed to create the DiscoveryClient: %v", err)
return nil, err
}
return &clientset, nil
}
`
var newClientsetForConfigOrDieTemplate = `
// NewForConfigOrDie creates a new Clientset for the given config and
// panics if there is an error in the config.
func NewForConfigOrDie(c *$.Config|raw$) *Clientset {
var clientset Clientset
$range .allGroups$ clientset.$.GroupVersion$Client =$.PackageName$.NewForConfigOrDie(c)
$end$
clientset.DiscoveryClient = $.NewDiscoveryClientForConfigOrDie|raw$(c)
return &clientset
}
`
var newClientsetForRESTClientTemplate = `
// New creates a new Clientset for the given RESTClient.
func New(c $.RESTClientInterface|raw$) *Clientset {
var clientset Clientset
$range .allGroups$ clientset.$.GroupVersion$Client =$.PackageName$.New(c)
$end$
clientset.DiscoveryClient = $.NewDiscoveryClient|raw$(c)
return &clientset
}
`

View file

@ -0,0 +1,54 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package generators
import (
"io"
"os"
"path/filepath"
"strings"
"k8s.io/gengo/generator"
"k8s.io/gengo/types"
)
// genExpansion produces a file for a group client, e.g. ExtensionsClient for the extension group.
type genExpansion struct {
generator.DefaultGen
groupPath string
// types in a group
types []*types.Type
}
// We only want to call GenerateType() once per group.
func (g *genExpansion) Filter(c *generator.Context, t *types.Type) bool {
return t == g.types[0]
}
func (g *genExpansion) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
sw := generator.NewSnippetWriter(w, c, "$", "$")
for _, t := range g.types {
if _, err := os.Stat(filepath.Join(g.groupPath, strings.ToLower(t.Name.Name+"_expansion.go"))); os.IsNotExist(err) {
sw.Do(expansionInterfaceTemplate, t)
}
}
return sw.Error()
}
var expansionInterfaceTemplate = `
type $.|public$Expansion interface {}
`

View file

@ -0,0 +1,253 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package generators
import (
"io"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
)
// genGroup produces a file for a group client, e.g. ExtensionsClient for the extension group.
type genGroup struct {
generator.DefaultGen
outputPackage string
group string
version string
apiPath string
// types in this group
types []*types.Type
imports namer.ImportTracker
inputPacakge string
}
var _ generator.Generator = &genGroup{}
// We only want to call GenerateType() once per group.
func (g *genGroup) Filter(c *generator.Context, t *types.Type) bool {
return t == g.types[0]
}
func (g *genGroup) Namers(c *generator.Context) namer.NameSystems {
return namer.NameSystems{
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
}
}
func (g *genGroup) Imports(c *generator.Context) (imports []string) {
imports = append(imports, g.imports.ImportLines()...)
return
}
func (g *genGroup) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
sw := generator.NewSnippetWriter(w, c, "$", "$")
const pkgRESTClient = "k8s.io/kubernetes/pkg/client/restclient"
const pkgRegistered = "k8s.io/kubernetes/pkg/apimachinery/registered"
const pkgAPI = "k8s.io/kubernetes/pkg/api"
const pkgSerializer = "k8s.io/kubernetes/pkg/runtime/serializer"
const pkgUnversioned = "k8s.io/kubernetes/pkg/api/unversioned"
const pkgSchema = "k8s.io/kubernetes/pkg/runtime/schema"
apiPath := func(group string) string {
if len(g.apiPath) > 0 {
return `"` + g.apiPath + `"`
}
if group == "core" {
return `"/api"`
}
return `"/apis"`
}
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.inputPacakge)
if override := types.ExtractCommentTags("+", p.DocComments)["groupName"]; override != nil {
groupName = override[0]
}
m := map[string]interface{}{
"group": g.group,
"version": g.version,
"GroupVersion": namer.IC(g.group) + namer.IC(g.version),
"groupName": groupName,
"types": g.types,
"Config": c.Universe.Type(types.Name{Package: pkgRESTClient, Name: "Config"}),
"DefaultKubernetesUserAgent": c.Universe.Function(types.Name{Package: pkgRESTClient, Name: "DefaultKubernetesUserAgent"}),
"RESTClientInterface": c.Universe.Type(types.Name{Package: pkgRESTClient, Name: "Interface"}),
"RESTClientFor": c.Universe.Function(types.Name{Package: pkgRESTClient, Name: "RESTClientFor"}),
"Group": c.Universe.Variable(types.Name{Package: pkgRegistered, Name: "Group"}),
"GroupOrDie": c.Universe.Variable(types.Name{Package: pkgRegistered, Name: "GroupOrDie"}),
"IsEnabledVersion": c.Universe.Variable(types.Name{Package: pkgRegistered, Name: "IsEnabledVersion"}),
"ParseGroupVersion": c.Universe.Function(types.Name{Package: pkgSchema, Name: "ParseGroupVersion"}),
"apiPath": apiPath(g.group),
"codecs": c.Universe.Variable(types.Name{Package: pkgAPI, Name: "Codecs"}),
"directCodecFactory": c.Universe.Variable(types.Name{Package: pkgSerializer, Name: "DirectCodecFactory"}),
"Errorf": c.Universe.Variable(types.Name{Package: "fmt", Name: "Errorf"}),
}
sw.Do(groupInterfaceTemplate, m)
sw.Do(groupClientTemplate, m)
for _, t := range g.types {
wrapper := map[string]interface{}{
"type": t,
"GroupVersion": namer.IC(g.group) + namer.IC(g.version),
}
namespaced := !extractBoolTagOrDie("nonNamespaced", t.SecondClosestCommentLines)
if namespaced {
sw.Do(getterImplNamespaced, wrapper)
} else {
sw.Do(getterImplNonNamespaced, wrapper)
}
}
sw.Do(newClientForConfigTemplate, m)
sw.Do(newClientForConfigOrDieTemplate, m)
sw.Do(newClientForRESTClientTemplate, m)
if g.version == "" {
sw.Do(setInternalVersionClientDefaultsTemplate, m)
} else {
sw.Do(setClientDefaultsTemplate, m)
}
sw.Do(getRESTClient, m)
return sw.Error()
}
var groupInterfaceTemplate = `
type $.GroupVersion$Interface interface {
RESTClient() $.RESTClientInterface|raw$
$range .types$ $.|publicPlural$Getter
$end$
}
`
var groupClientTemplate = `
// $.GroupVersion$Client is used to interact with features provided by the $.Group$ group.
type $.GroupVersion$Client struct {
restClient $.RESTClientInterface|raw$
}
`
var getterImplNamespaced = `
func (c *$.GroupVersion$Client) $.type|publicPlural$(namespace string) $.type|public$Interface {
return new$.type|publicPlural$(c, namespace)
}
`
var getterImplNonNamespaced = `
func (c *$.GroupVersion$Client) $.type|publicPlural$() $.type|public$Interface {
return new$.type|publicPlural$(c)
}
`
var newClientForConfigTemplate = `
// NewForConfig creates a new $.GroupVersion$Client for the given config.
func NewForConfig(c *$.Config|raw$) (*$.GroupVersion$Client, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
client, err := $.RESTClientFor|raw$(&config)
if err != nil {
return nil, err
}
return &$.GroupVersion$Client{client}, nil
}
`
var newClientForConfigOrDieTemplate = `
// NewForConfigOrDie creates a new $.GroupVersion$Client for the given config and
// panics if there is an error in the config.
func NewForConfigOrDie(c *$.Config|raw$) *$.GroupVersion$Client {
client, err := NewForConfig(c)
if err != nil {
panic(err)
}
return client
}
`
var getRESTClient = `
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *$.GroupVersion$Client) RESTClient() $.RESTClientInterface|raw$ {
if c == nil {
return nil
}
return c.restClient
}
`
var newClientForRESTClientTemplate = `
// New creates a new $.GroupVersion$Client for the given RESTClient.
func New(c $.RESTClientInterface|raw$) *$.GroupVersion$Client {
return &$.GroupVersion$Client{c}
}
`
var setInternalVersionClientDefaultsTemplate = `
func setConfigDefaults(config *$.Config|raw$) error {
// if $.group$ group is not registered, return an error
g, err := $.Group|raw$("$.groupName$")
if err != nil {
return err
}
config.APIPath = $.apiPath$
if config.UserAgent == "" {
config.UserAgent = $.DefaultKubernetesUserAgent|raw$()
}
if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group {
copyGroupVersion := g.GroupVersion
config.GroupVersion = &copyGroupVersion
}
config.NegotiatedSerializer = $.codecs|raw$
if config.QPS == 0 {
config.QPS = 5
}
if config.Burst == 0 {
config.Burst = 10
}
return nil
}
`
var setClientDefaultsTemplate = `
func setConfigDefaults(config *$.Config|raw$) error {
gv, err := $.ParseGroupVersion|raw$("$.groupName$/$.version$")
if err != nil {
return err
}
// if $.groupName$/$.version$ is not enabled, return an error
if ! $.IsEnabledVersion|raw$(gv) {
return $.Errorf|raw$("$.groupName$/$.version$ is not enabled")
}
config.APIPath = $.apiPath$
if config.UserAgent == "" {
config.UserAgent = $.DefaultKubernetesUserAgent|raw$()
}
copyGroupVersion := gv
config.GroupVersion = &copyGroupVersion
config.NegotiatedSerializer = $.directCodecFactory|raw${CodecFactory: $.codecs|raw$}
return nil
}
`

View file

@ -0,0 +1,339 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package generators
import (
"io"
"path/filepath"
"strings"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
)
// genClientForType produces a file for each top-level type.
type genClientForType struct {
generator.DefaultGen
outputPackage string
group string
version string
typeToMatch *types.Type
imports namer.ImportTracker
}
var _ generator.Generator = &genClientForType{}
// 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 }
func (g *genClientForType) Namers(c *generator.Context) namer.NameSystems {
return namer.NameSystems{
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
}
}
func (g *genClientForType) Imports(c *generator.Context) (imports []string) {
return g.imports.ImportLines()
}
// Ideally, we'd like hasStatus to return true if there is a subresource path
// registered for "status" in the API server, but we do not have that
// information, so hasStatus returns true if the type has a status field.
func hasStatus(t *types.Type) bool {
for _, m := range t.Members {
if m.Name == "Status" && strings.Contains(m.Tags, `json:"status`) {
return true
}
}
return false
}
// GenerateType makes the body of a file implementing the individual typed client for type t.
func (g *genClientForType) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
sw := generator.NewSnippetWriter(w, c, "$", "$")
pkg := filepath.Base(t.Name.Package)
namespaced := !extractBoolTagOrDie("nonNamespaced", t.SecondClosestCommentLines)
m := map[string]interface{}{
"type": t,
"package": pkg,
"Package": namer.IC(pkg),
"Group": namer.IC(g.group),
"GroupVersion": namer.IC(g.group) + namer.IC(g.version),
"watchInterface": c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/watch", Name: "Interface"}),
"RESTClientInterface": c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/client/restclient", Name: "Interface"}),
"apiParameterCodec": c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api", Name: "ParameterCodec"}),
"PatchType": c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api", Name: "PatchType"}),
"namespaced": namespaced,
}
if g.version == "" {
m["DeleteOptions"] = c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api", Name: "DeleteOptions"})
m["ListOptions"] = c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api", Name: "ListOptions"})
} else {
m["DeleteOptions"] = c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api/v1", Name: "DeleteOptions"})
m["ListOptions"] = c.Universe.Type(types.Name{Package: "k8s.io/kubernetes/pkg/api/v1", Name: "ListOptions"})
}
sw.Do(getterComment, m)
if namespaced {
sw.Do(getterNamesapced, m)
} else {
sw.Do(getterNonNamesapced, m)
}
noMethods := extractBoolTagOrDie("noMethods", t.SecondClosestCommentLines) == true
sw.Do(interfaceTemplate1, m)
if !noMethods {
sw.Do(interfaceTemplate2, m)
// Include the UpdateStatus method if the type has a status
if hasStatus(t) {
sw.Do(interfaceUpdateStatusTemplate, m)
}
sw.Do(interfaceTemplate3, m)
}
sw.Do(interfaceTemplate4, m)
if namespaced {
sw.Do(structNamespaced, m)
sw.Do(newStructNamespaced, m)
} else {
sw.Do(structNonNamespaced, m)
sw.Do(newStructNonNamespaced, m)
}
if !noMethods {
sw.Do(createTemplate, m)
sw.Do(updateTemplate, m)
// Generate the UpdateStatus method if the type has a status
if hasStatus(t) {
sw.Do(updateStatusTemplate, m)
}
sw.Do(deleteTemplate, m)
sw.Do(deleteCollectionTemplate, m)
sw.Do(getTemplate, m)
sw.Do(listTemplate, m)
sw.Do(watchTemplate, m)
sw.Do(patchTemplate, m)
}
return sw.Error()
}
// group client will implement this interface.
var getterComment = `
// $.type|publicPlural$Getter has a method to return a $.type|public$Interface.
// A group's client should implement this interface.`
var getterNamesapced = `
type $.type|publicPlural$Getter interface {
$.type|publicPlural$(namespace string) $.type|public$Interface
}
`
var getterNonNamesapced = `
type $.type|publicPlural$Getter interface {
$.type|publicPlural$() $.type|public$Interface
}
`
// this type's interface, typed client will implement this interface.
var interfaceTemplate1 = `
// $.type|public$Interface has methods to work with $.type|public$ resources.
type $.type|public$Interface interface {`
var interfaceTemplate2 = `
Create(*$.type|raw$) (*$.type|raw$, error)
Update(*$.type|raw$) (*$.type|raw$, error)`
var interfaceUpdateStatusTemplate = `
UpdateStatus(*$.type|raw$) (*$.type|raw$, error)`
// template for the Interface
var interfaceTemplate3 = `
Delete(name string, options *$.DeleteOptions|raw$) error
DeleteCollection(options *$.DeleteOptions|raw$, listOptions $.ListOptions|raw$) error
Get(name string) (*$.type|raw$, error)
List(opts $.ListOptions|raw$) (*$.type|raw$List, error)
Watch(opts $.ListOptions|raw$) ($.watchInterface|raw$, error)
Patch(name string, pt $.PatchType|raw$, data []byte, subresources ...string) (result *$.type|raw$, err error)`
var interfaceTemplate4 = `
$.type|public$Expansion
}
`
// 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
}
`
// 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$
}
`
var newStructNamespaced = `
// new$.type|publicPlural$ returns a $.type|publicPlural$
func new$.type|publicPlural$(c *$.GroupVersion$Client, namespace string) *$.type|privatePlural$ {
return &$.type|privatePlural${
client: c.RESTClient(),
ns: namespace,
}
}
`
var newStructNonNamespaced = `
// new$.type|publicPlural$ returns a $.type|publicPlural$
func new$.type|publicPlural$(c *$.GroupVersion$Client) *$.type|privatePlural$ {
return &$.type|privatePlural${
client: c.RESTClient(),
}
}
`
var listTemplate = `
// List takes label and field selectors, and returns the list of $.type|publicPlural$ that match those selectors.
func (c *$.type|privatePlural$) List(opts $.ListOptions|raw$) (result *$.type|raw$List, err error) {
result = &$.type|raw$List{}
err = c.client.Get().
$if .namespaced$Namespace(c.ns).$end$
Resource("$.type|allLowercasePlural$").
VersionedParams(&opts, $.apiParameterCodec|raw$).
Do().
Into(result)
return
}
`
var getTemplate = `
// Get takes name of the $.type|private$, and returns the corresponding $.type|private$ object, and an error if there is any.
func (c *$.type|privatePlural$) Get(name string) (result *$.type|raw$, err error) {
result = &$.type|raw${}
err = c.client.Get().
$if .namespaced$Namespace(c.ns).$end$
Resource("$.type|allLowercasePlural$").
Name(name).
Do().
Into(result)
return
}
`
var deleteTemplate = `
// Delete takes name of the $.type|private$ and deletes it. Returns an error if one occurs.
func (c *$.type|privatePlural$) Delete(name string, options *$.DeleteOptions|raw$) error {
return c.client.Delete().
$if .namespaced$Namespace(c.ns).$end$
Resource("$.type|allLowercasePlural$").
Name(name).
Body(options).
Do().
Error()
}
`
var deleteCollectionTemplate = `
// DeleteCollection deletes a collection of objects.
func (c *$.type|privatePlural$) DeleteCollection(options *$.DeleteOptions|raw$, listOptions $.ListOptions|raw$) error {
return c.client.Delete().
$if .namespaced$Namespace(c.ns).$end$
Resource("$.type|allLowercasePlural$").
VersionedParams(&listOptions, $.apiParameterCodec|raw$).
Body(options).
Do().
Error()
}
`
var createTemplate = `
// Create takes the representation of a $.type|private$ and creates it. Returns the server's representation of the $.type|private$, and an error, if there is any.
func (c *$.type|privatePlural$) Create($.type|private$ *$.type|raw$) (result *$.type|raw$, err error) {
result = &$.type|raw${}
err = c.client.Post().
$if .namespaced$Namespace(c.ns).$end$
Resource("$.type|allLowercasePlural$").
Body($.type|private$).
Do().
Into(result)
return
}
`
var updateTemplate = `
// Update takes the representation of a $.type|private$ and updates it. Returns the server's representation of the $.type|private$, and an error, if there is any.
func (c *$.type|privatePlural$) Update($.type|private$ *$.type|raw$) (result *$.type|raw$, err error) {
result = &$.type|raw${}
err = c.client.Put().
$if .namespaced$Namespace(c.ns).$end$
Resource("$.type|allLowercasePlural$").
Name($.type|private$.Name).
Body($.type|private$).
Do().
Into(result)
return
}
`
var updateStatusTemplate = `
func (c *$.type|privatePlural$) UpdateStatus($.type|private$ *$.type|raw$) (result *$.type|raw$, err error) {
result = &$.type|raw${}
err = c.client.Put().
$if .namespaced$Namespace(c.ns).$end$
Resource("$.type|allLowercasePlural$").
Name($.type|private$.Name).
SubResource("status").
Body($.type|private$).
Do().
Into(result)
return
}
`
var watchTemplate = `
// Watch returns a $.watchInterface|raw$ that watches the requested $.type|privatePlural$.
func (c *$.type|privatePlural$) Watch(opts $.ListOptions|raw$) ($.watchInterface|raw$, error) {
return c.client.Get().
Prefix("watch").
$if .namespaced$Namespace(c.ns).$end$
Resource("$.type|allLowercasePlural$").
VersionedParams(&opts, $.apiParameterCodec|raw$).
Watch()
}
`
var patchTemplate = `
// Patch applies the patch and returns the patched $.type|private$.
func (c *$.type|privatePlural$) Patch(name string, pt $.PatchType|raw$, data []byte, subresources ...string) (result *$.type|raw$, err error) {
result = &$.type|raw${}
err = c.client.Patch(pt).
$if .namespaced$Namespace(c.ns).$end$
Resource("$.type|allLowercasePlural$").
SubResource(subresources...).
Name(name).
Body(data).
Do().
Into(result)
return
}
`

View file

@ -0,0 +1,33 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package generators
import (
"github.com/golang/glog"
"k8s.io/gengo/types"
)
// extractBoolTagOrDie gets the comment-tags for the key and asserts that, if
// it exists, the value is boolean. If the tag did not exist, it returns
// false.
func extractBoolTagOrDie(key string, lines []string) bool {
val, err := types.ExtractSingleBoolCommentTag("+", key, false, lines)
if err != nil {
glog.Fatalf(err.Error())
}
return val
}

View file

@ -0,0 +1,218 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// client-gen makes the individual typed clients using go2idl.
package main
import (
"fmt"
"path/filepath"
"sort"
"strings"
"k8s.io/gengo/args"
clientgenargs "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/args"
"k8s.io/kubernetes/cmd/libs/go2idl/client-gen/generators"
"k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types"
"github.com/golang/glog"
flag "github.com/spf13/pflag"
)
var (
test = flag.BoolP("test", "t", false, "set this flag to generate the client code for the testdata")
inputVersions = flag.StringSlice("input", []string{
"api/",
"authentication/",
"authorization/",
"autoscaling/",
"batch/",
"certificates/",
"extensions/",
"rbac/",
"storage/",
"apps/",
"policy/",
}, "group/versions that client-gen will generate clients for. At most one version per group is allowed. Specified in the format \"group1/version1,group2/version2...\". Default to \"api/,extensions/,autoscaling/,batch/,rbac/\"")
includedTypesOverrides = flag.StringSlice("included-types-overrides", []string{}, "list of group/version/type for which client should be generated. By default, client is generated for all types which have genclient=true in types.go. This overrides that. For each groupVersion in this list, only the types mentioned here will be included. The default check of genclient=true will be used for other group versions.")
basePath = flag.String("input-base", "k8s.io/kubernetes/pkg/apis", "base path to look for the api group. Default to \"k8s.io/kubernetes/pkg/apis\"")
clientsetName = flag.StringP("clientset-name", "n", "internalclientset", "the name of the generated clientset package.")
clientsetAPIPath = flag.StringP("clientset-api-path", "", "", "the value of default API path.")
clientsetPath = flag.String("clientset-path", "k8s.io/kubernetes/pkg/client/clientset_generated/", "the generated clientset will be output to <clientset-path>/<clientset-name>. Default to \"k8s.io/kubernetes/pkg/client/clientset_generated/\"")
clientsetOnly = flag.Bool("clientset-only", false, "when set, client-gen only generates the clientset shell, without generating the individual typed clients")
fakeClient = flag.Bool("fake-clientset", true, "when set, client-gen will generate the fake clientset that can be used in tests")
)
func versionToPath(gvPath string, group string, version string) (path string) {
// special case for the core group
if group == "api" {
path = filepath.Join(*basePath, "../api", version)
} else {
path = filepath.Join(*basePath, gvPath, group, version)
}
return
}
func parseGroupVersionType(gvtString string) (gvString string, typeStr string, err error) {
invalidFormatErr := fmt.Errorf("invalid value: %s, should be of the form group/version/type", gvtString)
subs := strings.Split(gvtString, "/")
length := len(subs)
switch length {
case 2:
// gvtString of the form group/type, e.g. api/Service,extensions/ReplicaSet
return subs[0] + "/", subs[1], nil
case 3:
return strings.Join(subs[:length-1], "/"), subs[length-1], nil
default:
return "", "", invalidFormatErr
}
}
func parsePathGroupVersion(pgvString string) (gvPath string, gvString string) {
subs := strings.Split(pgvString, "/")
length := len(subs)
switch length {
case 0, 1, 2:
return "", pgvString
default:
return strings.Join(subs[:length-2], "/"), strings.Join(subs[length-2:], "/")
}
}
func parseInputVersions() (paths []string, groups []types.GroupVersions, gvToPath map[types.GroupVersion]string, err error) {
var seenGroups = make(map[types.Group]*types.GroupVersions)
gvToPath = make(map[types.GroupVersion]string)
for _, input := range *inputVersions {
gvPath, gvString := parsePathGroupVersion(input)
gv, err := types.ToGroupVersion(gvString)
if err != nil {
return nil, nil, nil, err
}
if group, ok := seenGroups[gv.Group]; ok {
(*seenGroups[gv.Group]).Versions = append(group.Versions, gv.Version)
} else {
seenGroups[gv.Group] = &types.GroupVersions{
Group: gv.Group,
Versions: []types.Version{gv.Version},
}
}
path := versionToPath(gvPath, gv.Group.String(), gv.Version.String())
paths = append(paths, path)
gvToPath[gv] = path
}
var groupNames []string
for groupName := range seenGroups {
groupNames = append(groupNames, groupName.String())
}
sort.Strings(groupNames)
for _, groupName := range groupNames {
groups = append(groups, *seenGroups[types.Group(groupName)])
}
return paths, groups, gvToPath, nil
}
func parseIncludedTypesOverrides() (map[types.GroupVersion][]string, error) {
overrides := make(map[types.GroupVersion][]string)
for _, input := range *includedTypesOverrides {
gvString, typeStr, err := parseGroupVersionType(input)
if err != nil {
return nil, err
}
gv, err := types.ToGroupVersion(gvString)
if err != nil {
return nil, err
}
types, ok := overrides[gv]
if !ok {
types = []string{}
}
types = append(types, typeStr)
overrides[gv] = types
}
return overrides, nil
}
func main() {
arguments := args.Default()
arguments.GoHeaderFilePath = filepath.Join(args.DefaultSourceTree(), "k8s.io/kubernetes/hack/boilerplate/boilerplate.go.txt")
flag.Parse()
var cmdArgs string
flag.VisitAll(func(f *flag.Flag) {
if !f.Changed || f.Name == "verify-only" {
return
}
cmdArgs = cmdArgs + fmt.Sprintf("--%s=%s ", f.Name, f.Value)
})
dependencies := []string{
"k8s.io/kubernetes/pkg/fields",
"k8s.io/kubernetes/pkg/labels",
"k8s.io/kubernetes/pkg/watch",
"k8s.io/kubernetes/pkg/apimachinery/registered",
}
if *test {
arguments.InputDirs = append(dependencies, []string{
"k8s.io/kubernetes/cmd/libs/go2idl/client-gen/test_apis/testgroup",
}...)
arguments.CustomArgs = clientgenargs.Args{
Groups: []types.GroupVersions{{Group: "testgroup", Versions: []types.Version{""}}},
GroupVersionToInputPath: map[types.GroupVersion]string{
types.GroupVersion{Group: "testgroup", Version: ""}: "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/test_apis/testgroup",
},
ClientsetName: "test_internalclientset",
ClientsetOutputPath: "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/testoutput/clientset_generated/",
ClientsetOnly: false,
FakeClient: true,
CmdArgs: cmdArgs,
}
} else {
inputPath, groups, gvToPath, err := parseInputVersions()
if err != nil {
glog.Fatalf("Error: %v", err)
}
includedTypesOverrides, err := parseIncludedTypesOverrides()
if err != nil {
glog.Fatalf("Unexpected error: %v", err)
}
glog.V(3).Infof("going to generate clientset from these input paths: %v", inputPath)
arguments.InputDirs = append(inputPath, dependencies...)
arguments.CustomArgs = clientgenargs.Args{
Groups: groups,
GroupVersionToInputPath: gvToPath,
ClientsetName: *clientsetName,
ClientsetAPIPath: *clientsetAPIPath,
ClientsetOutputPath: *clientsetPath,
ClientsetOnly: *clientsetOnly,
FakeClient: *fakeClient,
CmdArgs: cmdArgs,
IncludedTypesOverrides: includedTypesOverrides,
}
glog.V(3).Infof("==arguments: %v\n", arguments)
}
if err := arguments.Execute(
generators.NameSystems(),
generators.DefaultNameSystem(),
generators.Packages,
); err != nil {
glog.Fatalf("Error: %v", err)
}
}

View file

@ -0,0 +1,4 @@
This dir can not be named "testdata" because of the way ugorji gnerates code.
Specifically, it emits a .go file and then calls `go run` on it. Because
"testdata" is a special name to Go, it decides NOT to find the vendor dir, and
therefore fails to compile. Just name it something else.

View file

@ -0,0 +1,30 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"register.go",
"types.generated.go",
"types.go",
],
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//pkg/apis/meta/v1:go_default_library",
"//pkg/runtime:go_default_library",
"//pkg/runtime/schema:go_default_library",
"//pkg/types:go_default_library",
"//vendor:github.com/ugorji/go/codec",
],
)

View file

@ -0,0 +1,18 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// +groupName=testgroup.k8s.io
package testgroup // import "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/test_apis/testgroup"

View file

@ -0,0 +1,29 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_library(
name = "go_default_library",
srcs = ["install.go"],
tags = ["automanaged"],
deps = [
"//cmd/libs/go2idl/client-gen/test_apis/testgroup:go_default_library",
"//cmd/libs/go2idl/client-gen/test_apis/testgroup/v1:go_default_library",
"//pkg/api:go_default_library",
"//pkg/api/meta:go_default_library",
"//pkg/apimachinery:go_default_library",
"//pkg/apimachinery/registered:go_default_library",
"//pkg/runtime:go_default_library",
"//pkg/runtime/schema:go_default_library",
"//pkg/util/sets:go_default_library",
"//vendor:github.com/golang/glog",
],
)

View file

@ -0,0 +1,123 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package install installs the experimental API group, making it available as
// an option to all of the API encoding/decoding machinery.
package install
import (
"fmt"
"github.com/golang/glog"
"k8s.io/kubernetes/cmd/libs/go2idl/client-gen/test_apis/testgroup"
"k8s.io/kubernetes/cmd/libs/go2idl/client-gen/test_apis/testgroup/v1"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/apimachinery"
"k8s.io/kubernetes/pkg/apimachinery/registered"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/util/sets"
)
const importPrefix = "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/test_apis/testgroup"
var accessor = meta.NewAccessor()
const groupName = "testgroup.k8s.io"
// availableVersions lists all known external versions for this group from most preferred to least preferred
var availableVersions = []schema.GroupVersion{{Group: groupName, Version: "v1"}}
func init() {
externalVersions := availableVersions
registered.RegisterVersions(availableVersions)
if err := registered.EnableVersions(externalVersions...); err != nil {
glog.V(4).Infof("%v", err)
return
}
if err := enableVersions(externalVersions); err != nil {
glog.V(4).Infof("%v", err)
return
}
}
// TODO: enableVersions should be centralized rather than spread in each API
// group.
// We can combine registered.RegisterVersions, registered.EnableVersions and
// registered.RegisterGroup once we have moved enableVersions there.
func enableVersions(externalVersions []schema.GroupVersion) error {
addVersionsToScheme(externalVersions...)
preferredExternalVersion := externalVersions[0]
groupMeta := apimachinery.GroupMeta{
GroupVersion: preferredExternalVersion,
GroupVersions: externalVersions,
RESTMapper: newRESTMapper(externalVersions),
SelfLinker: runtime.SelfLinker(accessor),
InterfacesFor: interfacesFor,
}
if err := registered.RegisterGroup(groupMeta); err != nil {
return err
}
return nil
}
func newRESTMapper(externalVersions []schema.GroupVersion) meta.RESTMapper {
// the list of kinds that are scoped at the root of the api hierarchy
// if a kind is not enumerated here, it is assumed to have a namespace scope
rootScoped := sets.NewString()
ignoredKinds := sets.NewString()
return api.NewDefaultRESTMapper(externalVersions, interfacesFor, importPrefix, ignoredKinds, rootScoped)
}
// InterfacesFor returns the default Codec and ResourceVersioner for a given version
// string, or an error if the version is not known.
func interfacesFor(version schema.GroupVersion) (*meta.VersionInterfaces, error) {
switch version {
case v1.SchemeGroupVersion:
return &meta.VersionInterfaces{
ObjectConvertor: api.Scheme,
MetadataAccessor: accessor,
}, nil
default:
g, _ := registered.Group(groupName)
return nil, fmt.Errorf("unsupported storage version: %s (valid: %v)", version, g.GroupVersions)
}
}
func addVersionsToScheme(externalVersions ...schema.GroupVersion) {
// add the internal version to Scheme
if err := testgroup.AddToScheme(api.Scheme); err != nil {
// Programmer error, detect immediately
panic(err)
}
// add the enabled external versions to Scheme
for _, v := range externalVersions {
switch v {
case v1.SchemeGroupVersion:
if err := v1.AddToScheme(api.Scheme); err != nil {
// Programmer error, detect immediately
panic(err)
}
}
}
}

View file

@ -0,0 +1,46 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package testgroup
import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/runtime/schema"
)
var SchemeGroupVersion = schema.GroupVersion{Group: "testgroup.k8s.io", Version: runtime.APIVersionInternal}
var (
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
AddToScheme = SchemeBuilder.AddToScheme
)
// Adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&TestType{},
&TestTypeList{},
)
scheme.AddKnownTypes(SchemeGroupVersion,
&api.ListOptions{},
)
return nil
}
func (obj *TestType) GetObjectKind() schema.ObjectKind { return &obj.TypeMeta }
func (obj *TestTypeList) GetObjectKind() schema.ObjectKind { return &obj.TypeMeta }

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,41 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package testgroup
import (
"k8s.io/kubernetes/pkg/api"
metav1 "k8s.io/kubernetes/pkg/apis/meta/v1"
)
// +genclient=true
type TestType struct {
metav1.TypeMeta `json:",inline"`
api.ObjectMeta `json:"metadata,omitempty"`
Status TestTypeStatus `json:"status,omitempty"`
}
type TestTypeList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []TestType `json:"items"`
}
type TestTypeStatus struct {
Blah string
}

View file

@ -0,0 +1,32 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"register.go",
"types.generated.go",
"types.go",
],
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//pkg/api/v1:go_default_library",
"//pkg/apis/meta/v1:go_default_library",
"//pkg/runtime:go_default_library",
"//pkg/runtime/schema:go_default_library",
"//pkg/types:go_default_library",
"//pkg/watch/versioned:go_default_library",
"//vendor:github.com/ugorji/go/codec",
],
)

View file

@ -0,0 +1,19 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// +k8s:openapi-gen=true
// +groupName=testgroup.k8s.io
package v1

View file

@ -0,0 +1,52 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1
import (
"k8s.io/kubernetes/pkg/api/v1"
metav1 "k8s.io/kubernetes/pkg/apis/meta/v1"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/runtime/schema"
versionedwatch "k8s.io/kubernetes/pkg/watch/versioned"
)
var SchemeGroupVersion = schema.GroupVersion{Group: "testgroup.k8s.io", Version: "v1"}
var (
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
AddToScheme = SchemeBuilder.AddToScheme
)
// Adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&TestType{},
&TestTypeList{},
)
scheme.AddKnownTypes(SchemeGroupVersion,
&v1.ListOptions{},
&v1.DeleteOptions{},
&metav1.Status{},
&metav1.ExportOptions{},
)
versionedwatch.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}
func (obj *TestType) GetObjectKind() schema.ObjectKind { return &obj.TypeMeta }
func (obj *TestTypeList) GetObjectKind() schema.ObjectKind { return &obj.TypeMeta }

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,48 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1
import (
"k8s.io/kubernetes/pkg/api"
metav1 "k8s.io/kubernetes/pkg/apis/meta/v1"
)
// +genclient=true
type TestType struct {
metav1.TypeMeta `json:",inline"`
// ---
// the next tag removes the field from openapi spec. Adding unversioned objectMeta bring in a whole set of
// unversioned objects in the generate file that is not used anywhere other than this test type.
// +k8s:openapi-gen=false
// +optional
api.ObjectMeta `json:"metadata,omitempty"`
// +optional
Status TestTypeStatus `json:"status,omitempty"`
}
type TestTypeList struct {
metav1.TypeMeta `json:",inline"`
// +optional
metav1.ListMeta `json:"metadata,omitempty"`
Items []TestType `json:"items"`
}
type TestTypeStatus struct {
Blah string
}

View file

@ -0,0 +1,39 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_library(
name = "go_default_library",
srcs = [
"clientset.go",
"doc.go",
],
tags = ["automanaged"],
deps = [
"//cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset/typed/testgroup/internalversion:go_default_library",
"//pkg/client/restclient:go_default_library",
"//pkg/client/typed/discovery:go_default_library",
"//pkg/util/flowcontrol:go_default_library",
"//plugin/pkg/client/auth:go_default_library",
"//vendor:github.com/golang/glog",
],
)
go_test(
name = "go_default_test",
srcs = ["clientset_test.go"],
library = "go_default_library",
tags = ["automanaged"],
deps = [
"//pkg/client/restclient:go_default_library",
"//pkg/util/flowcontrol:go_default_library",
],
)

View file

@ -0,0 +1,91 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package test_internalclientset
import (
"github.com/golang/glog"
internalversiontestgroup "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset/typed/testgroup/internalversion"
restclient "k8s.io/kubernetes/pkg/client/restclient"
discovery "k8s.io/kubernetes/pkg/client/typed/discovery"
"k8s.io/kubernetes/pkg/util/flowcontrol"
_ "k8s.io/kubernetes/plugin/pkg/client/auth"
)
type Interface interface {
Discovery() discovery.DiscoveryInterface
Testgroup() internalversiontestgroup.TestgroupInterface
}
// Clientset contains the clients for groups. Each group has exactly one
// version included in a Clientset.
type Clientset struct {
*discovery.DiscoveryClient
*internalversiontestgroup.TestgroupClient
}
// Testgroup retrieves the TestgroupClient
func (c *Clientset) Testgroup() internalversiontestgroup.TestgroupInterface {
if c == nil {
return nil
}
return c.TestgroupClient
}
// Discovery retrieves the DiscoveryClient
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
return c.DiscoveryClient
}
// NewForConfig creates a new Clientset for the given config.
func NewForConfig(c *restclient.Config) (*Clientset, error) {
configShallowCopy := *c
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
}
var clientset Clientset
var err error
clientset.TestgroupClient, err = internalversiontestgroup.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
clientset.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)
if err != nil {
glog.Errorf("failed to create the DiscoveryClient: %v", err)
return nil, err
}
return &clientset, nil
}
// NewForConfigOrDie creates a new Clientset for the given config and
// panics if there is an error in the config.
func NewForConfigOrDie(c *restclient.Config) *Clientset {
var clientset Clientset
clientset.TestgroupClient = internalversiontestgroup.NewForConfigOrDie(c)
clientset.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)
return &clientset
}
// New creates a new Clientset for the given RESTClient.
func New(c restclient.Interface) *Clientset {
var clientset Clientset
clientset.TestgroupClient = internalversiontestgroup.New(c)
clientset.DiscoveryClient = discovery.NewDiscoveryClient(c)
return &clientset
}

View file

@ -0,0 +1,43 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package test_internalclientset
import (
"testing"
restclient "k8s.io/kubernetes/pkg/client/restclient"
"k8s.io/kubernetes/pkg/util/flowcontrol"
)
func ClientSetRateLimiterTest(t *testing.T) {
rateLimiter := flowcontrol.NewTokenBucketRateLimiter(1.0, 10)
config := restclient.Config{
RateLimiter: rateLimiter,
}
if err := restclient.SetKubernetesDefaults(&config); err != nil {
t.Errorf("setting defaults failed for %#v: %v", config, err)
}
clientSet, err := NewForConfig(&config)
if err != nil {
t.Errorf("creating clientset for config %v failed: %v", config, err)
}
testGroupThrottler := clientSet.Testgroup().RESTClient().GetRateLimiter()
if rateLimiter != testGroupThrottler {
t.Errorf("Clients in client set should use rateLimiter passed in config:\noriginal: %v\ntestGroup: %v", rateLimiter, testGroupThrottler)
}
}

View file

@ -0,0 +1,20 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// This package is generated by client-gen with arguments: --test=true
// This package has the automatically generated clientset.
package test_internalclientset

View file

@ -0,0 +1,32 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_library(
name = "go_default_library",
srcs = [
"clientset_generated.go",
"doc.go",
],
tags = ["automanaged"],
deps = [
"//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",
"//pkg/apimachinery/registered:go_default_library",
"//pkg/client/testing/core:go_default_library",
"//pkg/client/typed/discovery:go_default_library",
"//pkg/client/typed/discovery/fake:go_default_library",
"//pkg/runtime:go_default_library",
"//pkg/watch:go_default_library",
],
)

View file

@ -0,0 +1,68 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fake
import (
clientset "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset"
internalversiontestgroup "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset/typed/testgroup/internalversion"
fakeinternalversiontestgroup "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset/typed/testgroup/internalversion/fake"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apimachinery/registered"
"k8s.io/kubernetes/pkg/client/testing/core"
"k8s.io/kubernetes/pkg/client/typed/discovery"
fakediscovery "k8s.io/kubernetes/pkg/client/typed/discovery/fake"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/watch"
)
// 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 := core.NewObjectTracker(api.Scheme, api.Codecs.UniversalDecoder())
for _, obj := range objects {
if err := o.Add(obj); err != nil {
panic(err)
}
}
fakePtr := core.Fake{}
fakePtr.AddReactor("*", "*", core.ObjectReaction(o, registered.RESTMapper()))
fakePtr.AddWatchReactor("*", core.DefaultWatchReactor(watch.NewFake(), nil))
return &Clientset{fakePtr}
}
// Clientset implements clientset.Interface. Meant to be embedded into a
// struct to get a default implementation. This makes faking out just the method
// you want to test easier.
type Clientset struct {
core.Fake
}
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
return &fakediscovery.FakeDiscovery{Fake: &c.Fake}
}
var _ clientset.Interface = &Clientset{}
// Testgroup retrieves the TestgroupClient
func (c *Clientset) Testgroup() internalversiontestgroup.TestgroupInterface {
return &fakeinternalversiontestgroup.FakeTestgroup{Fake: &c.Fake}
}

View file

@ -0,0 +1,20 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// This package is generated by client-gen with arguments: --test=true
// This package has the automatically generated fake clientset.
package fake

View file

@ -0,0 +1,29 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"generated_expansion.go",
"testgroup_client.go",
"testtype.go",
],
tags = ["automanaged"],
deps = [
"//cmd/libs/go2idl/client-gen/test_apis/testgroup:go_default_library",
"//pkg/api:go_default_library",
"//pkg/apimachinery/registered:go_default_library",
"//pkg/client/restclient:go_default_library",
"//pkg/watch:go_default_library",
],
)

View file

@ -0,0 +1,20 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// This package is generated by client-gen with arguments: --test=true
// This package has the automatically generated typed clients.
package internalversion

View file

@ -0,0 +1,31 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"fake_testgroup_client.go",
"fake_testtype.go",
],
tags = ["automanaged"],
deps = [
"//cmd/libs/go2idl/client-gen/test_apis/testgroup:go_default_library",
"//cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset/typed/testgroup/internalversion:go_default_library",
"//pkg/api:go_default_library",
"//pkg/client/restclient:go_default_library",
"//pkg/client/testing/core:go_default_library",
"//pkg/labels:go_default_library",
"//pkg/runtime/schema:go_default_library",
"//pkg/watch:go_default_library",
],
)

View file

@ -0,0 +1,20 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// This package is generated by client-gen with arguments: --test=true
// Package fake has the automatically generated clients.
package fake

View file

@ -0,0 +1,38 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fake
import (
internalversion "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset/typed/testgroup/internalversion"
restclient "k8s.io/kubernetes/pkg/client/restclient"
core "k8s.io/kubernetes/pkg/client/testing/core"
)
type FakeTestgroup struct {
*core.Fake
}
func (c *FakeTestgroup) TestTypes(namespace string) internalversion.TestTypeInterface {
return &FakeTestTypes{c, namespace}
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *FakeTestgroup) RESTClient() restclient.Interface {
var ret *restclient.RESTClient
return ret
}

View file

@ -0,0 +1,127 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fake
import (
testgroup "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/test_apis/testgroup"
api "k8s.io/kubernetes/pkg/api"
core "k8s.io/kubernetes/pkg/client/testing/core"
labels "k8s.io/kubernetes/pkg/labels"
schema "k8s.io/kubernetes/pkg/runtime/schema"
watch "k8s.io/kubernetes/pkg/watch"
)
// FakeTestTypes implements TestTypeInterface
type FakeTestTypes struct {
Fake *FakeTestgroup
ns string
}
var testtypesResource = schema.GroupVersionResource{Group: "testgroup.k8s.io", Version: "", Resource: "testtypes"}
func (c *FakeTestTypes) Create(testType *testgroup.TestType) (result *testgroup.TestType, err error) {
obj, err := c.Fake.
Invokes(core.NewCreateAction(testtypesResource, c.ns, testType), &testgroup.TestType{})
if obj == nil {
return nil, err
}
return obj.(*testgroup.TestType), err
}
func (c *FakeTestTypes) Update(testType *testgroup.TestType) (result *testgroup.TestType, err error) {
obj, err := c.Fake.
Invokes(core.NewUpdateAction(testtypesResource, c.ns, testType), &testgroup.TestType{})
if obj == nil {
return nil, err
}
return obj.(*testgroup.TestType), err
}
func (c *FakeTestTypes) UpdateStatus(testType *testgroup.TestType) (*testgroup.TestType, error) {
obj, err := c.Fake.
Invokes(core.NewUpdateSubresourceAction(testtypesResource, "status", c.ns, testType), &testgroup.TestType{})
if obj == nil {
return nil, err
}
return obj.(*testgroup.TestType), err
}
func (c *FakeTestTypes) Delete(name string, options *api.DeleteOptions) error {
_, err := c.Fake.
Invokes(core.NewDeleteAction(testtypesResource, c.ns, name), &testgroup.TestType{})
return err
}
func (c *FakeTestTypes) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error {
action := core.NewDeleteCollectionAction(testtypesResource, c.ns, listOptions)
_, err := c.Fake.Invokes(action, &testgroup.TestTypeList{})
return err
}
func (c *FakeTestTypes) Get(name string) (result *testgroup.TestType, err error) {
obj, err := c.Fake.
Invokes(core.NewGetAction(testtypesResource, c.ns, name), &testgroup.TestType{})
if obj == nil {
return nil, err
}
return obj.(*testgroup.TestType), err
}
func (c *FakeTestTypes) List(opts api.ListOptions) (result *testgroup.TestTypeList, err error) {
obj, err := c.Fake.
Invokes(core.NewListAction(testtypesResource, c.ns, opts), &testgroup.TestTypeList{})
if obj == nil {
return nil, err
}
label, _, _ := core.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &testgroup.TestTypeList{}
for _, item := range obj.(*testgroup.TestTypeList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested testTypes.
func (c *FakeTestTypes) Watch(opts api.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(core.NewWatchAction(testtypesResource, c.ns, opts))
}
// Patch applies the patch and returns the patched testType.
func (c *FakeTestTypes) Patch(name string, pt api.PatchType, data []byte, subresources ...string) (result *testgroup.TestType, err error) {
obj, err := c.Fake.
Invokes(core.NewPatchSubresourceAction(testtypesResource, c.ns, name, data, subresources...), &testgroup.TestType{})
if obj == nil {
return nil, err
}
return obj.(*testgroup.TestType), err
}

View file

@ -0,0 +1,19 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package internalversion
type TestTypeExpansion interface{}

View file

@ -0,0 +1,99 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package internalversion
import (
api "k8s.io/kubernetes/pkg/api"
registered "k8s.io/kubernetes/pkg/apimachinery/registered"
restclient "k8s.io/kubernetes/pkg/client/restclient"
)
type TestgroupInterface interface {
RESTClient() restclient.Interface
TestTypesGetter
}
// TestgroupClient is used to interact with features provided by the k8s.io/kubernetes/pkg/apimachinery/registered.Group group.
type TestgroupClient struct {
restClient restclient.Interface
}
func (c *TestgroupClient) TestTypes(namespace string) TestTypeInterface {
return newTestTypes(c, namespace)
}
// NewForConfig creates a new TestgroupClient for the given config.
func NewForConfig(c *restclient.Config) (*TestgroupClient, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
client, err := restclient.RESTClientFor(&config)
if err != nil {
return nil, err
}
return &TestgroupClient{client}, nil
}
// NewForConfigOrDie creates a new TestgroupClient for the given config and
// panics if there is an error in the config.
func NewForConfigOrDie(c *restclient.Config) *TestgroupClient {
client, err := NewForConfig(c)
if err != nil {
panic(err)
}
return client
}
// New creates a new TestgroupClient for the given RESTClient.
func New(c restclient.Interface) *TestgroupClient {
return &TestgroupClient{c}
}
func setConfigDefaults(config *restclient.Config) error {
// if testgroup group is not registered, return an error
g, err := registered.Group("testgroup.k8s.io")
if err != nil {
return err
}
config.APIPath = "/apis"
if config.UserAgent == "" {
config.UserAgent = restclient.DefaultKubernetesUserAgent()
}
if config.GroupVersion == nil || config.GroupVersion.Group != g.GroupVersion.Group {
copyGroupVersion := g.GroupVersion
config.GroupVersion = &copyGroupVersion
}
config.NegotiatedSerializer = api.Codecs
if config.QPS == 0 {
config.QPS = 5
}
if config.Burst == 0 {
config.Burst = 10
}
return nil
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *TestgroupClient) RESTClient() restclient.Interface {
if c == nil {
return nil
}
return c.restClient
}

View file

@ -0,0 +1,166 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package internalversion
import (
testgroup "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/test_apis/testgroup"
api "k8s.io/kubernetes/pkg/api"
restclient "k8s.io/kubernetes/pkg/client/restclient"
watch "k8s.io/kubernetes/pkg/watch"
)
// TestTypesGetter has a method to return a TestTypeInterface.
// A group's client should implement this interface.
type TestTypesGetter interface {
TestTypes(namespace string) TestTypeInterface
}
// TestTypeInterface has methods to work with TestType resources.
type TestTypeInterface interface {
Create(*testgroup.TestType) (*testgroup.TestType, error)
Update(*testgroup.TestType) (*testgroup.TestType, error)
UpdateStatus(*testgroup.TestType) (*testgroup.TestType, error)
Delete(name string, options *api.DeleteOptions) error
DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error
Get(name string) (*testgroup.TestType, error)
List(opts api.ListOptions) (*testgroup.TestTypeList, error)
Watch(opts api.ListOptions) (watch.Interface, error)
Patch(name string, pt api.PatchType, data []byte, subresources ...string) (result *testgroup.TestType, err error)
TestTypeExpansion
}
// testTypes implements TestTypeInterface
type testTypes struct {
client restclient.Interface
ns string
}
// newTestTypes returns a TestTypes
func newTestTypes(c *TestgroupClient, namespace string) *testTypes {
return &testTypes{
client: c.RESTClient(),
ns: namespace,
}
}
// Create takes the representation of a testType and creates it. Returns the server's representation of the testType, and an error, if there is any.
func (c *testTypes) Create(testType *testgroup.TestType) (result *testgroup.TestType, err error) {
result = &testgroup.TestType{}
err = c.client.Post().
Namespace(c.ns).
Resource("testtypes").
Body(testType).
Do().
Into(result)
return
}
// Update takes the representation of a testType and updates it. Returns the server's representation of the testType, and an error, if there is any.
func (c *testTypes) Update(testType *testgroup.TestType) (result *testgroup.TestType, err error) {
result = &testgroup.TestType{}
err = c.client.Put().
Namespace(c.ns).
Resource("testtypes").
Name(testType.Name).
Body(testType).
Do().
Into(result)
return
}
func (c *testTypes) UpdateStatus(testType *testgroup.TestType) (result *testgroup.TestType, err error) {
result = &testgroup.TestType{}
err = c.client.Put().
Namespace(c.ns).
Resource("testtypes").
Name(testType.Name).
SubResource("status").
Body(testType).
Do().
Into(result)
return
}
// Delete takes name of the testType and deletes it. Returns an error if one occurs.
func (c *testTypes) Delete(name string, options *api.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("testtypes").
Name(name).
Body(options).
Do().
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *testTypes) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("testtypes").
VersionedParams(&listOptions, api.ParameterCodec).
Body(options).
Do().
Error()
}
// Get takes name of the testType, and returns the corresponding testType object, and an error if there is any.
func (c *testTypes) Get(name string) (result *testgroup.TestType, err error) {
result = &testgroup.TestType{}
err = c.client.Get().
Namespace(c.ns).
Resource("testtypes").
Name(name).
Do().
Into(result)
return
}
// List takes label and field selectors, and returns the list of TestTypes that match those selectors.
func (c *testTypes) List(opts api.ListOptions) (result *testgroup.TestTypeList, err error) {
result = &testgroup.TestTypeList{}
err = c.client.Get().
Namespace(c.ns).
Resource("testtypes").
VersionedParams(&opts, api.ParameterCodec).
Do().
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested testTypes.
func (c *testTypes) Watch(opts api.ListOptions) (watch.Interface, error) {
return c.client.Get().
Prefix("watch").
Namespace(c.ns).
Resource("testtypes").
VersionedParams(&opts, api.ParameterCodec).
Watch()
}
// Patch applies the patch and returns the patched testType.
func (c *testTypes) Patch(name string, pt api.PatchType, data []byte, subresources ...string) (result *testgroup.TestType, err error) {
result = &testgroup.TestType{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("testtypes").
SubResource(subresources...).
Name(name).
Body(data).
Do().
Into(result)
return
}

View file

@ -0,0 +1,29 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_library(
name = "go_default_library",
srcs = [
"helpers.go",
"types.go",
],
tags = ["automanaged"],
deps = ["//vendor:k8s.io/gengo/namer"],
)
go_test(
name = "go_default_test",
srcs = ["helpers_test.go"],
library = "go_default_library",
tags = ["automanaged"],
deps = [],
)

View file

@ -0,0 +1,108 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package types
import (
"fmt"
"regexp"
"sort"
"strings"
"k8s.io/gengo/namer"
)
// ToGroupVersion turns "group/version" string into a GroupVersion struct. It reports error
// if it cannot parse the string.
func ToGroupVersion(gv string) (GroupVersion, error) {
// this can be the internal version for the legacy kube types
// TODO once we've cleared the last uses as strings, this special case should be removed.
if (len(gv) == 0) || (gv == "/") {
return GroupVersion{}, nil
}
switch strings.Count(gv, "/") {
case 0:
return GroupVersion{"", Version(gv)}, nil
case 1:
i := strings.Index(gv, "/")
return GroupVersion{Group(gv[:i]), Version(gv[i+1:])}, nil
default:
return GroupVersion{}, fmt.Errorf("unexpected GroupVersion string: %v", gv)
}
}
type sortableSliceOfVersions []string
func (a sortableSliceOfVersions) Len() int { return len(a) }
func (a sortableSliceOfVersions) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a sortableSliceOfVersions) Less(i, j int) bool {
vi, vj := strings.TrimLeft(a[i], "v"), strings.TrimLeft(a[j], "v")
major := regexp.MustCompile("^[0-9]+")
viMajor, vjMajor := major.FindString(vi), major.FindString(vj)
viRemaining, vjRemaining := strings.TrimLeft(vi, viMajor), strings.TrimLeft(vj, vjMajor)
switch {
case len(viRemaining) == 0 && len(vjRemaining) == 0:
return viMajor < vjMajor
case len(viRemaining) == 0 && len(vjRemaining) != 0:
// stable version is greater than unstable version
return false
case len(viRemaining) != 0 && len(vjRemaining) == 0:
// stable version is greater than unstable version
return true
}
// neither are stable versions
if viMajor != vjMajor {
return viMajor < vjMajor
}
// assuming at most we have one alpha or one beta version, so if vi contains "alpha", it's the lesser one.
return strings.Contains(viRemaining, "alpha")
}
// Determine the default version among versions. If a user calls a group client
// without specifying the version (e.g., c.Core(), instead of c.CoreV1()), the
// default version will be returned.
func defaultVersion(versions []Version) Version {
var versionStrings []string
for _, version := range versions {
versionStrings = append(versionStrings, string(version))
}
sort.Sort(sortableSliceOfVersions(versionStrings))
return Version(versionStrings[len(versionStrings)-1])
}
// ToGroupVersionPackages is a helper function used by generators for groups.
func ToGroupVersionPackages(groups []GroupVersions) []GroupVersionPackage {
var groupVersionPackages []GroupVersionPackage
for _, group := range groups {
defaultVersion := defaultVersion(group.Versions)
for _, version := range group.Versions {
groupVersionPackages = append(groupVersionPackages, GroupVersionPackage{
Group: Group(namer.IC(group.Group.NonEmpty())),
Version: Version(namer.IC(version.String())),
GroupVersion: namer.IC(group.Group.NonEmpty()) + namer.IC(version.String()),
PackageName: strings.ToLower(version.NonEmpty() + group.Group.NonEmpty()),
IsDefaultVersion: version == defaultVersion && version != "",
})
}
}
return groupVersionPackages
}
// NormalizeGroupVersion calls normalizes the GroupVersion.
//func NormalizeGroupVersion(gv GroupVersion) GroupVersion {
// return GroupVersion{Group: gv.Group.NonEmpty(), Version: gv.Version, NonEmptyVersion: normalization.Version(gv.Version)}
//}

View file

@ -0,0 +1,32 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package types
import (
"reflect"
"sort"
"testing"
)
func TestVersionSort(t *testing.T) {
unsortedVersions := []string{"v4beta1", "v2beta1", "v2alpha1", "v3", "v1"}
expected := []string{"v2alpha1", "v2beta1", "v4beta1", "v1", "v3"}
sort.Sort(sortableSliceOfVersions(unsortedVersions))
if !reflect.DeepEqual(unsortedVersions, expected) {
t.Errorf("expected %#v\ngot %#v", expected, unsortedVersions)
}
}

View file

@ -0,0 +1,64 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package types
type Version string
func (v Version) String() string {
return string(v)
}
func (v Version) NonEmpty() string {
if v == "" {
return "internalVersion"
}
return v.String()
}
type Group string
func (g Group) String() string {
return string(g)
}
func (g Group) NonEmpty() string {
if g == "api" {
return "core"
}
return string(g)
}
type GroupVersion struct {
Group Group
Version Version
}
type GroupVersions struct {
Group Group
Versions []Version
}
// GroupVersionPackage contains group name, version name, and the package name client-gen will generate for this group version.
type GroupVersionPackage struct {
Group Group
Version Version
// If a user calls a group client without specifying the version (e.g.,
// c.Core(), instead of c.CoreV1()), the default version will be returned.
IsDefaultVersion bool
GroupVersion string
PackageName string
}

View file

@ -0,0 +1,23 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_binary(
name = "conversion-gen",
srcs = ["main.go"],
tags = ["automanaged"],
deps = [
"//cmd/libs/go2idl/conversion-gen/generators:go_default_library",
"//vendor:github.com/golang/glog",
"//vendor:github.com/spf13/pflag",
"//vendor:k8s.io/gengo/args",
],
)

View file

@ -0,0 +1,25 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_library(
name = "go_default_library",
srcs = ["conversion.go"],
tags = ["automanaged"],
deps = [
"//pkg/util/sets:go_default_library",
"//vendor:github.com/golang/glog",
"//vendor:k8s.io/gengo/args",
"//vendor:k8s.io/gengo/generator",
"//vendor:k8s.io/gengo/namer",
"//vendor:k8s.io/gengo/types",
],
)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,78 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// conversion-gen is a tool for auto-generating Conversion functions.
//
// Given a list of input directories, it will scan for "peer" packages and
// generate functions that efficiently convert between same-name types in each
// package. For any pair of types that has a
// `Convert_<pkg1>_<type>_To_<pkg2>_<Type()`
// function (and its reciprocal), it will simply call that. use standard value
// assignment whenever possible. The resulting file will be stored in the same
// directory as the processed source package.
//
// Generation is governed by comment tags in the source. Any package may
// request Conversion generation by including a comment in the file-comments of
// one file, of the form:
// // +k8s:conversion-gen=<import-path-of-peer-package>
//
// When generating for a package, individual types or fields of structs may opt
// out of Conversion generation by specifying a comment on the of the form:
// // +k8s:conversion-gen=false
package main
import (
"path/filepath"
"k8s.io/gengo/args"
"k8s.io/kubernetes/cmd/libs/go2idl/conversion-gen/generators"
"github.com/golang/glog"
"github.com/spf13/pflag"
)
func main() {
arguments := args.Default()
// Override defaults.
arguments.OutputFileBaseName = "conversion_generated"
arguments.GoHeaderFilePath = filepath.Join(args.DefaultSourceTree(), "k8s.io/kubernetes/hack/boilerplate/boilerplate.go.txt")
// Custom args.
customArgs := &generators.CustomArgs{
ExtraPeerDirs: []string{
"k8s.io/kubernetes/pkg/api",
"k8s.io/kubernetes/pkg/api/v1",
"k8s.io/kubernetes/pkg/apis/meta/v1",
"k8s.io/kubernetes/pkg/conversion",
"k8s.io/kubernetes/pkg/runtime",
},
SkipUnsafe: false,
}
pflag.CommandLine.StringSliceVar(&customArgs.ExtraPeerDirs, "extra-peer-dirs", customArgs.ExtraPeerDirs,
"Comma-separated list of import paths which are considered, after tag-specified peers, for conversions.")
arguments.CustomArgs = customArgs
// Run it.
if err := arguments.Execute(
generators.NameSystems(),
generators.DefaultNameSystem(),
generators.Packages,
); err != nil {
glog.Fatalf("Error: %v", err)
}
glog.V(2).Info("Completed successfully.")
}

View file

@ -0,0 +1,23 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_binary(
name = "deepcopy-gen",
srcs = ["main.go"],
tags = ["automanaged"],
deps = [
"//vendor:github.com/golang/glog",
"//vendor:github.com/spf13/pflag",
"//vendor:k8s.io/gengo/args",
"//vendor:k8s.io/gengo/examples/deepcopy-gen/generators",
],
)

View file

@ -0,0 +1,82 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// deepcopy-gen is a tool for auto-generating DeepCopy functions.
//
// Given a list of input directories, it will generate functions that
// efficiently perform a full deep-copy of each type. For any type that
// offers a `.DeepCopy()` method, it will simply call that. Otherwise it will
// use standard value assignment whenever possible. If that is not possible it
// will try to call its own generated copy function for the type, if the type is
// within the allowed root packages. Failing that, it will fall back on
// `conversion.Cloner.DeepCopy(val)` to make the copy. The resulting file will
// be stored in the same directory as the processed source package.
//
// Generation is governed by comment tags in the source. Any package may
// request DeepCopy generation by including a comment in the file-comments of
// one file, of the form:
// // +k8s:deepcopy-gen=package
//
// Packages can request that the generated DeepCopy functions be registered
// with an `init()` function call to `Scheme.AddGeneratedDeepCopyFuncs()` by
// changing the tag to:
// // +k8s:deepcopy-gen=package,register
//
// DeepCopy functions can be generated for individual types, rather than the
// entire package by specifying a comment on the type definion of the form:
// // +k8s:deepcopy-gen=true
//
// When generating for a whole package, individual types may opt out of
// DeepCopy generation by specifying a comment on the of the form:
// // +k8s:deepcopy-gen=false
//
// Note that registration is a whole-package option, and is not available for
// individual types.
package main
import (
"path/filepath"
"k8s.io/gengo/args"
"k8s.io/gengo/examples/deepcopy-gen/generators"
"github.com/golang/glog"
"github.com/spf13/pflag"
)
func main() {
arguments := args.Default()
// Override defaults.
arguments.OutputFileBaseName = "deepcopy_generated"
arguments.GoHeaderFilePath = filepath.Join(args.DefaultSourceTree(), "k8s.io/kubernetes/hack/boilerplate/boilerplate.go.txt")
// Custom args.
customArgs := &generators.CustomArgs{}
pflag.CommandLine.StringSliceVar(&customArgs.BoundingDirs, "bounding-dirs", customArgs.BoundingDirs,
"Comma-separated list of import paths which bound the types for which deep-copies will be generated.")
arguments.CustomArgs = customArgs
// Run it.
if err := arguments.Execute(
generators.NameSystems(),
generators.DefaultNameSystem(),
generators.Packages,
); err != nil {
glog.Fatalf("Error: %v", err)
}
glog.V(2).Info("Completed successfully.")
}

View file

@ -0,0 +1,23 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_binary(
name = "defaulter-gen",
srcs = ["main.go"],
tags = ["automanaged"],
deps = [
"//vendor:github.com/golang/glog",
"//vendor:github.com/spf13/pflag",
"//vendor:k8s.io/gengo/args",
"//vendor:k8s.io/gengo/examples/defaulter-gen/generators",
],
)

View file

@ -0,0 +1,78 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// defaulter-gen is a tool for auto-generating Defaulter functions.
//
// Given a list of input directories, it will scan for top level types
// and generate efficient defaulters for an entire object from the sum
// of the SetDefault_* methods contained in the object tree.
//
// Generation is governed by comment tags in the source. Any package may
// request defaulter generation by including one or more comment tags at
// the package comment level:
//
// // +k8s:defaulter-gen=<field-name-to-flag>
//
// which will create defaulters for any type that contains the provided
// field name (if the type has defaulters). Any type may request explicit
// defaulting by providing the comment tag:
//
// // +k8s:defaulter-gen=true|false
//
// An existing defaulter method (`SetDefaults_TYPE`) can provide the
// comment tag:
//
// // +k8s:defaulter-gen=covers
//
// to indicate that the defaulter does not or should not call any nested
// defaulters.
package main
import (
"path/filepath"
"k8s.io/gengo/args"
"k8s.io/gengo/examples/defaulter-gen/generators"
"github.com/golang/glog"
"github.com/spf13/pflag"
)
func main() {
arguments := args.Default()
// Override defaults.
arguments.OutputFileBaseName = "zz_generated.defaults"
arguments.GoHeaderFilePath = filepath.Join(args.DefaultSourceTree(), "k8s.io/kubernetes/hack/boilerplate/boilerplate.go.txt")
// Custom args.
customArgs := &generators.CustomArgs{
ExtraPeerDirs: []string{},
}
pflag.CommandLine.StringSliceVar(&customArgs.ExtraPeerDirs, "extra-peer-dirs", customArgs.ExtraPeerDirs,
"Comma-separated list of import paths which are considered, after tag-specified peers, for conversions.")
arguments.CustomArgs = customArgs
// Run it.
if err := arguments.Execute(
generators.NameSystems(),
generators.DefaultNameSystem(),
generators.Packages,
); err != nil {
glog.Fatalf("Error: %v", err)
}
glog.V(2).Info("Completed successfully.")
}

View file

@ -0,0 +1 @@
go-to-protobuf

View file

@ -0,0 +1,21 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_binary(
name = "go-to-protobuf",
srcs = ["main.go"],
tags = ["automanaged"],
deps = [
"//cmd/libs/go2idl/go-to-protobuf/protobuf:go_default_library",
"//vendor:github.com/spf13/pflag",
],
)

View file

@ -0,0 +1,2 @@
assignees:
- smarterclayton

View file

@ -0,0 +1,36 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// go-to-protobuf generates a Protobuf IDL from a Go struct, respecting any
// existing IDL tags on the Go struct.
package main
import (
"k8s.io/kubernetes/cmd/libs/go2idl/go-to-protobuf/protobuf"
flag "github.com/spf13/pflag"
)
var g = protobuf.New()
func init() {
g.BindFlags(flag.CommandLine)
}
func main() {
flag.Parse()
protobuf.Run(g)
}

View file

@ -0,0 +1,43 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_library(
name = "go_default_library",
srcs = [
"cmd.go",
"generator.go",
"import_tracker.go",
"namer.go",
"package.go",
"parser.go",
"tags.go",
],
tags = ["automanaged"],
deps = [
"//third_party/forked/golang/reflect:go_default_library",
"//vendor:github.com/golang/glog",
"//vendor:github.com/spf13/pflag",
"//vendor:k8s.io/gengo/args",
"//vendor:k8s.io/gengo/generator",
"//vendor:k8s.io/gengo/namer",
"//vendor:k8s.io/gengo/parser",
"//vendor:k8s.io/gengo/types",
],
)
go_test(
name = "go_default_test",
srcs = ["namer_test.go"],
library = "go_default_library",
tags = ["automanaged"],
deps = [],
)

View file

@ -0,0 +1,308 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// go-to-protobuf generates a Protobuf IDL from a Go struct, respecting any
// existing IDL tags on the Go struct.
package protobuf
import (
"bytes"
"fmt"
"log"
"os/exec"
"path/filepath"
"strings"
"k8s.io/gengo/args"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/parser"
"k8s.io/gengo/types"
flag "github.com/spf13/pflag"
)
type Generator struct {
Common args.GeneratorArgs
Packages string
OutputBase string
ProtoImport []string
Conditional string
Clean bool
OnlyIDL bool
KeepGogoproto bool
SkipGeneratedRewrite bool
DropEmbeddedFields string
}
func New() *Generator {
sourceTree := args.DefaultSourceTree()
common := args.GeneratorArgs{
OutputBase: sourceTree,
GoHeaderFilePath: filepath.Join(sourceTree, "k8s.io/kubernetes/hack/boilerplate/boilerplate.go.txt"),
}
defaultProtoImport := filepath.Join(sourceTree, "k8s.io", "kubernetes", "vendor", "github.com", "gogo", "protobuf", "protobuf")
return &Generator{
Common: common,
OutputBase: sourceTree,
ProtoImport: []string{defaultProtoImport},
Packages: strings.Join([]string{
`+k8s.io/kubernetes/pkg/util/intstr`,
`+k8s.io/kubernetes/pkg/api/resource`,
`+k8s.io/kubernetes/pkg/runtime/schema`,
`+k8s.io/kubernetes/pkg/runtime`,
`+k8s.io/kubernetes/pkg/watch/versioned`,
`k8s.io/kubernetes/pkg/apis/meta/v1`,
`k8s.io/kubernetes/pkg/api/v1`,
`k8s.io/kubernetes/pkg/apis/policy/v1beta1`,
`k8s.io/kubernetes/pkg/apis/extensions/v1beta1`,
`k8s.io/kubernetes/pkg/apis/autoscaling/v1`,
`k8s.io/kubernetes/pkg/apis/authorization/v1beta1`,
`k8s.io/kubernetes/pkg/apis/batch/v1`,
`k8s.io/kubernetes/pkg/apis/batch/v2alpha1`,
`k8s.io/kubernetes/pkg/apis/apps/v1beta1`,
`k8s.io/kubernetes/pkg/apis/authentication/v1beta1`,
`k8s.io/kubernetes/pkg/apis/rbac/v1alpha1`,
`k8s.io/kubernetes/federation/apis/federation/v1beta1`,
`k8s.io/kubernetes/pkg/apis/certificates/v1alpha1`,
`k8s.io/kubernetes/pkg/apis/imagepolicy/v1alpha1`,
`k8s.io/kubernetes/pkg/apis/storage/v1beta1`,
}, ","),
DropEmbeddedFields: "k8s.io/kubernetes/pkg/apis/meta/v1.TypeMeta",
}
}
func (g *Generator) BindFlags(flag *flag.FlagSet) {
flag.StringVarP(&g.Common.GoHeaderFilePath, "go-header-file", "h", g.Common.GoHeaderFilePath, "File containing boilerplate header text. The string YEAR will be replaced with the current 4-digit year.")
flag.BoolVar(&g.Common.VerifyOnly, "verify-only", g.Common.VerifyOnly, "If true, only verify existing output, do not write anything.")
flag.StringVarP(&g.Packages, "packages", "p", g.Packages, "comma-separated list of directories to get input types from. Directories prefixed with '-' are not generated, directories prefixed with '+' only create types with explicit IDL instructions.")
flag.StringVarP(&g.OutputBase, "output-base", "o", g.OutputBase, "Output base; defaults to $GOPATH/src/")
flag.StringSliceVar(&g.ProtoImport, "proto-import", g.ProtoImport, "The search path for the core protobuf .protos, required, defaults to GODEPS on path.")
flag.StringVar(&g.Conditional, "conditional", g.Conditional, "An optional Golang build tag condition to add to the generated Go code")
flag.BoolVar(&g.Clean, "clean", g.Clean, "If true, remove all generated files for the specified Packages.")
flag.BoolVar(&g.OnlyIDL, "only-idl", g.OnlyIDL, "If true, only generate the IDL for each package.")
flag.BoolVar(&g.KeepGogoproto, "keep-gogoproto", g.KeepGogoproto, "If true, the generated IDL will contain gogoprotobuf extensions which are normally removed")
flag.BoolVar(&g.SkipGeneratedRewrite, "skip-generated-rewrite", g.SkipGeneratedRewrite, "If true, skip fixing up the generated.pb.go file (debugging only).")
flag.StringVar(&g.DropEmbeddedFields, "drop-embedded-fields", g.DropEmbeddedFields, "Comma-delimited list of embedded Go types to omit from generated protobufs")
}
func Run(g *Generator) {
if g.Common.VerifyOnly {
g.OnlyIDL = true
g.Clean = false
}
b := parser.New()
b.AddBuildTags("proto")
omitTypes := map[types.Name]struct{}{}
for _, t := range strings.Split(g.DropEmbeddedFields, ",") {
name := types.Name{}
if i := strings.LastIndex(t, "."); i != -1 {
name.Package, name.Name = t[:i], t[i+1:]
} else {
name.Name = t
}
if len(name.Name) == 0 {
log.Fatalf("--drop-embedded-types requires names in the form of [GOPACKAGE.]TYPENAME: %v", t)
}
omitTypes[name] = struct{}{}
}
boilerplate, err := g.Common.LoadGoBoilerplate()
if err != nil {
log.Fatalf("Failed loading boilerplate: %v", err)
}
protobufNames := NewProtobufNamer()
outputPackages := generator.Packages{}
for _, d := range strings.Split(g.Packages, ",") {
generateAllTypes, outputPackage := true, true
switch {
case strings.HasPrefix(d, "+"):
d = d[1:]
generateAllTypes = false
case strings.HasPrefix(d, "-"):
d = d[1:]
outputPackage = false
}
name := protoSafePackage(d)
parts := strings.SplitN(d, "=", 2)
if len(parts) > 1 {
d = parts[0]
name = parts[1]
}
p := newProtobufPackage(d, name, generateAllTypes, omitTypes)
header := append([]byte{}, boilerplate...)
header = append(header, p.HeaderText...)
p.HeaderText = header
protobufNames.Add(p)
if outputPackage {
outputPackages = append(outputPackages, p)
}
}
if !g.Common.VerifyOnly {
for _, p := range outputPackages {
if err := p.(*protobufPackage).Clean(g.OutputBase); err != nil {
log.Fatalf("Unable to clean package %s: %v", p.Name(), err)
}
}
}
if g.Clean {
return
}
for _, p := range protobufNames.List() {
if err := b.AddDir(p.Path()); err != nil {
log.Fatalf("Unable to add directory %q: %v", p.Path(), err)
}
}
c, err := generator.NewContext(
b,
namer.NameSystems{
"public": namer.NewPublicNamer(3),
"proto": protobufNames,
},
"public",
)
if err != nil {
log.Fatalf("Failed making a context: %v", err)
}
c.Verify = g.Common.VerifyOnly
c.FileTypes["protoidl"] = NewProtoFile()
if err := protobufNames.AssignTypesToPackages(c); err != nil {
log.Fatalf("Failed to identify Common types: %v", err)
}
if err := c.ExecutePackages(g.OutputBase, outputPackages); err != nil {
log.Fatalf("Failed executing generator: %v", err)
}
if g.OnlyIDL {
return
}
if _, err := exec.LookPath("protoc"); err != nil {
log.Fatalf("Unable to find 'protoc': %v", err)
}
searchArgs := []string{"-I", ".", "-I", g.OutputBase}
if len(g.ProtoImport) != 0 {
for _, s := range g.ProtoImport {
searchArgs = append(searchArgs, "-I", s)
}
}
args := append(searchArgs, fmt.Sprintf("--gogo_out=%s", g.OutputBase))
buf := &bytes.Buffer{}
if len(g.Conditional) > 0 {
fmt.Fprintf(buf, "// +build %s\n\n", g.Conditional)
}
buf.Write(boilerplate)
for _, outputPackage := range outputPackages {
p := outputPackage.(*protobufPackage)
path := filepath.Join(g.OutputBase, p.ImportPath())
outputPath := filepath.Join(g.OutputBase, p.OutputPath())
// generate the gogoprotobuf protoc
cmd := exec.Command("protoc", append(args, path)...)
out, err := cmd.CombinedOutput()
if len(out) > 0 {
log.Printf(string(out))
}
if err != nil {
log.Println(strings.Join(cmd.Args, " "))
log.Fatalf("Unable to generate protoc on %s: %v", p.PackageName, err)
}
if g.SkipGeneratedRewrite {
continue
}
// alter the generated protobuf file to remove the generated types (but leave the serializers) and rewrite the
// package statement to match the desired package name
if err := RewriteGeneratedGogoProtobufFile(outputPath, p.ExtractGeneratedType, p.OptionalTypeName, buf.Bytes()); err != nil {
log.Fatalf("Unable to rewrite generated %s: %v", outputPath, err)
}
// sort imports
cmd = exec.Command("goimports", "-w", outputPath)
out, err = cmd.CombinedOutput()
if len(out) > 0 {
log.Printf(string(out))
}
if err != nil {
log.Println(strings.Join(cmd.Args, " "))
log.Fatalf("Unable to rewrite imports for %s: %v", p.PackageName, err)
}
// format and simplify the generated file
cmd = exec.Command("gofmt", "-s", "-w", outputPath)
out, err = cmd.CombinedOutput()
if len(out) > 0 {
log.Printf(string(out))
}
if err != nil {
log.Println(strings.Join(cmd.Args, " "))
log.Fatalf("Unable to apply gofmt for %s: %v", p.PackageName, err)
}
}
if g.SkipGeneratedRewrite {
return
}
if !g.KeepGogoproto {
// generate, but do so without gogoprotobuf extensions
for _, outputPackage := range outputPackages {
p := outputPackage.(*protobufPackage)
p.OmitGogo = true
}
if err := c.ExecutePackages(g.OutputBase, outputPackages); err != nil {
log.Fatalf("Failed executing generator: %v", err)
}
}
for _, outputPackage := range outputPackages {
p := outputPackage.(*protobufPackage)
if len(p.StructTags) == 0 {
continue
}
pattern := filepath.Join(g.OutputBase, p.PackagePath, "*.go")
files, err := filepath.Glob(pattern)
if err != nil {
log.Fatalf("Can't glob pattern %q: %v", pattern, err)
}
for _, s := range files {
if strings.HasSuffix(s, "_test.go") {
continue
}
if err := RewriteTypesWithProtobufStructTags(s, p.StructTags); err != nil {
log.Fatalf("Unable to rewrite with struct tags %s: %v", s, err)
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,50 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package protobuf
import (
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
)
type ImportTracker struct {
namer.DefaultImportTracker
}
func NewImportTracker(local types.Name, typesToAdd ...*types.Type) *ImportTracker {
tracker := namer.NewDefaultImportTracker(local)
tracker.IsInvalidType = func(t *types.Type) bool { return t.Kind != types.Protobuf }
tracker.LocalName = func(name types.Name) string { return name.Package }
tracker.PrintImport = func(path, name string) string { return path }
tracker.AddTypes(typesToAdd...)
return &ImportTracker{
DefaultImportTracker: tracker,
}
}
// AddNullable ensures that support for the nullable Gogo-protobuf extension is added.
func (tracker *ImportTracker) AddNullable() {
tracker.AddType(&types.Type{
Kind: types.Protobuf,
Name: types.Name{
Name: "nullable",
Package: "gogoproto",
Path: "github.com/gogo/protobuf/gogoproto/gogo.proto",
},
})
}

View file

@ -0,0 +1,186 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package protobuf
import (
"fmt"
"reflect"
"strings"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
)
type localNamer struct {
localPackage types.Name
}
func (n localNamer) Name(t *types.Type) string {
if t.Key != nil && t.Elem != nil {
return fmt.Sprintf("map<%s, %s>", n.Name(t.Key), n.Name(t.Elem))
}
if len(n.localPackage.Package) != 0 && n.localPackage.Package == t.Name.Package {
return t.Name.Name
}
return t.Name.String()
}
type protobufNamer struct {
packages []*protobufPackage
packagesByPath map[string]*protobufPackage
}
func NewProtobufNamer() *protobufNamer {
return &protobufNamer{
packagesByPath: make(map[string]*protobufPackage),
}
}
func (n *protobufNamer) Name(t *types.Type) string {
if t.Kind == types.Map {
return fmt.Sprintf("map<%s, %s>", n.Name(t.Key), n.Name(t.Elem))
}
return t.Name.String()
}
func (n *protobufNamer) List() []generator.Package {
packages := make([]generator.Package, 0, len(n.packages))
for i := range n.packages {
packages = append(packages, n.packages[i])
}
return packages
}
func (n *protobufNamer) Add(p *protobufPackage) {
if _, ok := n.packagesByPath[p.PackagePath]; !ok {
n.packagesByPath[p.PackagePath] = p
n.packages = append(n.packages, p)
}
}
func (n *protobufNamer) GoNameToProtoName(name types.Name) types.Name {
if p, ok := n.packagesByPath[name.Package]; ok {
return types.Name{
Name: name.Name,
Package: p.PackageName,
Path: p.ImportPath(),
}
}
for _, p := range n.packages {
if _, ok := p.FilterTypes[name]; ok {
return types.Name{
Name: name.Name,
Package: p.PackageName,
Path: p.ImportPath(),
}
}
}
return types.Name{Name: name.Name}
}
func protoSafePackage(name string) string {
pkg := strings.Replace(name, "/", ".", -1)
return strings.Replace(pkg, "-", "_", -1)
}
type typeNameSet map[types.Name]*protobufPackage
// assignGoTypeToProtoPackage looks for Go and Protobuf types that are referenced by a type in
// a package. It will not recurse into protobuf types.
func assignGoTypeToProtoPackage(p *protobufPackage, t *types.Type, local, global typeNameSet, optional map[types.Name]struct{}) {
newT, isProto := isFundamentalProtoType(t)
if isProto {
t = newT
}
if otherP, ok := global[t.Name]; ok {
if _, ok := local[t.Name]; !ok {
p.Imports.AddType(&types.Type{
Kind: types.Protobuf,
Name: otherP.ProtoTypeName(),
})
}
return
}
global[t.Name] = p
if _, ok := local[t.Name]; ok {
return
}
// don't recurse into existing proto types
if isProto {
p.Imports.AddType(t)
return
}
local[t.Name] = p
for _, m := range t.Members {
if namer.IsPrivateGoName(m.Name) {
continue
}
field := &protoField{}
tag := reflect.StructTag(m.Tags).Get("protobuf")
if tag == "-" {
continue
}
if err := protobufTagToField(tag, field, m, t, p.ProtoTypeName()); err == nil && field.Type != nil {
assignGoTypeToProtoPackage(p, field.Type, local, global, optional)
continue
}
assignGoTypeToProtoPackage(p, m.Type, local, global, optional)
}
// TODO: should methods be walked?
if t.Elem != nil {
assignGoTypeToProtoPackage(p, t.Elem, local, global, optional)
}
if t.Key != nil {
assignGoTypeToProtoPackage(p, t.Key, local, global, optional)
}
if t.Underlying != nil {
if t.Kind == types.Alias && isOptionalAlias(t) {
optional[t.Name] = struct{}{}
}
assignGoTypeToProtoPackage(p, t.Underlying, local, global, optional)
}
}
func (n *protobufNamer) AssignTypesToPackages(c *generator.Context) error {
global := make(typeNameSet)
for _, p := range n.packages {
local := make(typeNameSet)
optional := make(map[types.Name]struct{})
p.Imports = NewImportTracker(p.ProtoTypeName())
for _, t := range c.Order {
if t.Name.Package != p.PackagePath {
continue
}
assignGoTypeToProtoPackage(p, t, local, global, optional)
}
p.FilterTypes = make(map[types.Name]struct{})
p.LocalNames = make(map[string]struct{})
p.OptionalTypeNames = make(map[string]struct{})
for k, v := range local {
if v == p {
p.FilterTypes[k] = struct{}{}
p.LocalNames[k.Name] = struct{}{}
if _, ok := optional[k]; ok {
p.OptionalTypeNames[k.Name] = struct{}{}
}
}
}
}
return nil
}

View file

@ -0,0 +1,50 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package protobuf
import "testing"
func TestProtoSafePackage(t *testing.T) {
tests := []struct {
pkg string
expected string
}{
{
pkg: "foo",
expected: "foo",
},
{
pkg: "foo/bar",
expected: "foo.bar",
},
{
pkg: "foo/bar/baz",
expected: "foo.bar.baz",
},
{
pkg: "foo/bar-baz/x/y-z/q",
expected: "foo.bar_baz.x.y_z.q",
},
}
for _, test := range tests {
actual := protoSafePackage(test.pkg)
if e, a := test.expected, actual; e != a {
t.Errorf("%s: expected %s, got %s", test.pkg, e, a)
}
}
}

View file

@ -0,0 +1,211 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package protobuf
import (
"fmt"
"go/ast"
"log"
"os"
"path/filepath"
"reflect"
"strings"
"k8s.io/gengo/generator"
"k8s.io/gengo/types"
)
func newProtobufPackage(packagePath, packageName string, generateAll bool, omitFieldTypes map[types.Name]struct{}) *protobufPackage {
pkg := &protobufPackage{
DefaultPackage: generator.DefaultPackage{
// The protobuf package name (foo.bar.baz)
PackageName: packageName,
// A path segment relative to the GOPATH root (foo/bar/baz)
PackagePath: packagePath,
HeaderText: []byte(
`
// This file was autogenerated by go-to-protobuf. Do not edit it manually!
`),
PackageDocumentation: []byte(fmt.Sprintf(
`// Package %s is an autogenerated protobuf IDL.
`, packageName)),
},
GenerateAll: generateAll,
OmitFieldTypes: omitFieldTypes,
}
pkg.FilterFunc = pkg.filterFunc
pkg.GeneratorFunc = pkg.generatorFunc
return pkg
}
// protobufPackage contains the protobuf implementation of Package.
type protobufPackage struct {
generator.DefaultPackage
// If true, generate protobuf serializations for all public types.
// If false, only generate protobuf serializations for structs that
// request serialization.
GenerateAll bool
// A list of types to filter to; if not specified all types will be included.
FilterTypes map[types.Name]struct{}
// If true, omit any gogoprotobuf extensions not defined as types.
OmitGogo bool
// A list of field types that will be excluded from the output struct
OmitFieldTypes map[types.Name]struct{}
// A list of names that this package exports
LocalNames map[string]struct{}
// A list of type names in this package that will need marshaller rewriting
// to remove synthetic protobuf fields.
OptionalTypeNames map[string]struct{}
// A list of struct tags to generate onto named struct fields
StructTags map[string]map[string]string
// An import tracker for this package
Imports *ImportTracker
}
func (p *protobufPackage) Clean(outputBase string) error {
for _, s := range []string{p.ImportPath(), p.OutputPath()} {
if err := os.Remove(filepath.Join(outputBase, s)); err != nil && !os.IsNotExist(err) {
return err
}
}
return nil
}
func (p *protobufPackage) ProtoTypeName() types.Name {
return types.Name{
Name: p.Path(), // the go path "foo/bar/baz"
Package: p.Name(), // the protobuf package "foo.bar.baz"
Path: p.ImportPath(), // the path of the import to get the proto
}
}
func (p *protobufPackage) filterFunc(c *generator.Context, t *types.Type) bool {
switch t.Kind {
case types.Func, types.Chan:
return false
case types.Struct:
if t.Name.Name == "struct{}" {
return false
}
case types.Builtin:
return false
case types.Alias:
if !isOptionalAlias(t) {
return false
}
case types.Slice, types.Array, types.Map:
return false
case types.Pointer:
return false
}
if _, ok := isFundamentalProtoType(t); ok {
return false
}
_, ok := p.FilterTypes[t.Name]
return ok
}
func (p *protobufPackage) HasGoType(name string) bool {
_, ok := p.LocalNames[name]
return ok
}
func (p *protobufPackage) OptionalTypeName(name string) bool {
_, ok := p.OptionalTypeNames[name]
return ok
}
func (p *protobufPackage) ExtractGeneratedType(t *ast.TypeSpec) bool {
if !p.HasGoType(t.Name.Name) {
return false
}
switch s := t.Type.(type) {
case *ast.StructType:
for i, f := range s.Fields.List {
if len(f.Tag.Value) == 0 {
continue
}
tag := strings.Trim(f.Tag.Value, "`")
protobufTag := reflect.StructTag(tag).Get("protobuf")
if len(protobufTag) == 0 {
continue
}
if len(f.Names) > 1 {
log.Printf("WARNING: struct %s field %d %s: defined multiple names but single protobuf tag", t.Name.Name, i, f.Names[0].Name)
// TODO hard error?
}
if p.StructTags == nil {
p.StructTags = make(map[string]map[string]string)
}
m := p.StructTags[t.Name.Name]
if m == nil {
m = make(map[string]string)
p.StructTags[t.Name.Name] = m
}
m[f.Names[0].Name] = tag
}
default:
log.Printf("WARNING: unexpected Go AST type definition: %#v", t)
}
return true
}
func (p *protobufPackage) generatorFunc(c *generator.Context) []generator.Generator {
generators := []generator.Generator{}
p.Imports.AddNullable()
generators = append(generators, &genProtoIDL{
DefaultGen: generator.DefaultGen{
OptionalName: "generated",
},
localPackage: types.Name{Package: p.PackageName, Path: p.PackagePath},
localGoPackage: types.Name{Package: p.PackagePath, Name: p.GoPackageName()},
imports: p.Imports,
generateAll: p.GenerateAll,
omitGogo: p.OmitGogo,
omitFieldTypes: p.OmitFieldTypes,
})
return generators
}
func (p *protobufPackage) GoPackageName() string {
return filepath.Base(p.PackagePath)
}
func (p *protobufPackage) ImportPath() string {
return filepath.Join(p.PackagePath, "generated.proto")
}
func (p *protobufPackage) OutputPath() string {
return filepath.Join(p.PackagePath, "generated.pb.go")
}
var (
_ = generator.Package(&protobufPackage{})
)

View file

@ -0,0 +1,452 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package protobuf
import (
"bytes"
"errors"
"fmt"
"go/ast"
"go/format"
"go/parser"
"go/printer"
"go/token"
"io/ioutil"
"os"
"reflect"
"strings"
customreflect "k8s.io/kubernetes/third_party/forked/golang/reflect"
)
func rewriteFile(name string, header []byte, rewriteFn func(*token.FileSet, *ast.File) error) error {
fset := token.NewFileSet()
src, err := ioutil.ReadFile(name)
if err != nil {
return err
}
file, err := parser.ParseFile(fset, name, src, parser.DeclarationErrors|parser.ParseComments)
if err != nil {
return err
}
if err := rewriteFn(fset, file); err != nil {
return err
}
b := &bytes.Buffer{}
b.Write(header)
if err := printer.Fprint(b, fset, file); err != nil {
return err
}
body, err := format.Source(b.Bytes())
if err != nil {
return err
}
f, err := os.OpenFile(name, os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
return err
}
defer f.Close()
if _, err := f.Write(body); err != nil {
return err
}
return f.Close()
}
// ExtractFunc extracts information from the provided TypeSpec and returns true if the type should be
// removed from the destination file.
type ExtractFunc func(*ast.TypeSpec) bool
// OptionalFunc returns true if the provided local name is a type that has protobuf.nullable=true
// and should have its marshal functions adjusted to remove the 'Items' accessor.
type OptionalFunc func(name string) bool
func RewriteGeneratedGogoProtobufFile(name string, extractFn ExtractFunc, optionalFn OptionalFunc, header []byte) error {
return rewriteFile(name, header, func(fset *token.FileSet, file *ast.File) error {
cmap := ast.NewCommentMap(fset, file, file.Comments)
// transform methods that point to optional maps or slices
for _, d := range file.Decls {
rewriteOptionalMethods(d, optionalFn)
}
// remove types that are already declared
decls := []ast.Decl{}
for _, d := range file.Decls {
if dropExistingTypeDeclarations(d, extractFn) {
continue
}
if dropEmptyImportDeclarations(d) {
continue
}
decls = append(decls, d)
}
file.Decls = decls
// remove unmapped comments
file.Comments = cmap.Filter(file).Comments()
return nil
})
}
// rewriteOptionalMethods makes specific mutations to marshaller methods that belong to types identified
// as being "optional" (they may be nil on the wire). This allows protobuf to serialize a map or slice and
// properly discriminate between empty and nil (which is not possible in protobuf).
// TODO: move into upstream gogo-protobuf once https://github.com/gogo/protobuf/issues/181
// has agreement
func rewriteOptionalMethods(decl ast.Decl, isOptional OptionalFunc) {
switch t := decl.(type) {
case *ast.FuncDecl:
ident, ptr, ok := receiver(t)
if !ok {
return
}
// correct initialization of the form `m.Field = &OptionalType{}` to
// `m.Field = OptionalType{}`
if t.Name.Name == "Unmarshal" {
ast.Walk(optionalAssignmentVisitor{fn: isOptional}, t.Body)
}
if !isOptional(ident.Name) {
return
}
switch t.Name.Name {
case "Unmarshal":
ast.Walk(&optionalItemsVisitor{}, t.Body)
case "MarshalTo", "Size", "String":
ast.Walk(&optionalItemsVisitor{}, t.Body)
fallthrough
case "Marshal":
// if the method has a pointer receiver, set it back to a normal receiver
if ptr {
t.Recv.List[0].Type = ident
}
}
}
}
type optionalAssignmentVisitor struct {
fn OptionalFunc
}
// Visit walks the provided node, transforming field initializations of the form
// m.Field = &OptionalType{} -> m.Field = OptionalType{}
func (v optionalAssignmentVisitor) Visit(n ast.Node) ast.Visitor {
switch t := n.(type) {
case *ast.AssignStmt:
if len(t.Lhs) == 1 && len(t.Rhs) == 1 {
if !isFieldSelector(t.Lhs[0], "m", "") {
return nil
}
unary, ok := t.Rhs[0].(*ast.UnaryExpr)
if !ok || unary.Op != token.AND {
return nil
}
composite, ok := unary.X.(*ast.CompositeLit)
if !ok || composite.Type == nil || len(composite.Elts) != 0 {
return nil
}
if ident, ok := composite.Type.(*ast.Ident); ok && v.fn(ident.Name) {
t.Rhs[0] = composite
}
}
return nil
}
return v
}
type optionalItemsVisitor struct{}
// Visit walks the provided node, looking for specific patterns to transform that match
// the effective outcome of turning struct{ map[x]y || []x } into map[x]y or []x.
func (v *optionalItemsVisitor) Visit(n ast.Node) ast.Visitor {
switch t := n.(type) {
case *ast.RangeStmt:
if isFieldSelector(t.X, "m", "Items") {
t.X = &ast.Ident{Name: "m"}
}
case *ast.AssignStmt:
if len(t.Lhs) == 1 && len(t.Rhs) == 1 {
switch lhs := t.Lhs[0].(type) {
case *ast.IndexExpr:
if isFieldSelector(lhs.X, "m", "Items") {
lhs.X = &ast.StarExpr{X: &ast.Ident{Name: "m"}}
}
default:
if isFieldSelector(t.Lhs[0], "m", "Items") {
t.Lhs[0] = &ast.StarExpr{X: &ast.Ident{Name: "m"}}
}
}
switch rhs := t.Rhs[0].(type) {
case *ast.CallExpr:
if ident, ok := rhs.Fun.(*ast.Ident); ok && ident.Name == "append" {
ast.Walk(v, rhs)
if len(rhs.Args) > 0 {
switch arg := rhs.Args[0].(type) {
case *ast.Ident:
if arg.Name == "m" {
rhs.Args[0] = &ast.StarExpr{X: &ast.Ident{Name: "m"}}
}
}
}
return nil
}
}
}
case *ast.IfStmt:
switch cond := t.Cond.(type) {
case *ast.BinaryExpr:
if cond.Op == token.EQL {
if isFieldSelector(cond.X, "m", "Items") && isIdent(cond.Y, "nil") {
cond.X = &ast.StarExpr{X: &ast.Ident{Name: "m"}}
}
}
}
if t.Init != nil {
// Find form:
// if err := m[len(m.Items)-1].Unmarshal(data[iNdEx:postIndex]); err != nil {
// return err
// }
switch s := t.Init.(type) {
case *ast.AssignStmt:
if call, ok := s.Rhs[0].(*ast.CallExpr); ok {
if sel, ok := call.Fun.(*ast.SelectorExpr); ok {
if x, ok := sel.X.(*ast.IndexExpr); ok {
// m[] -> (*m)[]
if sel2, ok := x.X.(*ast.SelectorExpr); ok {
if ident, ok := sel2.X.(*ast.Ident); ok && ident.Name == "m" {
x.X = &ast.StarExpr{X: &ast.Ident{Name: "m"}}
}
}
// len(m.Items) -> len(*m)
if bin, ok := x.Index.(*ast.BinaryExpr); ok {
if call2, ok := bin.X.(*ast.CallExpr); ok && len(call2.Args) == 1 {
if isFieldSelector(call2.Args[0], "m", "Items") {
call2.Args[0] = &ast.StarExpr{X: &ast.Ident{Name: "m"}}
}
}
}
}
}
}
}
}
case *ast.IndexExpr:
if isFieldSelector(t.X, "m", "Items") {
t.X = &ast.Ident{Name: "m"}
return nil
}
case *ast.CallExpr:
changed := false
for i := range t.Args {
if isFieldSelector(t.Args[i], "m", "Items") {
t.Args[i] = &ast.Ident{Name: "m"}
changed = true
}
}
if changed {
return nil
}
}
return v
}
func isFieldSelector(n ast.Expr, name, field string) bool {
s, ok := n.(*ast.SelectorExpr)
if !ok || s.Sel == nil || (field != "" && s.Sel.Name != field) {
return false
}
return isIdent(s.X, name)
}
func isIdent(n ast.Expr, value string) bool {
ident, ok := n.(*ast.Ident)
return ok && ident.Name == value
}
func receiver(f *ast.FuncDecl) (ident *ast.Ident, pointer bool, ok bool) {
if f.Recv == nil || len(f.Recv.List) != 1 {
return nil, false, false
}
switch t := f.Recv.List[0].Type.(type) {
case *ast.StarExpr:
identity, ok := t.X.(*ast.Ident)
if !ok {
return nil, false, false
}
return identity, true, true
case *ast.Ident:
return t, false, true
}
return nil, false, false
}
// dropExistingTypeDeclarations removes any type declaration for which extractFn returns true. The function
// returns true if the entire declaration should be dropped.
func dropExistingTypeDeclarations(decl ast.Decl, extractFn ExtractFunc) bool {
switch t := decl.(type) {
case *ast.GenDecl:
if t.Tok != token.TYPE {
return false
}
specs := []ast.Spec{}
for _, s := range t.Specs {
switch spec := s.(type) {
case *ast.TypeSpec:
if extractFn(spec) {
continue
}
specs = append(specs, spec)
}
}
if len(specs) == 0 {
return true
}
t.Specs = specs
}
return false
}
// dropEmptyImportDeclarations strips any generated but no-op imports from the generated code
// to prevent generation from being able to define side-effects. The function returns true
// if the entire declaration should be dropped.
func dropEmptyImportDeclarations(decl ast.Decl) bool {
switch t := decl.(type) {
case *ast.GenDecl:
if t.Tok != token.IMPORT {
return false
}
specs := []ast.Spec{}
for _, s := range t.Specs {
switch spec := s.(type) {
case *ast.ImportSpec:
if spec.Name != nil && spec.Name.Name == "_" {
continue
}
specs = append(specs, spec)
}
}
if len(specs) == 0 {
return true
}
t.Specs = specs
}
return false
}
func RewriteTypesWithProtobufStructTags(name string, structTags map[string]map[string]string) error {
return rewriteFile(name, []byte{}, func(fset *token.FileSet, file *ast.File) error {
allErrs := []error{}
// set any new struct tags
for _, d := range file.Decls {
if errs := updateStructTags(d, structTags, []string{"protobuf"}); len(errs) > 0 {
allErrs = append(allErrs, errs...)
}
}
if len(allErrs) > 0 {
var s string
for _, err := range allErrs {
s += err.Error() + "\n"
}
return errors.New(s)
}
return nil
})
}
func updateStructTags(decl ast.Decl, structTags map[string]map[string]string, toCopy []string) []error {
var errs []error
t, ok := decl.(*ast.GenDecl)
if !ok {
return nil
}
if t.Tok != token.TYPE {
return nil
}
for _, s := range t.Specs {
spec, ok := s.(*ast.TypeSpec)
if !ok {
continue
}
typeName := spec.Name.Name
fieldTags, ok := structTags[typeName]
if !ok {
continue
}
st, ok := spec.Type.(*ast.StructType)
if !ok {
continue
}
for i := range st.Fields.List {
f := st.Fields.List[i]
var name string
if len(f.Names) == 0 {
switch t := f.Type.(type) {
case *ast.Ident:
name = t.Name
case *ast.SelectorExpr:
name = t.Sel.Name
default:
errs = append(errs, fmt.Errorf("unable to get name for tag from struct %q, field %#v", spec.Name.Name, t))
continue
}
} else {
name = f.Names[0].Name
}
value, ok := fieldTags[name]
if !ok {
continue
}
var tags customreflect.StructTags
if f.Tag != nil {
oldTags, err := customreflect.ParseStructTags(strings.Trim(f.Tag.Value, "`"))
if err != nil {
errs = append(errs, fmt.Errorf("unable to read struct tag from struct %q, field %q: %v", spec.Name.Name, name, err))
continue
}
tags = oldTags
}
for _, name := range toCopy {
// don't overwrite existing tags
if tags.Has(name) {
continue
}
// append new tags
if v := reflect.StructTag(value).Get(name); len(v) > 0 {
tags = append(tags, customreflect.StructTag{Name: name, Value: v})
}
}
if len(tags) == 0 {
continue
}
if f.Tag == nil {
f.Tag = &ast.BasicLit{}
}
f.Tag.Value = tags.String()
}
}
return errs
}

View file

@ -0,0 +1,33 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package protobuf
import (
"github.com/golang/glog"
"k8s.io/gengo/types"
)
// extractBoolTagOrDie gets the comment-tags for the key and asserts that, if
// it exists, the value is boolean. If the tag did not exist, it returns
// false.
func extractBoolTagOrDie(key string, lines []string) bool {
val, err := types.ExtractSingleBoolCommentTag("+", key, false, lines)
if err != nil {
glog.Fatalf(err.Error())
}
return val
}

View file

@ -0,0 +1,23 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_binary(
name = "protoc-gen-gogo",
srcs = ["main.go"],
tags = ["automanaged"],
deps = [
"//vendor:github.com/gogo/protobuf/gogoproto",
"//vendor:github.com/gogo/protobuf/proto",
"//vendor:github.com/gogo/protobuf/sortkeys",
"//vendor:github.com/gogo/protobuf/vanity/command",
],
)

View file

@ -0,0 +1,32 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package main defines the protoc-gen-gogo binary we use to generate our proto go files,
// as well as takes dependencies on the correct gogo/protobuf packages for godeps.
package main
import (
"github.com/gogo/protobuf/vanity/command"
// dependencies that are required for our packages
_ "github.com/gogo/protobuf/gogoproto"
_ "github.com/gogo/protobuf/proto"
_ "github.com/gogo/protobuf/sortkeys"
)
func main() {
command.Write(command.Generate(command.Read()))
}

View file

@ -0,0 +1 @@
import-boss

View file

@ -0,0 +1,22 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_binary(
name = "import-boss",
srcs = ["main.go"],
tags = ["automanaged"],
deps = [
"//vendor:github.com/golang/glog",
"//vendor:k8s.io/gengo/args",
"//vendor:k8s.io/gengo/examples/import-boss/generators",
],
)

View file

@ -0,0 +1,90 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// import-boss enforces import restrictions in a given repository.
//
// When a directory is verified, import-boss looks for a file called
// ".import-restrictions". If this file is not found, parent directories will be
// recursively searched.
//
// If an ".import-restrictions" file is found, then all imports of the package
// are checked against each "rule" in the file. A rule consists of three parts:
// * A SelectorRegexp, to select the import paths that the rule applies to.
// * A list of AllowedPrefixes
// * A list of ForbiddenPrefixes
// An import is allowed if it matches at least one allowed prefix and does not
// match any forbidden prefix. An example file looks like this:
//
// {
// "Rules": [
// {
// "SelectorRegexp": "k8s[.]io",
// "AllowedPrefixes": [
// "k8s.io/gengo/examples",
// "k8s.io/kubernetes/third_party"
// ],
// "ForbiddenPrefixes": [
// "k8s.io/kubernetes/pkg/third_party/deprecated"
// ]
// },
// {
// "SelectorRegexp": "^unsafe$",
// "AllowedPrefixes": [
// ],
// "ForbiddenPrefixes": [
// ""
// ]
// }
// ]
// }
//
// Note the secound block explicitly matches the unsafe package, and forbids it
// ("" is a prefix of everything).
package main
import (
"os"
"path/filepath"
"k8s.io/gengo/args"
"k8s.io/gengo/examples/import-boss/generators"
"github.com/golang/glog"
)
func main() {
arguments := args.Default()
// Override defaults. These are Kubernetes specific input and output
// locations.
arguments.InputDirs = []string{
"k8s.io/kubernetes/pkg/...",
"k8s.io/kubernetes/cmd/...",
"k8s.io/kubernetes/plugin/...",
}
arguments.GoHeaderFilePath = filepath.Join(args.DefaultSourceTree(), "k8s.io/kubernetes/hack/boilerplate/boilerplate.go.txt")
// arguments.VerifyOnly = true
if err := arguments.Execute(
generators.NameSystems(),
generators.DefaultNameSystem(),
generators.Packages,
); err != nil {
glog.Errorf("Error: %v", err)
os.Exit(1)
}
glog.V(2).Info("Completed successfully.")
}

View file

@ -0,0 +1,23 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_binary(
name = "informer-gen",
srcs = ["main.go"],
tags = ["automanaged"],
deps = [
"//cmd/libs/go2idl/informer-gen/generators:go_default_library",
"//vendor:github.com/golang/glog",
"//vendor:github.com/spf13/pflag",
"//vendor:k8s.io/gengo/args",
],
)

View file

@ -0,0 +1,36 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_library(
name = "go_default_library",
srcs = [
"customargs.go",
"factory.go",
"generic.go",
"groupinterface.go",
"informer.go",
"packages.go",
"tags.go",
"types.go",
"versioninterface.go",
],
tags = ["automanaged"],
deps = [
"//cmd/libs/go2idl/client-gen/types:go_default_library",
"//vendor:github.com/golang/glog",
"//vendor:github.com/spf13/pflag",
"//vendor:k8s.io/gengo/args",
"//vendor:k8s.io/gengo/generator",
"//vendor:k8s.io/gengo/namer",
"//vendor:k8s.io/gengo/types",
],
)

View file

@ -0,0 +1,31 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package generators
import "github.com/spf13/pflag"
type CustomArgs struct {
VersionedClientSetPackage string
InternalClientSetPackage string
ListersPackage string
}
func (ca *CustomArgs) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&ca.InternalClientSetPackage, "internal-clientset-package", ca.InternalClientSetPackage, "the full package name for the internal clientset to use")
fs.StringVar(&ca.VersionedClientSetPackage, "versioned-clientset-package", ca.VersionedClientSetPackage, "the full package name for the versioned clientset to use")
fs.StringVar(&ca.ListersPackage, "listers-package", ca.ListersPackage, "the full package name for the listers to use")
}

View file

@ -0,0 +1,185 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package generators
import (
"io"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
clientgentypes "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types"
"github.com/golang/glog"
)
// factoryGenerator produces a file of listers for a given GroupVersion and
// type.
type factoryGenerator struct {
generator.DefaultGen
outputPackage string
imports namer.ImportTracker
groupVersions map[string]clientgentypes.GroupVersions
internalClientSetPackage string
versionedClientSetPackage string
filtered bool
}
var _ generator.Generator = &factoryGenerator{}
func (g *factoryGenerator) Filter(c *generator.Context, t *types.Type) bool {
if !g.filtered {
g.filtered = true
return true
}
return false
}
func (g *factoryGenerator) Namers(c *generator.Context) namer.NameSystems {
return namer.NameSystems{
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
}
}
func (g *factoryGenerator) Imports(c *generator.Context) (imports []string) {
imports = append(imports, g.imports.ImportLines()...)
return
}
func (g *factoryGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
sw := generator.NewSnippetWriter(w, c, "{{", "}}")
glog.V(5).Infof("processing type %v", t)
gvInterfaces := make(map[string]*types.Type)
gvNewFuncs := make(map[string]*types.Type)
for groupName := range g.groupVersions {
gvInterfaces[groupName] = c.Universe.Type(types.Name{Package: packageForGroup(g.outputPackage, g.groupVersions[groupName].Group), Name: "Interface"})
gvNewFuncs[groupName] = c.Universe.Function(types.Name{Package: packageForGroup(g.outputPackage, g.groupVersions[groupName].Group), Name: "New"})
}
m := map[string]interface{}{
"cacheSharedIndexInformer": c.Universe.Type(cacheSharedIndexInformer),
"groupVersions": g.groupVersions,
"gvInterfaces": gvInterfaces,
"gvNewFuncs": gvNewFuncs,
"interfacesNewInternalInformerFunc": c.Universe.Type(interfacesNewInternalInformerFunc),
"interfacesNewVersionedInformerFunc": c.Universe.Type(interfacesNewVersionedInformerFunc),
"interfacesSharedInformerFactory": c.Universe.Type(interfacesSharedInformerFactory),
"internalClientSetInterface": c.Universe.Type(types.Name{Package: g.internalClientSetPackage, Name: "Interface"}),
"reflectType": c.Universe.Type(reflectType),
"runtimeObject": c.Universe.Type(runtimeObject),
"syncMutex": c.Universe.Type(syncMutex),
"timeDuration": c.Universe.Type(timeDuration),
"versionedClientSetInterface": c.Universe.Type(types.Name{Package: g.versionedClientSetPackage, Name: "Interface"}),
}
sw.Do(sharedInformerFactoryStruct, m)
sw.Do(sharedInformerFactoryInterface, m)
return sw.Error()
}
var sharedInformerFactoryStruct = `
type sharedInformerFactory struct {
internalClient {{.internalClientSetInterface|raw}}
versionedClient {{.versionedClientSetInterface|raw}}
lock {{.syncMutex|raw}}
defaultResync {{.timeDuration|raw}}
informers map[{{.reflectType|raw}}]{{.cacheSharedIndexInformer|raw}}
// startedInformers is used for tracking which informers have been started.
// This allows Start() to be called multiple times safely.
startedInformers map[{{.reflectType|raw}}]bool
}
// NewSharedInformerFactory constructs a new instance of sharedInformerFactory
func NewSharedInformerFactory(internalClient {{.internalClientSetInterface|raw}}, versionedClient {{.versionedClientSetInterface|raw}}, defaultResync {{.timeDuration|raw}}) {{.interfacesSharedInformerFactory|raw}} {
return &sharedInformerFactory{
internalClient: internalClient,
versionedClient: versionedClient,
defaultResync: defaultResync,
informers: make(map[{{.reflectType|raw}}]{{.cacheSharedIndexInformer|raw}}),
startedInformers: make(map[{{.reflectType|raw}}]bool),
}
}
// Start initializes all requested informers.
func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {
f.lock.Lock()
defer f.lock.Unlock()
for informerType, informer := range f.informers {
if !f.startedInformers[informerType] {
go informer.Run(stopCh)
f.startedInformers[informerType] = true
}
}
}
// InternalInformerFor returns the SharedIndexInformer for obj using an internal
// client.
func (f *sharedInformerFactory) InternalInformerFor(obj {{.runtimeObject|raw}}, newFunc {{.interfacesNewInternalInformerFunc|raw}}) {{.cacheSharedIndexInformer|raw}} {
f.lock.Lock()
defer f.lock.Unlock()
informerType := reflect.TypeOf(obj)
informer, exists := f.informers[informerType]
if exists {
return informer
}
informer = newFunc(f.internalClient, f.defaultResync)
f.informers[informerType] = informer
return informer
}
// VersionedInformerFor returns the SharedIndexInformer for obj using a
// versioned client.
func (f *sharedInformerFactory) VersionedInformerFor(obj {{.runtimeObject|raw}}, newFunc {{.interfacesNewVersionedInformerFunc|raw}}) {{.cacheSharedIndexInformer|raw}} {
f.lock.Lock()
defer f.lock.Unlock()
informerType := reflect.TypeOf(obj)
informer, exists := f.informers[informerType]
if exists {
return informer
}
informer = newFunc(f.versionedClient, f.defaultResync)
f.informers[informerType] = informer
return informer
}
`
var sharedInformerFactoryInterface = `
// SharedInformerFactory provides shared informers for resources in all known
// API group versions.
type SharedInformerFactory interface {
{{.interfacesSharedInformerFactory|raw}}
{{$gvInterfaces := .gvInterfaces}}
{{range $groupName, $group := .groupVersions}}{{$groupName}}() {{index $gvInterfaces $groupName|raw}}
{{end}}
}
{{$gvNewFuncs := .gvNewFuncs}}
{{range $groupName, $group := .groupVersions}}
func (f *sharedInformerFactory) {{$groupName}}() {{index $gvInterfaces $groupName|raw}} {
return {{index $gvNewFuncs $groupName|raw}}(f)
}
{{end}}
`

View file

@ -0,0 +1,175 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package generators
import (
"io"
"sort"
"strings"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
clientgentypes "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types"
)
// genericGenerator generates the generic informer.
type genericGenerator struct {
generator.DefaultGen
outputPackage string
imports namer.ImportTracker
groupVersions map[string]clientgentypes.GroupVersions
typesForGroupVersion map[clientgentypes.GroupVersion][]*types.Type
filtered bool
}
var _ generator.Generator = &genericGenerator{}
func (g *genericGenerator) Filter(c *generator.Context, t *types.Type) bool {
if !g.filtered {
g.filtered = true
return true
}
return false
}
func (g *genericGenerator) Namers(c *generator.Context) namer.NameSystems {
pluralExceptions := map[string]string{
"Endpoints": "Endpoints",
}
return namer.NameSystems{
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
"allLowercasePlural": namer.NewAllLowercasePluralNamer(pluralExceptions),
"publicPlural": namer.NewPublicPluralNamer(pluralExceptions),
}
}
func (g *genericGenerator) Imports(c *generator.Context) (imports []string) {
imports = append(imports, g.imports.ImportLines()...)
imports = append(imports, "fmt")
return
}
type group struct {
Name string
Versions []*version
}
type groupSort []group
func (g groupSort) Len() int { return len(g) }
func (g groupSort) Less(i, j int) bool { return strings.ToLower(g[i].Name) < strings.ToLower(g[j].Name) }
func (g groupSort) Swap(i, j int) { g[i], g[j] = g[j], g[i] }
type version struct {
Name string
Resources []*types.Type
}
type versionSort []*version
func (v versionSort) Len() int { return len(v) }
func (v versionSort) Less(i, j int) bool {
return strings.ToLower(v[i].Name) < strings.ToLower(v[j].Name)
}
func (v versionSort) Swap(i, j int) { v[i], v[j] = v[j], v[i] }
func (g *genericGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
sw := generator.NewSnippetWriter(w, c, "{{", "}}")
groups := []group{}
schemeGVs := make(map[*version]*types.Type)
orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)}
for _, groupVersions := range g.groupVersions {
group := group{
Name: namer.IC(groupVersions.Group.NonEmpty()),
Versions: []*version{},
}
for _, v := range groupVersions.Versions {
gv := clientgentypes.GroupVersion{Group: groupVersions.Group, Version: v}
version := &version{
Name: namer.IC(v.NonEmpty()),
Resources: orderer.OrderTypes(g.typesForGroupVersion[gv]),
}
schemeGVs[version] = c.Universe.Variable(types.Name{Package: g.typesForGroupVersion[gv][0].Name.Package, Name: "SchemeGroupVersion"})
group.Versions = append(group.Versions, version)
}
sort.Sort(versionSort(group.Versions))
groups = append(groups, group)
}
sort.Sort(groupSort(groups))
m := map[string]interface{}{
"cacheGenericLister": c.Universe.Type(cacheGenericLister),
"cacheNewGenericLister": c.Universe.Function(cacheNewGenericLister),
"cacheSharedIndexInformer": c.Universe.Type(cacheSharedIndexInformer),
"groups": groups,
"schemeGVs": schemeGVs,
"schemaGroupResource": c.Universe.Type(schemaGroupResource),
"schemaGroupVersionResource": c.Universe.Type(schemaGroupVersionResource),
}
sw.Do(genericInformer, m)
sw.Do(forResource, m)
return sw.Error()
}
var genericInformer = `
// GenericInformer is type of SharedIndexInformer which will locate and delegate to other
// sharedInformers based on type
type GenericInformer interface {
Informer() {{.cacheSharedIndexInformer|raw}}
Lister() {{.cacheGenericLister|raw}}
}
type genericInformer struct {
informer {{.cacheSharedIndexInformer|raw}}
resource {{.schemaGroupResource|raw}}
}
// Informer returns the SharedIndexInformer.
func (f *genericInformer) Informer() {{.cacheSharedIndexInformer|raw}} {
return f.informer
}
// Lister returns the GenericLister.
func (f *genericInformer) Lister() {{.cacheGenericLister|raw}} {
return {{.cacheNewGenericLister|raw}}(f.Informer().GetIndexer(), f.resource)
}
`
var forResource = `
// ForResource gives generic access to a shared informer of the matching type
// TODO extend this to unknown resources with a client pool
func (f *sharedInformerFactory) ForResource(resource {{.schemaGroupVersionResource|raw}}) (GenericInformer, error) {
switch resource {
{{range $group := .groups -}}
{{range $version := .Versions -}}
// Group={{$group.Name}}, Version={{.Name}}
{{range .Resources -}}
case {{index $.schemeGVs $version|raw}}.WithResource("{{.|allLowercasePlural}}"):
return &genericInformer{resource: resource.GroupResource(), informer: f.{{$group.Name}}().{{$version.Name}}().{{.|publicPlural}}().Informer()}, nil
{{end}}
{{end}}
{{end -}}
}
return nil, fmt.Errorf("no informer found for %v", resource)
}
`

View file

@ -0,0 +1,114 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package generators
import (
"io"
"path/filepath"
"strings"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
clientgentypes "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types"
)
// groupInterfaceGenerator generates the per-group interface file.
type groupInterfaceGenerator struct {
generator.DefaultGen
outputPackage string
imports namer.ImportTracker
groupVersions clientgentypes.GroupVersions
filtered bool
}
var _ generator.Generator = &groupInterfaceGenerator{}
func (g *groupInterfaceGenerator) Filter(c *generator.Context, t *types.Type) bool {
if !g.filtered {
g.filtered = true
return true
}
return false
}
func (g *groupInterfaceGenerator) Namers(c *generator.Context) namer.NameSystems {
return namer.NameSystems{
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
}
}
func (g *groupInterfaceGenerator) Imports(c *generator.Context) (imports []string) {
imports = append(imports, g.imports.ImportLines()...)
return
}
type versionData struct {
Name string
Interface *types.Type
New *types.Type
}
func (g *groupInterfaceGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
sw := generator.NewSnippetWriter(w, c, "$", "$")
versions := make([]versionData, 0, len(g.groupVersions.Versions))
for _, version := range g.groupVersions.Versions {
gv := clientgentypes.GroupVersion{Group: g.groupVersions.Group, Version: version}
versionPackage := filepath.Join(g.outputPackage, strings.ToLower(gv.Version.NonEmpty()))
iface := c.Universe.Type(types.Name{Package: versionPackage, Name: "Interface"})
versions = append(versions, versionData{
Name: namer.IC(version.NonEmpty()),
Interface: iface,
New: c.Universe.Function(types.Name{Package: versionPackage, Name: "New"}),
})
}
m := map[string]interface{}{
"interfacesSharedInformerFactory": c.Universe.Type(interfacesSharedInformerFactory),
"versions": versions,
}
sw.Do(groupTemplate, m)
return sw.Error()
}
var groupTemplate = `
// Interface provides access to each of this group's versions.
type Interface interface {
$range .versions -$
// $.Name$ provides access to shared informers for resources in $.Name$.
$.Name$() $.Interface|raw$
$end$
}
type group struct {
$.interfacesSharedInformerFactory|raw$
}
// New returns a new Interface.
func New(f $.interfacesSharedInformerFactory|raw$) Interface {
return &group{f}
}
$range .versions$
// $.Name$ returns a new $.Interface|raw$.
func (g *group) $.Name$() $.Interface|raw$ {
return $.New|raw$(g.SharedInformerFactory)
}
$end$
`

View file

@ -0,0 +1,195 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package generators
import (
"fmt"
"io"
"strings"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
clientgentypes "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types"
"github.com/golang/glog"
)
// informerGenerator produces a file of listers for a given GroupVersion and
// type.
type informerGenerator struct {
generator.DefaultGen
outputPackage string
groupVersion clientgentypes.GroupVersion
typeToGenerate *types.Type
imports namer.ImportTracker
versionedClientSetPackage string
internalClientSetPackage string
listersPackage string
}
var _ generator.Generator = &informerGenerator{}
func (g *informerGenerator) Filter(c *generator.Context, t *types.Type) bool {
return t == g.typeToGenerate
}
func (g *informerGenerator) Namers(c *generator.Context) namer.NameSystems {
return namer.NameSystems{
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
}
}
func (g *informerGenerator) Imports(c *generator.Context) (imports []string) {
imports = append(imports, g.imports.ImportLines()...)
return
}
func (g *informerGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
sw := generator.NewSnippetWriter(w, c, "$", "$")
glog.V(5).Infof("processing type %v", t)
//listerPackage := "k8s.io/kubernetes/pkg/client/listers/" + g.groupVersion.Group.NonEmpty() + "/" + strings.ToLower(g.groupVersion.Version.NonEmpty())
listerPackage := fmt.Sprintf("%s/%s/%s", g.listersPackage, g.groupVersion.Group.NonEmpty(), strings.ToLower(g.groupVersion.Version.NonEmpty()))
var (
clientSetInterface, namespaceAll *types.Type
informerFor string
)
if len(g.groupVersion.Version) == 0 {
clientSetInterface = c.Universe.Type(types.Name{Package: g.internalClientSetPackage, Name: "Interface"})
namespaceAll = c.Universe.Type(apiNamespaceAll)
informerFor = "InternalInformerFor"
} else {
clientSetInterface = c.Universe.Type(types.Name{Package: g.versionedClientSetPackage, Name: "Interface"})
namespaceAll = c.Universe.Type(v1NamespaceAll)
informerFor = "VersionedInformerFor"
}
m := map[string]interface{}{
"apiScheme": c.Universe.Type(apiScheme),
"cacheIndexers": c.Universe.Type(cacheIndexers),
"cacheListWatch": c.Universe.Type(cacheListWatch),
"cacheMetaNamespaceIndexFunc": c.Universe.Function(cacheMetaNamespaceIndexFunc),
"cacheNamespaceIndex": c.Universe.Variable(cacheNamespaceIndex),
"cacheNewSharedIndexInformer": c.Universe.Function(cacheNewSharedIndexInformer),
"cacheSharedIndexInformer": c.Universe.Type(cacheSharedIndexInformer),
"clientSetInterface": clientSetInterface,
"group": namer.IC(g.groupVersion.Group.NonEmpty()),
"informerFor": informerFor,
"interfacesSharedInformerFactory": c.Universe.Type(interfacesSharedInformerFactory),
"listOptions": c.Universe.Type(listOptions),
"lister": c.Universe.Type(types.Name{Package: listerPackage, Name: t.Name.Name + "Lister"}),
"namespaceAll": namespaceAll,
"namespaced": !extractBoolTagOrDie("nonNamespaced", t.SecondClosestCommentLines),
"newLister": c.Universe.Function(types.Name{Package: listerPackage, Name: "New" + t.Name.Name + "Lister"}),
"runtimeObject": c.Universe.Type(runtimeObject),
"timeDuration": c.Universe.Type(timeDuration),
"type": t,
"v1ListOptions": c.Universe.Type(v1ListOptions),
"version": namer.IC(g.groupVersion.Version.String()),
"watchInterface": c.Universe.Type(watchInterface),
}
sw.Do(typeInformerInterface, m)
sw.Do(typeInformerStruct, m)
if len(g.groupVersion.Version) == 0 {
sw.Do(typeInformerConstructorInternal, m)
} else {
sw.Do(typeInformerConstructorVersioned, m)
}
sw.Do(typeInformerInformer, m)
sw.Do(typeInformerLister, m)
return sw.Error()
}
var typeInformerInterface = `
// $.type|public$Informer provides access to a shared informer and lister for
// $.type|publicPlural$.
type $.type|public$Informer interface {
Informer() $.cacheSharedIndexInformer|raw$
Lister() $.lister|raw$
}
`
var typeInformerStruct = `
type $.type|private$Informer struct {
factory $.interfacesSharedInformerFactory|raw$
}
`
var typeInformerConstructorInternal = `
func new$.type|public$Informer(client $.clientSetInterface|raw$, resyncPeriod $.timeDuration|raw$) $.cacheSharedIndexInformer|raw$ {
sharedIndexInformer := $.cacheNewSharedIndexInformer|raw$(
&$.cacheListWatch|raw${
ListFunc: func(options $.v1ListOptions|raw$) ($.runtimeObject|raw$, error) {
var internalOptions $.listOptions|raw$
if err := $.apiScheme|raw$.Convert(&options, &internalOptions, nil); err != nil {
return nil, err
}
return client.$.group$$.version$().$.type|publicPlural$($if .namespaced$$.namespaceAll|raw$$end$).List(internalOptions)
},
WatchFunc: func(options $.v1ListOptions|raw$) ($.watchInterface|raw$, error) {
var internalOptions $.listOptions|raw$
if err := $.apiScheme|raw$.Convert(&options, &internalOptions, nil); err != nil {
return nil, err
}
return client.$.group$$.version$().$.type|publicPlural$($if .namespaced$$.namespaceAll|raw$$end$).Watch(internalOptions)
},
},
&$.type|raw${},
resyncPeriod,
$.cacheIndexers|raw${$.cacheNamespaceIndex|raw$: $.cacheMetaNamespaceIndexFunc|raw$},
)
return sharedIndexInformer
}
`
var typeInformerConstructorVersioned = `
func new$.type|public$Informer(client $.clientSetInterface|raw$, resyncPeriod $.timeDuration|raw$) $.cacheSharedIndexInformer|raw$ {
sharedIndexInformer := $.cacheNewSharedIndexInformer|raw$(
&$.cacheListWatch|raw${
ListFunc: func(options $.v1ListOptions|raw$) ($.runtimeObject|raw$, error) {
return client.$.group$$.version$().$.type|publicPlural$($if .namespaced$$.namespaceAll|raw$$end$).List(options)
},
WatchFunc: func(options $.v1ListOptions|raw$) ($.watchInterface|raw$, error) {
return client.$.group$$.version$().$.type|publicPlural$($if .namespaced$$.namespaceAll|raw$$end$).Watch(options)
},
},
&$.type|raw${},
resyncPeriod,
$.cacheIndexers|raw${$.cacheNamespaceIndex|raw$: $.cacheMetaNamespaceIndexFunc|raw$},
)
return sharedIndexInformer
}
`
var typeInformerInformer = `
func (f *$.type|private$Informer) Informer() $.cacheSharedIndexInformer|raw$ {
return f.factory.$.informerFor$(&$.type|raw${}, new$.type|public$Informer)
}
`
var typeInformerLister = `
func (f *$.type|private$Informer) Lister() $.lister|raw$ {
return $.newLister|raw$(f.Informer().GetIndexer())
}
`

View file

@ -0,0 +1,291 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package generators
import (
"fmt"
"path/filepath"
"strings"
"k8s.io/gengo/args"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
clientgentypes "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types"
"github.com/golang/glog"
"github.com/spf13/pflag"
)
// NameSystems returns the name system used by the generators in this package.
func NameSystems() namer.NameSystems {
pluralExceptions := map[string]string{
"Endpoints": "Endpoints",
}
return namer.NameSystems{
"public": namer.NewPublicNamer(0),
"private": namer.NewPrivateNamer(0),
"raw": namer.NewRawNamer("", nil),
"publicPlural": namer.NewPublicPluralNamer(pluralExceptions),
"allLowercasePlural": namer.NewAllLowercasePluralNamer(pluralExceptions),
"lowercaseSingular": &lowercaseSingularNamer{},
}
}
// lowercaseSingularNamer implements Namer
type lowercaseSingularNamer struct{}
// Name returns t's name in all lowercase.
func (n *lowercaseSingularNamer) Name(t *types.Type) string {
return strings.ToLower(t.Name.Name)
}
// DefaultNameSystem returns the default name system for ordering the types to be
// processed by the generators in this package.
func DefaultNameSystem() string {
return "public"
}
// generatedBy returns information about the arguments used to invoke
// lister-gen.
func generatedBy() string {
var cmdArgs string
pflag.VisitAll(func(f *pflag.Flag) {
if !f.Changed || f.Name == "verify-only" {
return
}
cmdArgs += fmt.Sprintf("--%s=%s ", f.Name, f.Value)
})
return fmt.Sprintf("\n// This file was automatically generated by informer-gen with arguments: %s\n\n", cmdArgs)
}
// objectMetaForPackage returns the type of ObjectMeta used by package p.
func objectMetaForPackage(p *types.Package) (*types.Type, error) {
generatingForPackage := false
for _, t := range p.Types {
// filter out types which dont have genclient=true.
if extractBoolTagOrDie("genclient", t.SecondClosestCommentLines) == false {
continue
}
generatingForPackage = true
for _, member := range t.Members {
if member.Name == "ObjectMeta" {
return member.Type, nil
}
}
}
if generatingForPackage {
return nil, fmt.Errorf("unable to find ObjectMeta for any types in package %s", p.Path)
}
return nil, nil
}
// isInternal returns true if t's package is k8s.io/kubernetes/pkg/api.
func isInternal(t *types.Type) bool {
return t.Name.Package == "k8s.io/kubernetes/pkg/api"
}
func packageForGroup(base string, group clientgentypes.Group) string {
return filepath.Join(base, group.NonEmpty())
}
// Packages makes the client package definition.
func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
boilerplate, err := arguments.LoadGoBoilerplate()
if err != nil {
glog.Fatalf("Failed loading boilerplate: %v", err)
}
boilerplate = append(boilerplate, []byte(generatedBy())...)
customArgs, ok := arguments.CustomArgs.(*CustomArgs)
if !ok {
glog.Fatalf("Wrong CustomArgs type: %T", arguments.CustomArgs)
}
var packageList generator.Packages
typesForGroupVersion := make(map[clientgentypes.GroupVersion][]*types.Type)
groupVersions := make(map[string]clientgentypes.GroupVersions)
for _, inputDir := range arguments.InputDirs {
p := context.Universe.Package(inputDir)
objectMeta, err := objectMetaForPackage(p)
if err != nil {
glog.Fatal(err)
}
if objectMeta == nil {
// no types in this package had genclient
continue
}
var gv clientgentypes.GroupVersion
if isInternal(objectMeta) {
lastSlash := strings.LastIndex(p.Path, "/")
if lastSlash == -1 {
glog.Fatalf("error constructing internal group version for package %q", p.Path)
}
gv.Group = clientgentypes.Group(p.Path[lastSlash+1:])
} else {
parts := strings.Split(p.Path, "/")
gv.Group = clientgentypes.Group(parts[len(parts)-2])
gv.Version = clientgentypes.Version(parts[len(parts)-1])
}
var typesToGenerate []*types.Type
for _, t := range p.Types {
// filter out types which dont have genclient=true.
if extractBoolTagOrDie("genclient", t.SecondClosestCommentLines) == false {
continue
}
// filter out types which have noMethods
if extractBoolTagOrDie("noMethods", t.SecondClosestCommentLines) == true {
continue
}
typesToGenerate = append(typesToGenerate, t)
if _, ok := typesForGroupVersion[gv]; !ok {
typesForGroupVersion[gv] = []*types.Type{}
}
typesForGroupVersion[gv] = append(typesForGroupVersion[gv], t)
}
if len(typesToGenerate) == 0 {
continue
}
icGroupName := namer.IC(gv.Group.NonEmpty())
groupVersionsEntry, ok := groupVersions[icGroupName]
if !ok {
groupVersionsEntry = clientgentypes.GroupVersions{
Group: gv.Group,
}
}
groupVersionsEntry.Versions = append(groupVersionsEntry.Versions, gv.Version)
groupVersions[icGroupName] = groupVersionsEntry
orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)}
typesToGenerate = orderer.OrderTypes(typesToGenerate)
packageList = append(packageList, versionPackage(arguments.OutputPackagePath, gv, boilerplate, typesToGenerate, customArgs.InternalClientSetPackage, customArgs.VersionedClientSetPackage, customArgs.ListersPackage))
}
packageList = append(packageList, factoryPackage(arguments.OutputPackagePath, boilerplate, groupVersions, customArgs.InternalClientSetPackage, customArgs.VersionedClientSetPackage, typesForGroupVersion))
for _, groupVersionsEntry := range groupVersions {
packageList = append(packageList, groupPackage(arguments.OutputPackagePath, groupVersionsEntry, boilerplate))
}
return packageList
}
func factoryPackage(basePackage string, boilerplate []byte, groupVersions map[string]clientgentypes.GroupVersions, internalClientSetPackage, versionedClientSetPackage string, typesForGroupVersion map[clientgentypes.GroupVersion][]*types.Type) generator.Package {
return &generator.DefaultPackage{
PackageName: filepath.Base(basePackage),
PackagePath: basePackage,
HeaderText: boilerplate,
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
generators = append(generators, &factoryGenerator{
DefaultGen: generator.DefaultGen{
OptionalName: "factory",
},
outputPackage: basePackage,
imports: generator.NewImportTracker(),
groupVersions: groupVersions,
internalClientSetPackage: internalClientSetPackage,
versionedClientSetPackage: versionedClientSetPackage,
})
generators = append(generators, &genericGenerator{
DefaultGen: generator.DefaultGen{
OptionalName: "generic",
},
outputPackage: basePackage,
imports: generator.NewImportTracker(),
groupVersions: groupVersions,
typesForGroupVersion: typesForGroupVersion,
})
return generators
},
}
}
func groupPackage(basePackage string, groupVersions clientgentypes.GroupVersions, boilerplate []byte) generator.Package {
packagePath := filepath.Join(basePackage, strings.ToLower(groupVersions.Group.NonEmpty()))
return &generator.DefaultPackage{
PackageName: strings.ToLower(groupVersions.Group.NonEmpty()),
PackagePath: packagePath,
HeaderText: boilerplate,
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
generators = append(generators, &groupInterfaceGenerator{
DefaultGen: generator.DefaultGen{
OptionalName: "interface",
},
outputPackage: packagePath,
groupVersions: groupVersions,
imports: generator.NewImportTracker(),
})
return generators
},
FilterFunc: func(c *generator.Context, t *types.Type) bool {
// piggy-back on types that are tagged for client-gen
return extractBoolTagOrDie("genclient", t.SecondClosestCommentLines) == true
},
}
}
func versionPackage(basePackage string, gv clientgentypes.GroupVersion, boilerplate []byte, typesToGenerate []*types.Type, internalClientSetPackage, versionedClientSetPackage, listersPackage string) generator.Package {
packagePath := filepath.Join(basePackage, strings.ToLower(gv.Group.NonEmpty()), strings.ToLower(gv.Version.NonEmpty()))
return &generator.DefaultPackage{
PackageName: strings.ToLower(gv.Version.NonEmpty()),
PackagePath: packagePath,
HeaderText: boilerplate,
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
generators = append(generators, &versionInterfaceGenerator{
DefaultGen: generator.DefaultGen{
OptionalName: "interface",
},
outputPackage: packagePath,
imports: generator.NewImportTracker(),
types: typesToGenerate,
})
for _, t := range typesToGenerate {
generators = append(generators, &informerGenerator{
DefaultGen: generator.DefaultGen{
OptionalName: strings.ToLower(t.Name.Name),
},
outputPackage: packagePath,
groupVersion: gv,
typeToGenerate: t,
imports: generator.NewImportTracker(),
internalClientSetPackage: internalClientSetPackage,
versionedClientSetPackage: versionedClientSetPackage,
listersPackage: listersPackage,
})
}
return generators
},
FilterFunc: func(c *generator.Context, t *types.Type) bool {
// piggy-back on types that are tagged for client-gen
return extractBoolTagOrDie("genclient", t.SecondClosestCommentLines) == true
},
}
}

View file

@ -0,0 +1,33 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package generators
import (
"github.com/golang/glog"
"k8s.io/gengo/types"
)
// extractBoolTagOrDie gets the comment-tags for the key and asserts that, if
// it exists, the value is boolean. If the tag did not exist, it returns
// false.
func extractBoolTagOrDie(key string, lines []string) bool {
val, err := types.ExtractSingleBoolCommentTag("+", key, false, lines)
if err != nil {
glog.Fatalf(err.Error())
}
return val
}

View file

@ -0,0 +1,45 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package generators
import "k8s.io/gengo/types"
var (
apiNamespaceAll = types.Name{Package: "k8s.io/kubernetes/pkg/api", Name: "NamespaceAll"}
apiScheme = types.Name{Package: "k8s.io/kubernetes/pkg/api", Name: "Scheme"}
cacheGenericLister = types.Name{Package: "k8s.io/kubernetes/pkg/client/cache", Name: "GenericLister"}
cacheIndexers = types.Name{Package: "k8s.io/kubernetes/pkg/client/cache", Name: "Indexers"}
cacheListWatch = types.Name{Package: "k8s.io/kubernetes/pkg/client/cache", Name: "ListWatch"}
cacheMetaNamespaceIndexFunc = types.Name{Package: "k8s.io/kubernetes/pkg/client/cache", Name: "MetaNamespaceIndexFunc"}
cacheNamespaceIndex = types.Name{Package: "k8s.io/kubernetes/pkg/client/cache", Name: "NamespaceIndex"}
cacheNewGenericLister = types.Name{Package: "k8s.io/kubernetes/pkg/client/cache", Name: "NewGenericLister"}
cacheNewSharedIndexInformer = types.Name{Package: "k8s.io/kubernetes/pkg/client/cache", Name: "NewSharedIndexInformer"}
cacheSharedIndexInformer = types.Name{Package: "k8s.io/kubernetes/pkg/client/cache", Name: "SharedIndexInformer"}
interfacesNewInternalInformerFunc = types.Name{Package: "k8s.io/kubernetes/pkg/client/informers/interfaces", Name: "NewInternalInformerFunc"}
interfacesNewVersionedInformerFunc = types.Name{Package: "k8s.io/kubernetes/pkg/client/informers/interfaces", Name: "NewVersionedInformerFunc"}
interfacesSharedInformerFactory = types.Name{Package: "k8s.io/kubernetes/pkg/client/informers/interfaces", Name: "SharedInformerFactory"}
listOptions = types.Name{Package: "k8s.io/kubernetes/pkg/api", Name: "ListOptions"}
reflectType = types.Name{Package: "reflect", Name: "Type"}
runtimeObject = types.Name{Package: "k8s.io/kubernetes/pkg/runtime", Name: "Object"}
schemaGroupResource = types.Name{Package: "k8s.io/kubernetes/pkg/runtime/schema", Name: "GroupResource"}
schemaGroupVersionResource = types.Name{Package: "k8s.io/kubernetes/pkg/runtime/schema", Name: "GroupVersionResource"}
syncMutex = types.Name{Package: "sync", Name: "Mutex"}
timeDuration = types.Name{Package: "time", Name: "Duration"}
v1ListOptions = types.Name{Package: "k8s.io/kubernetes/pkg/api/v1", Name: "ListOptions"}
v1NamespaceAll = types.Name{Package: "k8s.io/kubernetes/pkg/api/v1", Name: "NamespaceAll"}
watchInterface = types.Name{Package: "k8s.io/kubernetes/pkg/watch", Name: "Interface"}
)

View file

@ -0,0 +1,94 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package generators
import (
"io"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
)
// versionInterfaceGenerator generates the per-version interface file.
type versionInterfaceGenerator struct {
generator.DefaultGen
outputPackage string
imports namer.ImportTracker
types []*types.Type
filtered bool
}
var _ generator.Generator = &versionInterfaceGenerator{}
func (g *versionInterfaceGenerator) Filter(c *generator.Context, t *types.Type) bool {
if !g.filtered {
g.filtered = true
return true
}
return false
}
func (g *versionInterfaceGenerator) Namers(c *generator.Context) namer.NameSystems {
return namer.NameSystems{
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
}
}
func (g *versionInterfaceGenerator) Imports(c *generator.Context) (imports []string) {
imports = append(imports, g.imports.ImportLines()...)
return
}
func (g *versionInterfaceGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
sw := generator.NewSnippetWriter(w, c, "$", "$")
m := map[string]interface{}{
"interfacesSharedInformerFactory": c.Universe.Type(interfacesSharedInformerFactory),
"types": g.types,
}
sw.Do(versionTemplate, m)
return sw.Error()
}
var versionTemplate = `
// Interface provides access to all the informers in this group version.
type Interface interface {
$range .types -$
// $.|publicPlural$ returns a $.|public$Informer.
$.|publicPlural$() $.|public$Informer
$end$
}
type version struct {
$.interfacesSharedInformerFactory|raw$
}
// New returns a new Interface.
func New(f $.interfacesSharedInformerFactory|raw$) Interface {
return &version{f}
}
$range .types$
// $.|publicPlural$ returns a $.|public$Informer.
func (v *version) $.|publicPlural$() $.|public$Informer {
return &$.|private$Informer{factory: v.SharedInformerFactory}
}
$end$
`

View file

@ -0,0 +1,54 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"path/filepath"
"k8s.io/gengo/args"
"k8s.io/kubernetes/cmd/libs/go2idl/informer-gen/generators"
"github.com/golang/glog"
"github.com/spf13/pflag"
)
func main() {
customArgs := &generators.CustomArgs{
VersionedClientSetPackage: "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5",
InternalClientSetPackage: "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset",
ListersPackage: "k8s.io/kubernetes/pkg/client/listers",
}
arguments := &args.GeneratorArgs{
OutputBase: args.DefaultSourceTree(),
GoHeaderFilePath: filepath.Join(args.DefaultSourceTree(), "k8s.io/kubernetes/hack/boilerplate/boilerplate.go.txt"),
GeneratedBuildTag: "ignore_autogenerated",
OutputPackagePath: "k8s.io/kubernetes/pkg/client/informers/informers_generated",
CustomArgs: customArgs,
}
arguments.AddFlags(pflag.CommandLine)
customArgs.AddFlags(pflag.CommandLine)
// Run it.
if err := arguments.Execute(
generators.NameSystems(),
generators.DefaultNameSystem(),
generators.Packages,
); err != nil {
glog.Fatalf("Error: %v", err)
}
glog.V(2).Info("Completed successfully.")
}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1,23 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_binary(
name = "lister-gen",
srcs = ["main.go"],
tags = ["automanaged"],
deps = [
"//cmd/libs/go2idl/lister-gen/generators:go_default_library",
"//vendor:github.com/golang/glog",
"//vendor:github.com/spf13/pflag",
"//vendor:k8s.io/gengo/args",
],
)

View file

@ -0,0 +1,30 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
"go_test",
"cgo_library",
)
go_library(
name = "go_default_library",
srcs = [
"expansion.go",
"lister.go",
"tags.go",
],
tags = ["automanaged"],
deps = [
"//cmd/libs/go2idl/client-gen/types:go_default_library",
"//vendor:github.com/golang/glog",
"//vendor:github.com/spf13/pflag",
"//vendor:k8s.io/gengo/args",
"//vendor:k8s.io/gengo/generator",
"//vendor:k8s.io/gengo/namer",
"//vendor:k8s.io/gengo/types",
],
)

View file

@ -0,0 +1,65 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package generators
import (
"io"
"os"
"path/filepath"
"strings"
"k8s.io/gengo/generator"
"k8s.io/gengo/types"
)
// expansionGenerator produces a file for a expansion interfaces.
type expansionGenerator struct {
generator.DefaultGen
packagePath string
types []*types.Type
}
// We only want to call GenerateType() once per group.
func (g *expansionGenerator) Filter(c *generator.Context, t *types.Type) bool {
return t == g.types[0]
}
func (g *expansionGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
sw := generator.NewSnippetWriter(w, c, "$", "$")
for _, t := range g.types {
if _, err := os.Stat(filepath.Join(g.packagePath, strings.ToLower(t.Name.Name+"_expansion.go"))); os.IsNotExist(err) {
sw.Do(expansionInterfaceTemplate, t)
namespaced := !extractBoolTagOrDie("nonNamespaced", t.SecondClosestCommentLines)
if namespaced {
sw.Do(namespacedExpansionInterfaceTemplate, t)
}
}
}
return sw.Error()
}
var expansionInterfaceTemplate = `
// $.|public$ListerExpansion allows custom methods to be added to
// $.|public$Lister.
type $.|public$ListerExpansion interface {}
`
var namespacedExpansionInterfaceTemplate = `
// $.|public$NamespaceListerExpansion allows custom methods to be added to
// $.|public$NamespaeLister.
type $.|public$NamespaceListerExpansion interface {}
`

View file

@ -0,0 +1,370 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package generators
import (
"fmt"
"io"
"path/filepath"
"strings"
"k8s.io/gengo/args"
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
clientgentypes "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/types"
"github.com/golang/glog"
"github.com/spf13/pflag"
)
// NameSystems returns the name system used by the generators in this package.
func NameSystems() namer.NameSystems {
pluralExceptions := map[string]string{
"Endpoints": "Endpoints",
}
return namer.NameSystems{
"public": namer.NewPublicNamer(0),
"private": namer.NewPrivateNamer(0),
"raw": namer.NewRawNamer("", nil),
"publicPlural": namer.NewPublicPluralNamer(pluralExceptions),
"allLowercasePlural": namer.NewAllLowercasePluralNamer(pluralExceptions),
"lowercaseSingular": &lowercaseSingularNamer{},
}
}
// lowercaseSingularNamer implements Namer
type lowercaseSingularNamer struct{}
// Name returns t's name in all lowercase.
func (n *lowercaseSingularNamer) Name(t *types.Type) string {
return strings.ToLower(t.Name.Name)
}
// DefaultNameSystem returns the default name system for ordering the types to be
// processed by the generators in this package.
func DefaultNameSystem() string {
return "public"
}
// generatedBy returns information about the arguments used to invoke
// lister-gen.
func generatedBy() string {
var cmdArgs string
pflag.VisitAll(func(f *pflag.Flag) {
if !f.Changed || f.Name == "verify-only" {
return
}
cmdArgs += fmt.Sprintf("--%s=%s ", f.Name, f.Value)
})
return fmt.Sprintf("\n// This file was automatically generated by lister-gen with arguments: %s\n\n", cmdArgs)
}
// Packages makes the client package definition.
func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
boilerplate, err := arguments.LoadGoBoilerplate()
if err != nil {
glog.Fatalf("Failed loading boilerplate: %v", err)
}
boilerplate = append(boilerplate, []byte(generatedBy())...)
var packageList generator.Packages
for _, inputDir := range arguments.InputDirs {
p := context.Universe.Package(inputDir)
objectMeta, err := objectMetaForPackage(p)
if err != nil {
glog.Fatal(err)
}
if objectMeta == nil {
// no types in this package had genclient
continue
}
var gv clientgentypes.GroupVersion
var internalGVPkg string
if isInternal(objectMeta) {
lastSlash := strings.LastIndex(p.Path, "/")
if lastSlash == -1 {
glog.Fatalf("error constructing internal group version for package %q", p.Path)
}
gv.Group = clientgentypes.Group(p.Path[lastSlash+1:])
internalGVPkg = p.Path
} else {
parts := strings.Split(p.Path, "/")
gv.Group = clientgentypes.Group(parts[len(parts)-2])
gv.Version = clientgentypes.Version(parts[len(parts)-1])
internalGVPkg = strings.Join(parts[0:len(parts)-1], "/")
}
var typesToGenerate []*types.Type
for _, t := range p.Types {
// filter out types which dont have genclient=true.
if extractBoolTagOrDie("genclient", t.SecondClosestCommentLines) == false {
continue
}
typesToGenerate = append(typesToGenerate, t)
}
orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)}
typesToGenerate = orderer.OrderTypes(typesToGenerate)
packagePath := filepath.Join(arguments.OutputPackagePath, strings.ToLower(gv.Group.NonEmpty()), strings.ToLower(gv.Version.NonEmpty()))
packageList = append(packageList, &generator.DefaultPackage{
PackageName: strings.ToLower(gv.Version.NonEmpty()),
PackagePath: packagePath,
HeaderText: boilerplate,
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
generators = append(generators, &expansionGenerator{
DefaultGen: generator.DefaultGen{
OptionalName: "expansion_generated",
},
packagePath: filepath.Join(arguments.OutputBase, packagePath),
types: typesToGenerate,
})
for _, t := range typesToGenerate {
generators = append(generators, &listerGenerator{
DefaultGen: generator.DefaultGen{
OptionalName: strings.ToLower(t.Name.Name),
},
outputPackage: arguments.OutputPackagePath,
groupVersion: gv,
internalGVPkg: internalGVPkg,
typeToGenerate: t,
imports: generator.NewImportTracker(),
objectMeta: objectMeta,
})
}
return generators
},
FilterFunc: func(c *generator.Context, t *types.Type) bool {
// piggy-back on types that are tagged for client-gen
return extractBoolTagOrDie("genclient", t.SecondClosestCommentLines) == true
},
})
}
return packageList
}
// objectMetaForPackage returns the type of ObjectMeta used by package p.
func objectMetaForPackage(p *types.Package) (*types.Type, error) {
generatingForPackage := false
for _, t := range p.Types {
// filter out types which dont have genclient=true.
if extractBoolTagOrDie("genclient", t.SecondClosestCommentLines) == false {
continue
}
generatingForPackage = true
for _, member := range t.Members {
if member.Name == "ObjectMeta" {
return member.Type, nil
}
}
}
if generatingForPackage {
return nil, fmt.Errorf("unable to find ObjectMeta for any types in package %s", p.Path)
}
return nil, nil
}
// isInternal returns true if t's package is k8s.io/kubernetes/pkg/api.
func isInternal(t *types.Type) bool {
return t.Name.Package == "k8s.io/kubernetes/pkg/api"
}
// listerGenerator produces a file of listers for a given GroupVersion and
// type.
type listerGenerator struct {
generator.DefaultGen
outputPackage string
groupVersion clientgentypes.GroupVersion
internalGVPkg string
typeToGenerate *types.Type
imports namer.ImportTracker
objectMeta *types.Type
}
var _ generator.Generator = &listerGenerator{}
func (g *listerGenerator) Filter(c *generator.Context, t *types.Type) bool {
return t == g.typeToGenerate
}
func (g *listerGenerator) Namers(c *generator.Context) namer.NameSystems {
return namer.NameSystems{
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
}
}
func (g *listerGenerator) Imports(c *generator.Context) (imports []string) {
imports = append(imports, g.imports.ImportLines()...)
imports = append(imports, "k8s.io/kubernetes/pkg/api/errors")
imports = append(imports, "k8s.io/kubernetes/pkg/labels")
// for Indexer
imports = append(imports, "k8s.io/kubernetes/pkg/client/cache")
return
}
func (g *listerGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
sw := generator.NewSnippetWriter(w, c, "$", "$")
glog.V(5).Infof("processing type %v", t)
m := map[string]interface{}{
"Resource": c.Universe.Function(types.Name{Package: g.internalGVPkg, Name: "Resource"}),
"type": t,
"objectMeta": g.objectMeta,
}
namespaced := !extractBoolTagOrDie("nonNamespaced", t.SecondClosestCommentLines)
if namespaced {
sw.Do(typeListerInterface, m)
} else {
sw.Do(typeListerInterface_NonNamespaced, m)
}
sw.Do(typeListerStruct, m)
sw.Do(typeListerConstructor, m)
sw.Do(typeLister_List, m)
if namespaced {
sw.Do(typeLister_NamespaceLister, m)
sw.Do(namespaceListerInterface, m)
sw.Do(namespaceListerStruct, m)
sw.Do(namespaceLister_List, m)
sw.Do(namespaceLister_Get, m)
} else {
sw.Do(typeLister_NonNamespacedGet, m)
}
return sw.Error()
}
var typeListerInterface = `
// $.type|public$Lister helps list $.type|publicPlural$.
type $.type|public$Lister interface {
// List lists all $.type|publicPlural$ in the indexer.
List(selector labels.Selector) (ret []*$.type|raw$, err error)
// $.type|publicPlural$ returns an object that can list and get $.type|publicPlural$.
$.type|publicPlural$(namespace string) $.type|public$NamespaceLister
$.type|public$ListerExpansion
}
`
var typeListerInterface_NonNamespaced = `
// $.type|public$Lister helps list $.type|publicPlural$.
type $.type|public$Lister interface {
// List lists all $.type|publicPlural$ in the indexer.
List(selector labels.Selector) (ret []*$.type|raw$, err error)
// Get retrieves the $.type|public$ from the index for a given name.
Get(name string) (*$.type|raw$, error)
$.type|public$ListerExpansion
}
`
var typeListerStruct = `
// $.type|private$Lister implements the $.type|public$Lister interface.
type $.type|private$Lister struct {
indexer cache.Indexer
}
`
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 typeLister_List = `
// 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
}
`
var typeLister_NamespaceLister = `
// $.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 typeLister_NonNamespacedGet = `
// Get retrieves the $.type|public$ from the index for a given name.
func (s *$.type|private$Lister) Get(name string) (*$.type|raw$, error) {
key := &$.type|raw${ObjectMeta: $.objectMeta|raw${Name: name}}
obj, exists, err := s.indexer.Get(key)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound($.Resource|raw$("$.type|lowercaseSingular$"), name)
}
return obj.(*$.type|raw$), nil
}
`
var namespaceListerInterface = `
// $.type|public$NamespaceLister helps list and get $.type|publicPlural$.
type $.type|public$NamespaceLister interface {
// List lists all $.type|publicPlural$ in the indexer for a given namespace.
List(selector labels.Selector) (ret []*$.type|raw$, err error)
// Get retrieves the $.type|public$ from the indexer for a given namespace and name.
Get(name string) (*$.type|raw$, error)
$.type|public$NamespaceListerExpansion
}
`
var namespaceListerStruct = `
// $.type|private$NamespaceLister implements the $.type|public$NamespaceLister
// interface.
type $.type|private$NamespaceLister struct {
indexer cache.Indexer
namespace string
}
`
var namespaceLister_List = `
// 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 namespaceLister_Get = `
// 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
}
`

View file

@ -0,0 +1,33 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package generators
import (
"github.com/golang/glog"
"k8s.io/gengo/types"
)
// extractBoolTagOrDie gets the comment-tags for the key and asserts that, if
// it exists, the value is boolean. If the tag did not exist, it returns
// false.
func extractBoolTagOrDie(key string, lines []string) bool {
val, err := types.ExtractSingleBoolCommentTag("+", key, false, lines)
if err != nil {
glog.Fatalf(err.Error())
}
return val
}

View file

@ -0,0 +1,47 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"path/filepath"
"k8s.io/gengo/args"
"k8s.io/kubernetes/cmd/libs/go2idl/lister-gen/generators"
"github.com/golang/glog"
"github.com/spf13/pflag"
)
func main() {
arguments := &args.GeneratorArgs{
OutputBase: args.DefaultSourceTree(),
GoHeaderFilePath: filepath.Join(args.DefaultSourceTree(), "k8s.io/kubernetes/hack/boilerplate/boilerplate.go.txt"),
GeneratedBuildTag: "ignore_autogenerated",
OutputPackagePath: "k8s.io/kubernetes/pkg/client/listers",
}
arguments.AddFlags(pflag.CommandLine)
// Run it.
if err := arguments.Execute(
generators.NameSystems(),
generators.DefaultNameSystem(),
generators.Packages,
); err != nil {
glog.Fatalf("Error: %v", err)
}
glog.V(2).Info("Completed successfully.")
}

View file

@ -0,0 +1,14 @@
{
"Rules": [
{
"SelectorRegexp": "k8s[.]io",
"AllowedPrefixes": [
"k8s.io/kubernetes/cmd/libs/go2idl",
"k8s.io/kubernetes/pkg/genericapiserver/openapi/common",
"k8s.io/gengo",
"k8s.io/kubernetes/third_party",
"k8s.io/kubernetes/pkg/util/sets"
]
}
]
}

Some files were not shown because too many files have changed in this diff Show more