Custom resource definition
Co-authored-by: Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
This commit is contained in:
parent
cfaf47c8a2
commit
4c060a78cc
1348 changed files with 92364 additions and 55766 deletions
8
vendor/k8s.io/code-generator/cmd/client-gen/OWNERS
generated
vendored
Normal file
8
vendor/k8s.io/code-generator/cmd/client-gen/OWNERS
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
approvers:
|
||||
- lavalamp
|
||||
- wojtek-t
|
||||
- caesarxuchao
|
||||
reviewers:
|
||||
- lavalamp
|
||||
- wojtek-t
|
||||
- caesarxuchao
|
4
vendor/k8s.io/code-generator/cmd/client-gen/README.md
generated
vendored
Normal file
4
vendor/k8s.io/code-generator/cmd/client-gen/README.md
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
See [generating-clientset.md](https://git.k8s.io/community/contributors/devel/generating-clientset.md)
|
||||
|
||||
|
||||
[]()
|
120
vendor/k8s.io/code-generator/cmd/client-gen/args/args.go
generated
vendored
Normal file
120
vendor/k8s.io/code-generator/cmd/client-gen/args/args.go
generated
vendored
Normal file
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
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 (
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/gengo/args"
|
||||
|
||||
"k8s.io/code-generator/cmd/client-gen/types"
|
||||
codegenutil "k8s.io/code-generator/pkg/util"
|
||||
)
|
||||
|
||||
var DefaultInputDirs = []string{}
|
||||
|
||||
// ClientGenArgs is a wrapper for arguments to client-gen.
|
||||
type CustomArgs struct {
|
||||
// A sorted list of group versions to generate. For each of them the package path is found
|
||||
// in GroupVersionToInputPath.
|
||||
Groups []types.GroupVersions
|
||||
|
||||
// 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
|
||||
// ClientsetAPIPath is the default API HTTP 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
|
||||
}
|
||||
|
||||
func NewDefaults() (*args.GeneratorArgs, *CustomArgs) {
|
||||
genericArgs := args.Default().WithoutDefaultFlagParsing()
|
||||
customArgs := &CustomArgs{
|
||||
ClientsetName: "internalclientset",
|
||||
ClientsetAPIPath: "/apis",
|
||||
ClientsetOnly: false,
|
||||
FakeClient: true,
|
||||
}
|
||||
genericArgs.CustomArgs = customArgs
|
||||
genericArgs.InputDirs = DefaultInputDirs
|
||||
|
||||
if pkg := codegenutil.CurrentPackage(); len(pkg) != 0 {
|
||||
genericArgs.OutputPackagePath = path.Join(pkg, "pkg/client/clientset")
|
||||
}
|
||||
|
||||
return genericArgs, customArgs
|
||||
}
|
||||
|
||||
func (ca *CustomArgs) AddFlags(fs *pflag.FlagSet, inputBase string) {
|
||||
gvsBuilder := NewGroupVersionsBuilder(&ca.Groups)
|
||||
pflag.Var(NewGVPackagesValue(gvsBuilder, nil), "input", "group/versions that client-gen will generate clients for. At most one version per group is allowed. Specified in the format \"group1/version1,group2/version2...\".")
|
||||
pflag.Var(NewGVTypesValue(&ca.IncludedTypesOverrides, []string{}), "included-types-overrides", "list of group/version/type for which client should be generated. By default, client is generated for all types which have genclient in types.go. This overrides that. For each groupVersion in this list, only the types mentioned here will be included. The default check of genclient will be used for other group versions.")
|
||||
pflag.Var(NewInputBasePathValue(gvsBuilder, inputBase), "input-base", "base path to look for the api group.")
|
||||
pflag.StringVarP(&ca.ClientsetName, "clientset-name", "n", ca.ClientsetName, "the name of the generated clientset package.")
|
||||
pflag.StringVarP(&ca.ClientsetAPIPath, "clientset-api-path", "", ca.ClientsetAPIPath, "the value of default API HTTP path, starting with / and without trailing /.")
|
||||
pflag.BoolVar(&ca.ClientsetOnly, "clientset-only", ca.ClientsetOnly, "when set, client-gen only generates the clientset shell, without generating the individual typed clients")
|
||||
pflag.BoolVar(&ca.FakeClient, "fake-clientset", ca.FakeClient, "when set, client-gen will generate the fake clientset that can be used in tests")
|
||||
|
||||
// support old flags
|
||||
fs.SetNormalizeFunc(mapFlagName("clientset-path", "output-package", fs.GetNormalizeFunc()))
|
||||
}
|
||||
|
||||
func Validate(genericArgs *args.GeneratorArgs) error {
|
||||
customArgs := genericArgs.CustomArgs.(*CustomArgs)
|
||||
|
||||
if len(genericArgs.OutputPackagePath) == 0 {
|
||||
return fmt.Errorf("output package cannot be empty")
|
||||
}
|
||||
if len(customArgs.ClientsetName) == 0 {
|
||||
return fmt.Errorf("clientset name cannot be empty")
|
||||
}
|
||||
if len(customArgs.ClientsetAPIPath) == 0 {
|
||||
return fmt.Errorf("clientset API path cannot be empty")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GroupVersionPackages returns a map from GroupVersion to the package with the types.go.
|
||||
func (ca *CustomArgs) GroupVersionPackages() map[types.GroupVersion]string {
|
||||
res := map[types.GroupVersion]string{}
|
||||
for _, pkg := range ca.Groups {
|
||||
for _, v := range pkg.Versions {
|
||||
res[types.GroupVersion{Group: pkg.Group, Version: v.Version}] = v.Package
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func mapFlagName(from, to string, old func(fs *pflag.FlagSet, name string) pflag.NormalizedName) func(fs *pflag.FlagSet, name string) pflag.NormalizedName {
|
||||
return func(fs *pflag.FlagSet, name string) pflag.NormalizedName {
|
||||
if name == from {
|
||||
name = to
|
||||
}
|
||||
return old(fs, name)
|
||||
}
|
||||
}
|
183
vendor/k8s.io/code-generator/cmd/client-gen/args/gvpackages.go
generated
vendored
Normal file
183
vendor/k8s.io/code-generator/cmd/client-gen/args/gvpackages.go
generated
vendored
Normal file
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package args
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/csv"
|
||||
"flag"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/code-generator/cmd/client-gen/types"
|
||||
)
|
||||
|
||||
type inputBasePathValue struct {
|
||||
builder *groupVersionsBuilder
|
||||
}
|
||||
|
||||
var _ flag.Value = &inputBasePathValue{}
|
||||
|
||||
func NewInputBasePathValue(builder *groupVersionsBuilder, def string) *inputBasePathValue {
|
||||
v := &inputBasePathValue{
|
||||
builder: builder,
|
||||
}
|
||||
v.Set(def)
|
||||
return v
|
||||
}
|
||||
|
||||
func (s *inputBasePathValue) Set(val string) error {
|
||||
s.builder.importBasePath = val
|
||||
return s.builder.update()
|
||||
}
|
||||
|
||||
func (s *inputBasePathValue) Type() string {
|
||||
return "string"
|
||||
}
|
||||
|
||||
func (s *inputBasePathValue) String() string {
|
||||
return s.builder.importBasePath
|
||||
}
|
||||
|
||||
type gvPackagesValue struct {
|
||||
builder *groupVersionsBuilder
|
||||
groups []string
|
||||
changed bool
|
||||
}
|
||||
|
||||
func NewGVPackagesValue(builder *groupVersionsBuilder, def []string) *gvPackagesValue {
|
||||
gvp := new(gvPackagesValue)
|
||||
gvp.builder = builder
|
||||
if def != nil {
|
||||
if err := gvp.set(def); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
return gvp
|
||||
}
|
||||
|
||||
var _ flag.Value = &gvPackagesValue{}
|
||||
|
||||
func (s *gvPackagesValue) set(vs []string) error {
|
||||
if s.changed {
|
||||
s.groups = append(s.groups, vs...)
|
||||
} else {
|
||||
s.groups = append([]string(nil), vs...)
|
||||
}
|
||||
|
||||
s.builder.groups = s.groups
|
||||
return s.builder.update()
|
||||
}
|
||||
|
||||
func (s *gvPackagesValue) Set(val string) error {
|
||||
vs, err := readAsCSV(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.set(vs); err != nil {
|
||||
return err
|
||||
}
|
||||
s.changed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *gvPackagesValue) Type() string {
|
||||
return "stringSlice"
|
||||
}
|
||||
|
||||
func (s *gvPackagesValue) String() string {
|
||||
str, _ := writeAsCSV(s.groups)
|
||||
return "[" + str + "]"
|
||||
}
|
||||
|
||||
type groupVersionsBuilder struct {
|
||||
value *[]types.GroupVersions
|
||||
groups []string
|
||||
importBasePath string
|
||||
}
|
||||
|
||||
func NewGroupVersionsBuilder(groups *[]types.GroupVersions) *groupVersionsBuilder {
|
||||
return &groupVersionsBuilder{
|
||||
value: groups,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *groupVersionsBuilder) update() error {
|
||||
var seenGroups = make(map[types.Group]*types.GroupVersions)
|
||||
for _, v := range p.groups {
|
||||
pth, gvString := parsePathGroupVersion(v)
|
||||
gv, err := types.ToGroupVersion(gvString)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
versionPkg := types.PackageVersion{Package: path.Join(p.importBasePath, pth, gv.Group.NonEmpty(), gv.Version.String()), Version: gv.Version}
|
||||
if group, ok := seenGroups[gv.Group]; ok {
|
||||
seenGroups[gv.Group].Versions = append(group.Versions, versionPkg)
|
||||
} else {
|
||||
seenGroups[gv.Group] = &types.GroupVersions{
|
||||
PackageName: gv.Group.NonEmpty(),
|
||||
Group: gv.Group,
|
||||
Versions: []types.PackageVersion{versionPkg},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var groupNames []string
|
||||
for groupName := range seenGroups {
|
||||
groupNames = append(groupNames, groupName.String())
|
||||
}
|
||||
sort.Strings(groupNames)
|
||||
*p.value = []types.GroupVersions{}
|
||||
for _, groupName := range groupNames {
|
||||
*p.value = append(*p.value, *seenGroups[types.Group(groupName)])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
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 readAsCSV(val string) ([]string, error) {
|
||||
if val == "" {
|
||||
return []string{}, nil
|
||||
}
|
||||
stringReader := strings.NewReader(val)
|
||||
csvReader := csv.NewReader(stringReader)
|
||||
return csvReader.Read()
|
||||
}
|
||||
|
||||
func writeAsCSV(vals []string) (string, error) {
|
||||
b := &bytes.Buffer{}
|
||||
w := csv.NewWriter(b)
|
||||
err := w.Write(vals)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
w.Flush()
|
||||
return strings.TrimSuffix(b.String(), "\n"), nil
|
||||
}
|
110
vendor/k8s.io/code-generator/cmd/client-gen/args/gvtype.go
generated
vendored
Normal file
110
vendor/k8s.io/code-generator/cmd/client-gen/args/gvtype.go
generated
vendored
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package args
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"k8s.io/code-generator/cmd/client-gen/types"
|
||||
)
|
||||
|
||||
type gvTypeValue struct {
|
||||
gvToTypes *map[types.GroupVersion][]string
|
||||
changed bool
|
||||
}
|
||||
|
||||
func NewGVTypesValue(gvToTypes *map[types.GroupVersion][]string, def []string) *gvTypeValue {
|
||||
gvt := new(gvTypeValue)
|
||||
gvt.gvToTypes = gvToTypes
|
||||
if def != nil {
|
||||
if err := gvt.set(def); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
return gvt
|
||||
}
|
||||
|
||||
var _ flag.Value = &gvTypeValue{}
|
||||
|
||||
func (s *gvTypeValue) set(vs []string) error {
|
||||
if !s.changed {
|
||||
*s.gvToTypes = map[types.GroupVersion][]string{}
|
||||
}
|
||||
|
||||
for _, input := range vs {
|
||||
gvString, typeStr, err := parseGroupVersionType(input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
gv, err := types.ToGroupVersion(gvString)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
types, ok := (*s.gvToTypes)[gv]
|
||||
if !ok {
|
||||
types = []string{}
|
||||
}
|
||||
types = append(types, typeStr)
|
||||
(*s.gvToTypes)[gv] = types
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *gvTypeValue) Set(val string) error {
|
||||
vs, err := readAsCSV(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.set(vs); err != nil {
|
||||
return err
|
||||
}
|
||||
s.changed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *gvTypeValue) Type() string {
|
||||
return "stringSlice"
|
||||
}
|
||||
|
||||
func (s *gvTypeValue) String() string {
|
||||
strs := make([]string, 0, len(*s.gvToTypes))
|
||||
for gv, ts := range *s.gvToTypes {
|
||||
for _, t := range ts {
|
||||
strs = append(strs, gv.Group.String()+"/"+gv.Version.String()+"/"+t)
|
||||
}
|
||||
}
|
||||
str, _ := writeAsCSV(strs)
|
||||
return "[" + str + "]"
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
426
vendor/k8s.io/code-generator/cmd/client-gen/generators/client_generator.go
generated
vendored
Normal file
426
vendor/k8s.io/code-generator/cmd/client-gen/generators/client_generator.go
generated
vendored
Normal file
|
@ -0,0 +1,426 @@
|
|||
/*
|
||||
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 (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
clientgenargs "k8s.io/code-generator/cmd/client-gen/args"
|
||||
"k8s.io/code-generator/cmd/client-gen/generators/fake"
|
||||
"k8s.io/code-generator/cmd/client-gen/generators/scheme"
|
||||
"k8s.io/code-generator/cmd/client-gen/generators/util"
|
||||
"k8s.io/code-generator/cmd/client-gen/path"
|
||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||
"k8s.io/gengo/args"
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/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",
|
||||
}
|
||||
lowercaseNamer := namer.NewAllLowercasePluralNamer(pluralExceptions)
|
||||
|
||||
publicNamer := &ExceptionNamer{
|
||||
Exceptions: map[string]string{
|
||||
// these exceptions are used to deconflict the generated code
|
||||
// you can put your fully qualified package like
|
||||
// to generate a name that doesn't conflict with your group.
|
||||
// "k8s.io/apis/events/v1beta1.Event": "EventResource"
|
||||
},
|
||||
KeyFunc: func(t *types.Type) string {
|
||||
return t.Name.Package + "." + t.Name.Name
|
||||
},
|
||||
Delegate: namer.NewPublicNamer(0),
|
||||
}
|
||||
privateNamer := &ExceptionNamer{
|
||||
Exceptions: map[string]string{
|
||||
// these exceptions are used to deconflict the generated code
|
||||
// you can put your fully qualified package like
|
||||
// to generate a name that doesn't conflict with your group.
|
||||
// "k8s.io/apis/events/v1beta1.Event": "eventResource"
|
||||
},
|
||||
KeyFunc: func(t *types.Type) string {
|
||||
return t.Name.Package + "." + t.Name.Name
|
||||
},
|
||||
Delegate: namer.NewPrivateNamer(0),
|
||||
}
|
||||
publicPluralNamer := &ExceptionNamer{
|
||||
Exceptions: map[string]string{
|
||||
// these exceptions are used to deconflict the generated code
|
||||
// you can put your fully qualified package like
|
||||
// to generate a name that doesn't conflict with your group.
|
||||
// "k8s.io/apis/events/v1beta1.Event": "EventResource"
|
||||
},
|
||||
KeyFunc: func(t *types.Type) string {
|
||||
return t.Name.Package + "." + t.Name.Name
|
||||
},
|
||||
Delegate: namer.NewPublicPluralNamer(pluralExceptions),
|
||||
}
|
||||
privatePluralNamer := &ExceptionNamer{
|
||||
Exceptions: map[string]string{
|
||||
// you can put your fully qualified package like
|
||||
// to generate a name that doesn't conflict with your group.
|
||||
// "k8s.io/apis/events/v1beta1.Event": "eventResource"
|
||||
// these exceptions are used to deconflict the generated code
|
||||
"k8s.io/apis/events/v1beta1.Event": "eventResources",
|
||||
"k8s.io/kubernetes/pkg/apis/events.Event": "eventResources",
|
||||
},
|
||||
KeyFunc: func(t *types.Type) string {
|
||||
return t.Name.Package + "." + t.Name.Name
|
||||
},
|
||||
Delegate: namer.NewPrivatePluralNamer(pluralExceptions),
|
||||
}
|
||||
|
||||
return namer.NameSystems{
|
||||
"singularKind": namer.NewPublicNamer(0),
|
||||
"public": publicNamer,
|
||||
"private": privateNamer,
|
||||
"raw": namer.NewRawNamer("", nil),
|
||||
"publicPlural": publicPluralNamer,
|
||||
"privatePlural": privatePluralNamer,
|
||||
"allLowercasePlural": lowercaseNamer,
|
||||
"resource": NewTagOverrideNamer("resourceName", lowercaseNamer),
|
||||
}
|
||||
}
|
||||
|
||||
// ExceptionNamer allows you specify exceptional cases with exact names. This allows you to have control
|
||||
// for handling various conflicts, like group and resource names for instance.
|
||||
type ExceptionNamer struct {
|
||||
Exceptions map[string]string
|
||||
KeyFunc func(*types.Type) string
|
||||
|
||||
Delegate namer.Namer
|
||||
}
|
||||
|
||||
// Name provides the requested name for a type.
|
||||
func (n *ExceptionNamer) Name(t *types.Type) string {
|
||||
key := n.KeyFunc(t)
|
||||
if exception, ok := n.Exceptions[key]; ok {
|
||||
return exception
|
||||
}
|
||||
return n.Delegate.Name(t)
|
||||
}
|
||||
|
||||
// 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 packageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, clientsetPackage string, groupPackageName string, groupGoName string, apiPath string, srcTreePath string, inputPackage string, boilerplate []byte) generator.Package {
|
||||
groupVersionClientPackage := strings.ToLower(filepath.Join(clientsetPackage, "typed", groupPackageName, gv.Version.NonEmpty()))
|
||||
return &generator.DefaultPackage{
|
||||
PackageName: strings.ToLower(gv.Version.NonEmpty()),
|
||||
PackagePath: groupVersionClientPackage,
|
||||
HeaderText: boilerplate,
|
||||
PackageDocumentation: []byte(
|
||||
`// This package has the automatically generated typed clients.
|
||||
`),
|
||||
// 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: groupVersionClientPackage,
|
||||
clientsetPackage: clientsetPackage,
|
||||
group: gv.Group.NonEmpty(),
|
||||
version: gv.Version.String(),
|
||||
groupGoName: groupGoName,
|
||||
typeToMatch: t,
|
||||
imports: generator.NewImportTracker(),
|
||||
})
|
||||
}
|
||||
|
||||
generators = append(generators, &genGroup{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: groupPackageName + "_client",
|
||||
},
|
||||
outputPackage: groupVersionClientPackage,
|
||||
inputPackage: inputPackage,
|
||||
clientsetPackage: clientsetPackage,
|
||||
group: gv.Group.NonEmpty(),
|
||||
version: gv.Version.String(),
|
||||
groupGoName: groupGoName,
|
||||
apiPath: apiPath,
|
||||
types: typeList,
|
||||
imports: generator.NewImportTracker(),
|
||||
})
|
||||
|
||||
expansionFileName := "generated_expansion"
|
||||
generators = append(generators, &genExpansion{
|
||||
groupPackagePath: filepath.Join(srcTreePath, groupVersionClientPackage),
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: expansionFileName,
|
||||
},
|
||||
types: typeList,
|
||||
})
|
||||
|
||||
return generators
|
||||
},
|
||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||
return util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)).GenerateClient
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func packageForClientset(customArgs *clientgenargs.CustomArgs, clientsetPackage string, groupGoNames map[clientgentypes.GroupVersion]string, boilerplate []byte) generator.Package {
|
||||
return &generator.DefaultPackage{
|
||||
PackageName: customArgs.ClientsetName,
|
||||
PackagePath: clientsetPackage,
|
||||
HeaderText: boilerplate,
|
||||
PackageDocumentation: []byte(
|
||||
`// 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,
|
||||
groupGoNames: groupGoNames,
|
||||
clientsetPackage: clientsetPackage,
|
||||
outputPackage: customArgs.ClientsetName,
|
||||
imports: generator.NewImportTracker(),
|
||||
},
|
||||
}
|
||||
return generators
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func packageForScheme(customArgs *clientgenargs.CustomArgs, clientsetPackage string, srcTreePath string, groupGoNames map[clientgentypes.GroupVersion]string, boilerplate []byte) generator.Package {
|
||||
schemePackage := filepath.Join(clientsetPackage, "scheme")
|
||||
|
||||
// create runtime.Registry for internal client because it has to know about group versions
|
||||
internalClient := false
|
||||
NextGroup:
|
||||
for _, group := range customArgs.Groups {
|
||||
for _, v := range group.Versions {
|
||||
if v.String() == "" {
|
||||
internalClient = true
|
||||
break NextGroup
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &generator.DefaultPackage{
|
||||
PackageName: "scheme",
|
||||
PackagePath: schemePackage,
|
||||
HeaderText: boilerplate,
|
||||
PackageDocumentation: []byte(
|
||||
`// This package contains the scheme of 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"},
|
||||
|
||||
&scheme.GenScheme{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: "register",
|
||||
},
|
||||
InputPackages: customArgs.GroupVersionPackages(),
|
||||
OutputPackage: schemePackage,
|
||||
OutputPath: filepath.Join(srcTreePath, schemePackage),
|
||||
Groups: customArgs.Groups,
|
||||
GroupGoNames: groupGoNames,
|
||||
ImportTracker: generator.NewImportTracker(),
|
||||
CreateRegistry: internalClient,
|
||||
},
|
||||
}
|
||||
return generators
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// applyGroupOverrides applies group name overrides to each package, if applicable. If there is a
|
||||
// comment of the form "// +groupName=somegroup" or "// +groupName=somegroup.foo.bar.io", use the
|
||||
// first field (somegroup) as the name of the group in Go code, e.g. as the func name in a clientset.
|
||||
//
|
||||
// If the first field of the groupName is not unique within the clientset, use "// +groupName=unique
|
||||
func applyGroupOverrides(universe types.Universe, customArgs *clientgenargs.CustomArgs) {
|
||||
// Create a map from "old GV" to "new GV" so we know what changes we need to make.
|
||||
changes := make(map[clientgentypes.GroupVersion]clientgentypes.GroupVersion)
|
||||
for gv, inputDir := range customArgs.GroupVersionPackages() {
|
||||
p := universe.Package(inputDir)
|
||||
if override := types.ExtractCommentTags("+", p.Comments)["groupName"]; override != nil {
|
||||
newGV := clientgentypes.GroupVersion{
|
||||
Group: clientgentypes.Group(override[0]),
|
||||
Version: gv.Version,
|
||||
}
|
||||
changes[gv] = newGV
|
||||
}
|
||||
}
|
||||
|
||||
// Modify customArgs.Groups based on the groupName overrides.
|
||||
newGroups := make([]clientgentypes.GroupVersions, 0, len(customArgs.Groups))
|
||||
for _, gvs := range customArgs.Groups {
|
||||
gv := clientgentypes.GroupVersion{
|
||||
Group: gvs.Group,
|
||||
Version: gvs.Versions[0].Version, // we only need a version, and the first will do
|
||||
}
|
||||
if newGV, ok := changes[gv]; ok {
|
||||
// There's an override, so use it.
|
||||
newGVS := clientgentypes.GroupVersions{
|
||||
PackageName: gvs.PackageName,
|
||||
Group: newGV.Group,
|
||||
Versions: gvs.Versions,
|
||||
}
|
||||
newGroups = append(newGroups, newGVS)
|
||||
} else {
|
||||
// No override.
|
||||
newGroups = append(newGroups, gvs)
|
||||
}
|
||||
}
|
||||
customArgs.Groups = newGroups
|
||||
}
|
||||
|
||||
// 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.CustomArgs)
|
||||
if !ok {
|
||||
glog.Fatalf("cannot convert arguments.CustomArgs to clientgenargs.CustomArgs")
|
||||
}
|
||||
includedTypesOverrides := customArgs.IncludedTypesOverrides
|
||||
|
||||
applyGroupOverrides(context.Universe, customArgs)
|
||||
|
||||
gvToTypes := map[clientgentypes.GroupVersion][]*types.Type{}
|
||||
groupGoNames := make(map[clientgentypes.GroupVersion]string)
|
||||
for gv, inputDir := range customArgs.GroupVersionPackages() {
|
||||
p := context.Universe.Package(path.Vendorless(inputDir))
|
||||
|
||||
// If there's a comment of the form "// +groupGoName=SomeUniqueShortName", use that as
|
||||
// the Go group identifier in CamelCase. It defaults
|
||||
groupGoNames[gv] = namer.IC(strings.Split(gv.Group.NonEmpty(), ".")[0])
|
||||
if override := types.ExtractCommentTags("+", p.Comments)["groupGoName"]; override != nil {
|
||||
groupGoNames[gv] = namer.IC(override[0])
|
||||
}
|
||||
|
||||
// Package are indexed with the vendor prefix stripped
|
||||
for n, t := range p.Types {
|
||||
// filter out types which are not included in user specified overrides.
|
||||
typesOverride, ok := includedTypesOverrides[gv]
|
||||
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.
|
||||
if tags := util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)); !tags.GenerateClient {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if _, found := gvToTypes[gv]; !found {
|
||||
gvToTypes[gv] = []*types.Type{}
|
||||
}
|
||||
gvToTypes[gv] = append(gvToTypes[gv], t)
|
||||
}
|
||||
}
|
||||
|
||||
var packageList []generator.Package
|
||||
clientsetPackage := filepath.Join(arguments.OutputPackagePath, customArgs.ClientsetName)
|
||||
|
||||
packageList = append(packageList, packageForClientset(customArgs, clientsetPackage, groupGoNames, boilerplate))
|
||||
packageList = append(packageList, packageForScheme(customArgs, clientsetPackage, arguments.OutputBase, groupGoNames, boilerplate))
|
||||
if customArgs.FakeClient {
|
||||
packageList = append(packageList, fake.PackageForClientset(customArgs, clientsetPackage, groupGoNames, boilerplate))
|
||||
}
|
||||
|
||||
// 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)}
|
||||
gvPackages := customArgs.GroupVersionPackages()
|
||||
for _, group := range customArgs.Groups {
|
||||
for _, version := range group.Versions {
|
||||
gv := clientgentypes.GroupVersion{Group: group.Group, Version: version.Version}
|
||||
types := gvToTypes[gv]
|
||||
inputPath := gvPackages[gv]
|
||||
packageList = append(packageList, packageForGroup(gv, orderer.OrderTypes(types), clientsetPackage, group.PackageName, groupGoNames[gv], customArgs.ClientsetAPIPath, arguments.OutputBase, inputPath, boilerplate))
|
||||
if customArgs.FakeClient {
|
||||
packageList = append(packageList, fake.PackageForGroup(gv, orderer.OrderTypes(types), clientsetPackage, group.PackageName, groupGoNames[gv], inputPath, boilerplate))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return generator.Packages(packageList)
|
||||
}
|
||||
|
||||
// tagOverrideNamer is a namer which pulls names from a given tag, if specified,
|
||||
// and otherwise falls back to a different namer.
|
||||
type tagOverrideNamer struct {
|
||||
tagName string
|
||||
fallback namer.Namer
|
||||
}
|
||||
|
||||
func (n *tagOverrideNamer) Name(t *types.Type) string {
|
||||
if nameOverride := extractTag(n.tagName, append(t.SecondClosestCommentLines, t.CommentLines...)); nameOverride != "" {
|
||||
return nameOverride
|
||||
}
|
||||
|
||||
return n.fallback.Name(t)
|
||||
}
|
||||
|
||||
// NewTagOverrideNamer creates a namer.Namer which uses the contents of the given tag as
|
||||
// the name, or falls back to another Namer if the tag is not present.
|
||||
func NewTagOverrideNamer(tagName string, fallback namer.Namer) namer.Namer {
|
||||
return &tagOverrideNamer{
|
||||
tagName: tagName,
|
||||
fallback: fallback,
|
||||
}
|
||||
}
|
130
vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/fake_client_generator.go
generated
vendored
Normal file
130
vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/fake_client_generator.go
generated
vendored
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/types"
|
||||
|
||||
clientgenargs "k8s.io/code-generator/cmd/client-gen/args"
|
||||
scheme "k8s.io/code-generator/cmd/client-gen/generators/scheme"
|
||||
"k8s.io/code-generator/cmd/client-gen/generators/util"
|
||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||
)
|
||||
|
||||
func PackageForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, clientsetPackage string, groupPackageName string, groupGoName string, inputPackage string, boilerplate []byte) generator.Package {
|
||||
outputPackage := strings.ToLower(filepath.Join(clientsetPackage, "typed", groupPackageName, gv.Version.NonEmpty(), "fake"))
|
||||
// TODO: should make this a function, called by here and in client-generator.go
|
||||
realClientPackage := filepath.Join(clientsetPackage, "typed", groupPackageName, gv.Version.NonEmpty())
|
||||
return &generator.DefaultPackage{
|
||||
PackageName: "fake",
|
||||
PackagePath: outputPackage,
|
||||
HeaderText: boilerplate,
|
||||
PackageDocumentation: []byte(
|
||||
`// Package fake has the automatically generated clients.
|
||||
`),
|
||||
// GeneratorFunc returns a list of generators. Each generator makes a
|
||||
// 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: outputPackage,
|
||||
inputPackage: inputPackage,
|
||||
group: gv.Group.NonEmpty(),
|
||||
version: gv.Version.String(),
|
||||
groupGoName: groupGoName,
|
||||
typeToMatch: t,
|
||||
imports: generator.NewImportTracker(),
|
||||
})
|
||||
}
|
||||
|
||||
generators = append(generators, &genFakeForGroup{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: "fake_" + groupPackageName + "_client",
|
||||
},
|
||||
outputPackage: outputPackage,
|
||||
realClientPackage: realClientPackage,
|
||||
group: gv.Group.NonEmpty(),
|
||||
version: gv.Version.String(),
|
||||
groupGoName: groupGoName,
|
||||
types: typeList,
|
||||
imports: generator.NewImportTracker(),
|
||||
})
|
||||
return generators
|
||||
},
|
||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||
return util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)).GenerateClient
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func PackageForClientset(customArgs *clientgenargs.CustomArgs, clientsetPackage string, groupGoNames map[clientgentypes.GroupVersion]string, boilerplate []byte) 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(clientsetPackage, "fake"),
|
||||
HeaderText: boilerplate,
|
||||
PackageDocumentation: []byte(
|
||||
`// 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,
|
||||
groupGoNames: groupGoNames,
|
||||
fakeClientsetPackage: clientsetPackage,
|
||||
outputPackage: "fake",
|
||||
imports: generator.NewImportTracker(),
|
||||
realClientsetPackage: clientsetPackage,
|
||||
},
|
||||
&scheme.GenScheme{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: "register",
|
||||
},
|
||||
InputPackages: customArgs.GroupVersionPackages(),
|
||||
OutputPackage: clientsetPackage,
|
||||
Groups: customArgs.Groups,
|
||||
GroupGoNames: groupGoNames,
|
||||
ImportTracker: generator.NewImportTracker(),
|
||||
PrivateScheme: true,
|
||||
},
|
||||
}
|
||||
return generators
|
||||
},
|
||||
}
|
||||
}
|
173
vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_clientset.go
generated
vendored
Normal file
173
vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_clientset.go
generated
vendored
Normal file
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
)
|
||||
|
||||
// genClientset generates a package for a clientset.
|
||||
type genClientset struct {
|
||||
generator.DefaultGen
|
||||
groups []clientgentypes.GroupVersions
|
||||
groupGoNames map[clientgentypes.GroupVersion]string
|
||||
fakeClientsetPackage string
|
||||
outputPackage string
|
||||
imports namer.ImportTracker
|
||||
clientsetGenerated bool
|
||||
// the import path of the generated real clientset.
|
||||
realClientsetPackage 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 {
|
||||
groupClientPackage := filepath.Join(g.fakeClientsetPackage, "typed", group.PackageName, version.NonEmpty())
|
||||
fakeGroupClientPackage := filepath.Join(groupClientPackage, "fake")
|
||||
|
||||
groupAlias := strings.ToLower(g.groupGoNames[clientgentypes.GroupVersion{Group: group.Group, Version: version.Version}])
|
||||
imports = append(imports, strings.ToLower(fmt.Sprintf("%s%s \"%s\"", groupAlias, version.NonEmpty(), groupClientPackage)))
|
||||
imports = append(imports, strings.ToLower(fmt.Sprintf("fake%s%s \"%s\"", groupAlias, version.NonEmpty(), fakeGroupClientPackage)))
|
||||
}
|
||||
}
|
||||
// the package that has the clientset Interface
|
||||
imports = append(imports, fmt.Sprintf("clientset \"%s\"", g.realClientsetPackage))
|
||||
// imports for the code in commonTemplate
|
||||
imports = append(imports,
|
||||
"k8s.io/client-go/testing",
|
||||
"k8s.io/client-go/discovery",
|
||||
"fakediscovery \"k8s.io/client-go/discovery/fake\"",
|
||||
"k8s.io/apimachinery/pkg/runtime",
|
||||
"k8s.io/apimachinery/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, "$", "$")
|
||||
|
||||
allGroups := clientgentypes.ToGroupVersionInfo(g.groups, g.groupGoNames)
|
||||
|
||||
sw.Do(common, nil)
|
||||
sw.Do(checkImpl, nil)
|
||||
|
||||
for _, group := range allGroups {
|
||||
m := map[string]interface{}{
|
||||
"group": group.Group,
|
||||
"version": group.Version,
|
||||
"PackageAlias": group.PackageAlias,
|
||||
"GroupGoName": group.GroupGoName,
|
||||
"Version": namer.IC(group.Version.String()),
|
||||
}
|
||||
|
||||
sw.Do(clientsetInterfaceImplTemplate, m)
|
||||
// don't generated the default method if generating internalversion clientset
|
||||
if group.IsDefaultVersion && group.Version != "" {
|
||||
sw.Do(clientsetInterfaceDefaultVersionImpl, m)
|
||||
}
|
||||
}
|
||||
|
||||
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 := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
|
||||
for _, obj := range objects {
|
||||
if err := o.Add(obj); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
cs := &Clientset{}
|
||||
cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}
|
||||
cs.AddReactor("*", "*", testing.ObjectReaction(o))
|
||||
cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
|
||||
gvr := action.GetResource()
|
||||
ns := action.GetNamespace()
|
||||
watch, err := o.Watch(gvr, ns)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return true, watch, nil
|
||||
})
|
||||
|
||||
return cs
|
||||
}
|
||||
|
||||
// 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 {
|
||||
testing.Fake
|
||||
discovery *fakediscovery.FakeDiscovery
|
||||
}
|
||||
|
||||
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||
return c.discovery
|
||||
}
|
||||
`
|
||||
|
||||
var checkImpl = `
|
||||
var _ clientset.Interface = &Clientset{}
|
||||
`
|
||||
|
||||
var clientsetInterfaceImplTemplate = `
|
||||
// $.GroupGoName$$.Version$ retrieves the $.GroupGoName$$.Version$Client
|
||||
func (c *Clientset) $.GroupGoName$$.Version$() $.PackageAlias$.$.GroupGoName$$.Version$Interface {
|
||||
return &fake$.PackageAlias$.Fake$.GroupGoName$$.Version${Fake: &c.Fake}
|
||||
}
|
||||
`
|
||||
|
||||
var clientsetInterfaceDefaultVersionImpl = `
|
||||
// $.GroupGoName$ retrieves the $.GroupGoName$$.Version$Client
|
||||
func (c *Clientset) $.GroupGoName$() $.PackageAlias$.$.GroupGoName$$.Version$Interface {
|
||||
return &fake$.PackageAlias$.Fake$.GroupGoName$$.Version${Fake: &c.Fake}
|
||||
}
|
||||
`
|
130
vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_group.go
generated
vendored
Normal file
130
vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_group.go
generated
vendored
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
"k8s.io/code-generator/cmd/client-gen/generators/util"
|
||||
)
|
||||
|
||||
// genFakeForGroup produces a file for a group client, e.g. ExtensionsClient for the extension group.
|
||||
type genFakeForGroup struct {
|
||||
generator.DefaultGen
|
||||
outputPackage string
|
||||
realClientPackage string
|
||||
group string
|
||||
version string
|
||||
groupGoName string
|
||||
// types in this group
|
||||
types []*types.Type
|
||||
imports namer.ImportTracker
|
||||
// If the genGroup has been called. This generator should only execute once.
|
||||
called bool
|
||||
}
|
||||
|
||||
var _ generator.Generator = &genFakeForGroup{}
|
||||
|
||||
// We only want to call GenerateType() once per group.
|
||||
func (g *genFakeForGroup) Filter(c *generator.Context, t *types.Type) bool {
|
||||
if !g.called {
|
||||
g.called = true
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
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 = g.imports.ImportLines()
|
||||
if len(g.types) != 0 {
|
||||
imports = append(imports, strings.ToLower(fmt.Sprintf("%s \"%s\"", filepath.Base(g.realClientPackage), g.realClientPackage)))
|
||||
}
|
||||
return imports
|
||||
}
|
||||
|
||||
func (g *genFakeForGroup) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
|
||||
sw := generator.NewSnippetWriter(w, c, "$", "$")
|
||||
|
||||
m := map[string]interface{}{
|
||||
"GroupGoName": g.groupGoName,
|
||||
"Version": namer.IC(g.version),
|
||||
"Fake": c.Universe.Type(types.Name{Package: "k8s.io/client-go/testing", Name: "Fake"}),
|
||||
"RESTClientInterface": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Interface"}),
|
||||
"RESTClient": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "RESTClient"}),
|
||||
}
|
||||
|
||||
sw.Do(groupClientTemplate, m)
|
||||
for _, t := range g.types {
|
||||
tags, err := util.ParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
wrapper := map[string]interface{}{
|
||||
"type": t,
|
||||
"GroupGoName": g.groupGoName,
|
||||
"Version": namer.IC(g.version),
|
||||
"realClientPackage": strings.ToLower(filepath.Base(g.realClientPackage)),
|
||||
}
|
||||
if tags.NonNamespaced {
|
||||
sw.Do(getterImplNonNamespaced, wrapper)
|
||||
continue
|
||||
}
|
||||
sw.Do(getterImplNamespaced, wrapper)
|
||||
}
|
||||
sw.Do(getRESTClient, m)
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
var groupClientTemplate = `
|
||||
type Fake$.GroupGoName$$.Version$ struct {
|
||||
*$.Fake|raw$
|
||||
}
|
||||
`
|
||||
|
||||
var getterImplNamespaced = `
|
||||
func (c *Fake$.GroupGoName$$.Version$) $.type|publicPlural$(namespace string) $.realClientPackage$.$.type|public$Interface {
|
||||
return &Fake$.type|publicPlural${c, namespace}
|
||||
}
|
||||
`
|
||||
|
||||
var getterImplNonNamespaced = `
|
||||
func (c *Fake$.GroupGoName$$.Version$) $.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$.GroupGoName$$.Version$) RESTClient() $.RESTClientInterface|raw$ {
|
||||
var ret *$.RESTClient|raw$
|
||||
return ret
|
||||
}
|
||||
`
|
479
vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_type.go
generated
vendored
Normal file
479
vendor/k8s.io/code-generator/cmd/client-gen/generators/fake/generator_fake_for_type.go
generated
vendored
Normal file
|
@ -0,0 +1,479 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
"k8s.io/code-generator/cmd/client-gen/generators/util"
|
||||
"k8s.io/code-generator/cmd/client-gen/path"
|
||||
)
|
||||
|
||||
// genFakeForType produces a file for each top-level type.
|
||||
type genFakeForType struct {
|
||||
generator.DefaultGen
|
||||
outputPackage string
|
||||
group string
|
||||
version string
|
||||
groupGoName 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 genStatus to return true if there is a subresource path
|
||||
// registered for "status" in the API server, but we do not have that
|
||||
// information, so genStatus returns true if the type has a status field.
|
||||
func genStatus(t *types.Type) bool {
|
||||
// Default to true if we have a Status member
|
||||
hasStatus := false
|
||||
for _, m := range t.Members {
|
||||
if m.Name == "Status" {
|
||||
hasStatus = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
tags := util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
return hasStatus && !tags.NoStatus
|
||||
}
|
||||
|
||||
// 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)
|
||||
tags, err := util.ParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
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(path.Vendorless(g.inputPackage))
|
||||
if override := types.ExtractCommentTags("+", p.Comments)["groupName"]; override != nil {
|
||||
groupName = override[0]
|
||||
}
|
||||
|
||||
const pkgClientGoTesting = "k8s.io/client-go/testing"
|
||||
m := map[string]interface{}{
|
||||
"type": t,
|
||||
"inputType": t,
|
||||
"resultType": t,
|
||||
"subresourcePath": "",
|
||||
"package": pkg,
|
||||
"Package": namer.IC(pkg),
|
||||
"namespaced": !tags.NonNamespaced,
|
||||
"Group": namer.IC(g.group),
|
||||
"GroupGoName": g.groupGoName,
|
||||
"Version": namer.IC(g.version),
|
||||
"group": canonicalGroup,
|
||||
"groupName": groupName,
|
||||
"version": g.version,
|
||||
"DeleteOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "DeleteOptions"}),
|
||||
"ListOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "ListOptions"}),
|
||||
"GetOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "GetOptions"}),
|
||||
"Everything": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/labels", Name: "Everything"}),
|
||||
"GroupVersionResource": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/schema", Name: "GroupVersionResource"}),
|
||||
"GroupVersionKind": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/schema", Name: "GroupVersionKind"}),
|
||||
"PatchType": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/types", Name: "PatchType"}),
|
||||
"watchInterface": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/watch", Name: "Interface"}),
|
||||
|
||||
"NewRootListAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootListAction"}),
|
||||
"NewListAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewListAction"}),
|
||||
"NewRootGetAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootGetAction"}),
|
||||
"NewGetAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewGetAction"}),
|
||||
"NewRootDeleteAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootDeleteAction"}),
|
||||
"NewDeleteAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewDeleteAction"}),
|
||||
"NewRootDeleteCollectionAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootDeleteCollectionAction"}),
|
||||
"NewDeleteCollectionAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewDeleteCollectionAction"}),
|
||||
"NewRootUpdateAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootUpdateAction"}),
|
||||
"NewUpdateAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewUpdateAction"}),
|
||||
"NewRootCreateAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootCreateAction"}),
|
||||
"NewCreateAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewCreateAction"}),
|
||||
"NewRootWatchAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootWatchAction"}),
|
||||
"NewWatchAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewWatchAction"}),
|
||||
"NewCreateSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewCreateSubresourceAction"}),
|
||||
"NewRootCreateSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootCreateSubresourceAction"}),
|
||||
"NewUpdateSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewUpdateSubresourceAction"}),
|
||||
"NewGetSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewGetSubresourceAction"}),
|
||||
"NewRootGetSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootGetSubresourceAction"}),
|
||||
"NewRootUpdateSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootUpdateSubresourceAction"}),
|
||||
"NewRootPatchAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootPatchAction"}),
|
||||
"NewPatchAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewPatchAction"}),
|
||||
"NewRootPatchSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewRootPatchSubresourceAction"}),
|
||||
"NewPatchSubresourceAction": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "NewPatchSubresourceAction"}),
|
||||
"ExtractFromListOptions": c.Universe.Function(types.Name{Package: pkgClientGoTesting, Name: "ExtractFromListOptions"}),
|
||||
}
|
||||
|
||||
if tags.NonNamespaced {
|
||||
sw.Do(structNonNamespaced, m)
|
||||
} else {
|
||||
sw.Do(structNamespaced, m)
|
||||
}
|
||||
|
||||
if tags.NoVerbs {
|
||||
return sw.Error()
|
||||
}
|
||||
sw.Do(resource, m)
|
||||
sw.Do(kind, m)
|
||||
|
||||
if tags.HasVerb("get") {
|
||||
sw.Do(getTemplate, m)
|
||||
}
|
||||
if tags.HasVerb("list") {
|
||||
if hasObjectMeta(t) {
|
||||
sw.Do(listUsingOptionsTemplate, m)
|
||||
} else {
|
||||
sw.Do(listTemplate, m)
|
||||
}
|
||||
}
|
||||
if tags.HasVerb("watch") {
|
||||
sw.Do(watchTemplate, m)
|
||||
}
|
||||
|
||||
if tags.HasVerb("create") {
|
||||
sw.Do(createTemplate, m)
|
||||
}
|
||||
if tags.HasVerb("update") {
|
||||
sw.Do(updateTemplate, m)
|
||||
}
|
||||
if tags.HasVerb("updateStatus") && genStatus(t) {
|
||||
sw.Do(updateStatusTemplate, m)
|
||||
}
|
||||
if tags.HasVerb("delete") {
|
||||
sw.Do(deleteTemplate, m)
|
||||
}
|
||||
if tags.HasVerb("deleteCollection") {
|
||||
sw.Do(deleteCollectionTemplate, m)
|
||||
}
|
||||
if tags.HasVerb("patch") {
|
||||
sw.Do(patchTemplate, m)
|
||||
}
|
||||
|
||||
// generate extended client methods
|
||||
for _, e := range tags.Extensions {
|
||||
inputType := *t
|
||||
resultType := *t
|
||||
if len(e.InputTypeOverride) > 0 {
|
||||
if name, pkg := e.Input(); len(pkg) > 0 {
|
||||
newType := c.Universe.Type(types.Name{Package: pkg, Name: name})
|
||||
inputType = *newType
|
||||
} else {
|
||||
inputType.Name.Name = e.InputTypeOverride
|
||||
}
|
||||
}
|
||||
if len(e.ResultTypeOverride) > 0 {
|
||||
if name, pkg := e.Result(); len(pkg) > 0 {
|
||||
newType := c.Universe.Type(types.Name{Package: pkg, Name: name})
|
||||
resultType = *newType
|
||||
} else {
|
||||
resultType.Name.Name = e.ResultTypeOverride
|
||||
}
|
||||
}
|
||||
m["inputType"] = &inputType
|
||||
m["resultType"] = &resultType
|
||||
m["subresourcePath"] = e.SubResourcePath
|
||||
|
||||
if e.HasVerb("get") {
|
||||
if e.IsSubresource() {
|
||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, getSubresourceTemplate), m)
|
||||
} else {
|
||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, getTemplate), m)
|
||||
}
|
||||
}
|
||||
|
||||
if e.HasVerb("list") {
|
||||
|
||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, listTemplate), m)
|
||||
}
|
||||
|
||||
// TODO: Figure out schemantic for watching a sub-resource.
|
||||
if e.HasVerb("watch") {
|
||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, watchTemplate), m)
|
||||
}
|
||||
|
||||
if e.HasVerb("create") {
|
||||
if e.IsSubresource() {
|
||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, createSubresourceTemplate), m)
|
||||
} else {
|
||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, createTemplate), m)
|
||||
}
|
||||
}
|
||||
|
||||
if e.HasVerb("update") {
|
||||
if e.IsSubresource() {
|
||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, updateSubresourceTemplate), m)
|
||||
} else {
|
||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, updateTemplate), m)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Figure out schemantic for deleting a sub-resource (what arguments
|
||||
// are passed, does it need two names? etc.
|
||||
if e.HasVerb("delete") {
|
||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, deleteTemplate), m)
|
||||
}
|
||||
|
||||
if e.HasVerb("patch") {
|
||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, patchTemplate), m)
|
||||
}
|
||||
}
|
||||
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
// adjustTemplate adjust the origin verb template using the expansion name.
|
||||
// TODO: Make the verbs in templates parametrized so the strings.Replace() is
|
||||
// not needed.
|
||||
func adjustTemplate(name, verbType, template string) string {
|
||||
return strings.Replace(template, " "+strings.Title(verbType), " "+name, -1)
|
||||
}
|
||||
|
||||
// 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$.GroupGoName$$.Version$
|
||||
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$.GroupGoName$$.Version$
|
||||
}
|
||||
`
|
||||
|
||||
var resource = `
|
||||
var $.type|allLowercasePlural$Resource = $.GroupVersionResource|raw${Group: "$.groupName$", Version: "$.version$", Resource: "$.type|resource$"}
|
||||
`
|
||||
|
||||
var kind = `
|
||||
var $.type|allLowercasePlural$Kind = $.GroupVersionKind|raw${Group: "$.groupName$", Version: "$.version$", Kind: "$.type|singularKind$"}
|
||||
`
|
||||
|
||||
var listTemplate = `
|
||||
// List takes label and field selectors, and returns the list of $.type|publicPlural$ that match those selectors.
|
||||
func (c *Fake$.type|publicPlural$) List(opts $.ListOptions|raw$) (result *$.type|raw$List, err error) {
|
||||
obj, err := c.Fake.
|
||||
$if .namespaced$Invokes($.NewListAction|raw$($.type|allLowercasePlural$Resource, $.type|allLowercasePlural$Kind, c.ns, opts), &$.type|raw$List{})
|
||||
$else$Invokes($.NewRootListAction|raw$($.type|allLowercasePlural$Resource, $.type|allLowercasePlural$Kind, opts), &$.type|raw$List{})$end$
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*$.type|raw$List), err
|
||||
}
|
||||
`
|
||||
|
||||
var listUsingOptionsTemplate = `
|
||||
// List takes label and field selectors, and returns the list of $.type|publicPlural$ that match those selectors.
|
||||
func (c *Fake$.type|publicPlural$) List(opts $.ListOptions|raw$) (result *$.type|raw$List, err error) {
|
||||
obj, err := c.Fake.
|
||||
$if .namespaced$Invokes($.NewListAction|raw$($.type|allLowercasePlural$Resource, $.type|allLowercasePlural$Kind, c.ns, opts), &$.type|raw$List{})
|
||||
$else$Invokes($.NewRootListAction|raw$($.type|allLowercasePlural$Resource, $.type|allLowercasePlural$Kind, opts), &$.type|raw$List{})$end$
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := $.ExtractFromListOptions|raw$(opts)
|
||||
if label == nil {
|
||||
label = $.Everything|raw$()
|
||||
}
|
||||
list := &$.type|raw$List{ListMeta: obj.(*$.type|raw$List).ListMeta}
|
||||
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 = `
|
||||
// Get takes name of the $.type|private$, and returns the corresponding $.resultType|private$ object, and an error if there is any.
|
||||
func (c *Fake$.type|publicPlural$) Get(name string, options $.GetOptions|raw$) (result *$.resultType|raw$, err error) {
|
||||
obj, err := c.Fake.
|
||||
$if .namespaced$Invokes($.NewGetAction|raw$($.type|allLowercasePlural$Resource, c.ns, name), &$.resultType|raw${})
|
||||
$else$Invokes($.NewRootGetAction|raw$($.type|allLowercasePlural$Resource, name), &$.resultType|raw${})$end$
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*$.resultType|raw$), err
|
||||
}
|
||||
`
|
||||
|
||||
var getSubresourceTemplate = `
|
||||
// Get takes name of the $.type|private$, and returns the corresponding $.resultType|private$ object, and an error if there is any.
|
||||
func (c *Fake$.type|publicPlural$) Get($.type|private$Name string, options $.GetOptions|raw$) (result *$.resultType|raw$, err error) {
|
||||
obj, err := c.Fake.
|
||||
$if .namespaced$Invokes($.NewGetSubresourceAction|raw$($.type|allLowercasePlural$Resource, c.ns, "$.subresourcePath$", $.type|private$Name), &$.resultType|raw${})
|
||||
$else$Invokes($.NewRootGetSubresourceAction|raw$($.type|allLowercasePlural$Resource, $.type|private$Name), &$.resultType|raw${})$end$
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*$.resultType|raw$), err
|
||||
}
|
||||
`
|
||||
|
||||
var deleteTemplate = `
|
||||
// Delete takes name of the $.type|private$ and deletes it. Returns an error if one occurs.
|
||||
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 = `
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
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 = `
|
||||
// Create takes the representation of a $.inputType|private$ and creates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any.
|
||||
func (c *Fake$.type|publicPlural$) Create($.inputType|private$ *$.inputType|raw$) (result *$.resultType|raw$, err error) {
|
||||
obj, err := c.Fake.
|
||||
$if .namespaced$Invokes($.NewCreateAction|raw$($.inputType|allLowercasePlural$Resource, c.ns, $.inputType|private$), &$.resultType|raw${})
|
||||
$else$Invokes($.NewRootCreateAction|raw$($.inputType|allLowercasePlural$Resource, $.inputType|private$), &$.resultType|raw${})$end$
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*$.resultType|raw$), err
|
||||
}
|
||||
`
|
||||
|
||||
var createSubresourceTemplate = `
|
||||
// Create takes the representation of a $.inputType|private$ and creates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any.
|
||||
func (c *Fake$.type|publicPlural$) Create($.type|private$Name string, $.inputType|private$ *$.inputType|raw$) (result *$.resultType|raw$, err error) {
|
||||
obj, err := c.Fake.
|
||||
$if .namespaced$Invokes($.NewCreateSubresourceAction|raw$($.type|allLowercasePlural$Resource, $.type|private$Name, "$.subresourcePath$", c.ns, $.inputType|private$), &$.resultType|raw${})
|
||||
$else$Invokes($.NewRootCreateSubresourceAction|raw$($.type|allLowercasePlural$Resource, "$.subresourcePath$", $.inputType|private$), &$.resultType|raw${})$end$
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*$.resultType|raw$), err
|
||||
}
|
||||
`
|
||||
|
||||
var updateTemplate = `
|
||||
// Update takes the representation of a $.inputType|private$ and updates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any.
|
||||
func (c *Fake$.type|publicPlural$) Update($.inputType|private$ *$.inputType|raw$) (result *$.resultType|raw$, err error) {
|
||||
obj, err := c.Fake.
|
||||
$if .namespaced$Invokes($.NewUpdateAction|raw$($.inputType|allLowercasePlural$Resource, c.ns, $.inputType|private$), &$.resultType|raw${})
|
||||
$else$Invokes($.NewRootUpdateAction|raw$($.inputType|allLowercasePlural$Resource, $.inputType|private$), &$.resultType|raw${})$end$
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*$.resultType|raw$), err
|
||||
}
|
||||
`
|
||||
|
||||
var updateSubresourceTemplate = `
|
||||
// Update takes the representation of a $.inputType|private$ and updates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any.
|
||||
func (c *Fake$.type|publicPlural$) Update($.type|private$Name string, $.inputType|private$ *$.inputType|raw$) (result *$.resultType|raw$, err error) {
|
||||
obj, err := c.Fake.
|
||||
$if .namespaced$Invokes($.NewUpdateSubresourceAction|raw$($.type|allLowercasePlural$Resource, "$.subresourcePath$", c.ns, $.inputType|private$), &$.inputType|raw${})
|
||||
$else$Invokes($.NewRootUpdateSubresourceAction|raw$($.type|allLowercasePlural$Resource, "$.subresourcePath$", $.inputType|private$), &$.resultType|raw${})$end$
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*$.resultType|raw$), err
|
||||
}
|
||||
`
|
||||
|
||||
var updateStatusTemplate = `
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *Fake$.type|publicPlural$) UpdateStatus($.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 $.resultType|private$.
|
||||
func (c *Fake$.type|publicPlural$) Patch(name string, pt $.PatchType|raw$, data []byte, subresources ...string) (result *$.resultType|raw$, err error) {
|
||||
obj, err := c.Fake.
|
||||
$if .namespaced$Invokes($.NewPatchSubresourceAction|raw$($.type|allLowercasePlural$Resource, c.ns, name, data, subresources... ), &$.resultType|raw${})
|
||||
$else$Invokes($.NewRootPatchSubresourceAction|raw$($.type|allLowercasePlural$Resource, name, data, subresources...), &$.resultType|raw${})$end$
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*$.resultType|raw$), err
|
||||
}
|
||||
`
|
192
vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_clientset.go
generated
vendored
Normal file
192
vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_clientset.go
generated
vendored
Normal file
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
)
|
||||
|
||||
// genClientset generates a package for a clientset.
|
||||
type genClientset struct {
|
||||
generator.DefaultGen
|
||||
groups []clientgentypes.GroupVersions
|
||||
groupGoNames map[clientgentypes.GroupVersion]string
|
||||
clientsetPackage 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.clientsetPackage, "typed", group.PackageName, version.NonEmpty())
|
||||
groupAlias := strings.ToLower(g.groupGoNames[clientgentypes.GroupVersion{Group: group.Group, Version: version.Version}])
|
||||
imports = append(imports, strings.ToLower(fmt.Sprintf("%s%s \"%s\"", groupAlias, version.NonEmpty(), typedClientPath)))
|
||||
}
|
||||
}
|
||||
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, "$", "$")
|
||||
|
||||
allGroups := clientgentypes.ToGroupVersionInfo(g.groups, g.groupGoNames)
|
||||
m := map[string]interface{}{
|
||||
"allGroups": allGroups,
|
||||
"Config": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Config"}),
|
||||
"DefaultKubernetesUserAgent": c.Universe.Function(types.Name{Package: "k8s.io/client-go/rest", Name: "DefaultKubernetesUserAgent"}),
|
||||
"RESTClientInterface": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Interface"}),
|
||||
"DiscoveryInterface": c.Universe.Type(types.Name{Package: "k8s.io/client-go/discovery", Name: "DiscoveryInterface"}),
|
||||
"DiscoveryClient": c.Universe.Type(types.Name{Package: "k8s.io/client-go/discovery", Name: "DiscoveryClient"}),
|
||||
"NewDiscoveryClientForConfig": c.Universe.Function(types.Name{Package: "k8s.io/client-go/discovery", Name: "NewDiscoveryClientForConfig"}),
|
||||
"NewDiscoveryClientForConfigOrDie": c.Universe.Function(types.Name{Package: "k8s.io/client-go/discovery", Name: "NewDiscoveryClientForConfigOrDie"}),
|
||||
"NewDiscoveryClient": c.Universe.Function(types.Name{Package: "k8s.io/client-go/discovery", Name: "NewDiscoveryClient"}),
|
||||
"flowcontrolNewTokenBucketRateLimiter": c.Universe.Function(types.Name{Package: "k8s.io/client-go/util/flowcontrol", Name: "NewTokenBucketRateLimiter"}),
|
||||
}
|
||||
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$$.GroupGoName$$.Version$() $.PackageAlias$.$.GroupGoName$$.Version$Interface
|
||||
$if .IsDefaultVersion$// Deprecated: please explicitly pick a version if possible.
|
||||
$.GroupGoName$() $.PackageAlias$.$.GroupGoName$$.Version$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$$.LowerCaseGroupGoName$$.Version$ *$.PackageAlias$.$.GroupGoName$$.Version$Client
|
||||
$end$
|
||||
}
|
||||
`
|
||||
|
||||
var clientsetInterfaceImplTemplate = `
|
||||
// $.GroupGoName$$.Version$ retrieves the $.GroupGoName$$.Version$Client
|
||||
func (c *Clientset) $.GroupGoName$$.Version$() $.PackageAlias$.$.GroupGoName$$.Version$Interface {
|
||||
return c.$.LowerCaseGroupGoName$$.Version$
|
||||
}
|
||||
`
|
||||
|
||||
var clientsetInterfaceDefaultVersionImpl = `
|
||||
// Deprecated: $.GroupGoName$ retrieves the default version of $.GroupGoName$Client.
|
||||
// Please explicitly pick a version.
|
||||
func (c *Clientset) $.GroupGoName$() $.PackageAlias$.$.GroupGoName$$.Version$Interface {
|
||||
return c.$.LowerCaseGroupGoName$$.Version$
|
||||
}
|
||||
`
|
||||
|
||||
var getDiscoveryTemplate = `
|
||||
// Discovery retrieves the DiscoveryClient
|
||||
func (c *Clientset) Discovery() $.DiscoveryInterface|raw$ {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
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 = $.flowcontrolNewTokenBucketRateLimiter|raw$(configShallowCopy.QPS, configShallowCopy.Burst)
|
||||
}
|
||||
var cs Clientset
|
||||
var err error
|
||||
$range .allGroups$ cs.$.LowerCaseGroupGoName$$.Version$, err =$.PackageAlias$.NewForConfig(&configShallowCopy)
|
||||
if err!=nil {
|
||||
return nil, err
|
||||
}
|
||||
$end$
|
||||
cs.DiscoveryClient, err = $.NewDiscoveryClientForConfig|raw$(&configShallowCopy)
|
||||
if err!=nil {
|
||||
return nil, err
|
||||
}
|
||||
return &cs, 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 cs Clientset
|
||||
$range .allGroups$ cs.$.LowerCaseGroupGoName$$.Version$ =$.PackageAlias$.NewForConfigOrDie(c)
|
||||
$end$
|
||||
cs.DiscoveryClient = $.NewDiscoveryClientForConfigOrDie|raw$(c)
|
||||
return &cs
|
||||
}
|
||||
`
|
||||
|
||||
var newClientsetForRESTClientTemplate = `
|
||||
// New creates a new Clientset for the given RESTClient.
|
||||
func New(c $.RESTClientInterface|raw$) *Clientset {
|
||||
var cs Clientset
|
||||
$range .allGroups$ cs.$.LowerCaseGroupGoName$$.Version$ =$.PackageAlias$.New(c)
|
||||
$end$
|
||||
cs.DiscoveryClient = $.NewDiscoveryClient|raw$(c)
|
||||
return &cs
|
||||
}
|
||||
`
|
54
vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_expansion.go
generated
vendored
Normal file
54
vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_expansion.go
generated
vendored
Normal 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
|
||||
groupPackagePath 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 len(g.types) == 0 || 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.groupPackagePath, strings.ToLower(t.Name.Name+"_expansion.go"))); os.IsNotExist(err) {
|
||||
sw.Do(expansionInterfaceTemplate, t)
|
||||
}
|
||||
}
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
var expansionInterfaceTemplate = `
|
||||
type $.|public$Expansion interface {}
|
||||
`
|
247
vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_group.go
generated
vendored
Normal file
247
vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_group.go
generated
vendored
Normal file
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
|
||||
"k8s.io/code-generator/cmd/client-gen/generators/util"
|
||||
"k8s.io/code-generator/cmd/client-gen/path"
|
||||
)
|
||||
|
||||
// genGroup produces a file for a group client, e.g. ExtensionsClient for the extension group.
|
||||
type genGroup struct {
|
||||
generator.DefaultGen
|
||||
outputPackage string
|
||||
group string
|
||||
version string
|
||||
groupGoName string
|
||||
apiPath string
|
||||
// types in this group
|
||||
types []*types.Type
|
||||
imports namer.ImportTracker
|
||||
inputPackage string
|
||||
clientsetPackage string
|
||||
// If the genGroup has been called. This generator should only execute once.
|
||||
called bool
|
||||
}
|
||||
|
||||
var _ generator.Generator = &genGroup{}
|
||||
|
||||
// We only want to call GenerateType() once per group.
|
||||
func (g *genGroup) Filter(c *generator.Context, t *types.Type) bool {
|
||||
if !g.called {
|
||||
g.called = true
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
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()...)
|
||||
imports = append(imports, filepath.Join(g.clientsetPackage, "scheme"))
|
||||
return
|
||||
}
|
||||
|
||||
func (g *genGroup) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
|
||||
sw := generator.NewSnippetWriter(w, c, "$", "$")
|
||||
|
||||
apiPath := func(group string) string {
|
||||
if group == "core" {
|
||||
return `"/api"`
|
||||
}
|
||||
return `"` + g.apiPath + `"`
|
||||
}
|
||||
|
||||
groupName := g.group
|
||||
if g.group == "core" {
|
||||
groupName = ""
|
||||
}
|
||||
// allow user to define a group name that's different from the one parsed from the directory.
|
||||
p := c.Universe.Package(path.Vendorless(g.inputPackage))
|
||||
if override := types.ExtractCommentTags("+", p.Comments)["groupName"]; override != nil {
|
||||
groupName = override[0]
|
||||
}
|
||||
|
||||
m := map[string]interface{}{
|
||||
"group": g.group,
|
||||
"version": g.version,
|
||||
"groupName": groupName,
|
||||
"GroupGoName": g.groupGoName,
|
||||
"Version": namer.IC(g.version),
|
||||
"types": g.types,
|
||||
"apiPath": apiPath(g.group),
|
||||
"schemaGroupVersion": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/schema", Name: "GroupVersion"}),
|
||||
"runtimeAPIVersionInternal": c.Universe.Variable(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "APIVersionInternal"}),
|
||||
"serializerDirectCodecFactory": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/serializer", Name: "DirectCodecFactory"}),
|
||||
"restConfig": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Config"}),
|
||||
"restDefaultKubernetesUserAgent": c.Universe.Function(types.Name{Package: "k8s.io/client-go/rest", Name: "DefaultKubernetesUserAgent"}),
|
||||
"restRESTClientInterface": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Interface"}),
|
||||
"restRESTClientFor": c.Universe.Function(types.Name{Package: "k8s.io/client-go/rest", Name: "RESTClientFor"}),
|
||||
"SchemeGroupVersion": c.Universe.Variable(types.Name{Package: path.Vendorless(g.inputPackage), Name: "SchemeGroupVersion"}),
|
||||
}
|
||||
sw.Do(groupInterfaceTemplate, m)
|
||||
sw.Do(groupClientTemplate, m)
|
||||
for _, t := range g.types {
|
||||
tags, err := util.ParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
wrapper := map[string]interface{}{
|
||||
"type": t,
|
||||
"GroupGoName": g.groupGoName,
|
||||
"Version": namer.IC(g.version),
|
||||
}
|
||||
if tags.NonNamespaced {
|
||||
sw.Do(getterImplNonNamespaced, wrapper)
|
||||
} else {
|
||||
sw.Do(getterImplNamespaced, 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 $.GroupGoName$$.Version$Interface interface {
|
||||
RESTClient() $.restRESTClientInterface|raw$
|
||||
$range .types$ $.|publicPlural$Getter
|
||||
$end$
|
||||
}
|
||||
`
|
||||
|
||||
var groupClientTemplate = `
|
||||
// $.GroupGoName$$.Version$Client is used to interact with features provided by the $.groupName$ group.
|
||||
type $.GroupGoName$$.Version$Client struct {
|
||||
restClient $.restRESTClientInterface|raw$
|
||||
}
|
||||
`
|
||||
|
||||
var getterImplNamespaced = `
|
||||
func (c *$.GroupGoName$$.Version$Client) $.type|publicPlural$(namespace string) $.type|public$Interface {
|
||||
return new$.type|publicPlural$(c, namespace)
|
||||
}
|
||||
`
|
||||
|
||||
var getterImplNonNamespaced = `
|
||||
func (c *$.GroupGoName$$.Version$Client) $.type|publicPlural$() $.type|public$Interface {
|
||||
return new$.type|publicPlural$(c)
|
||||
}
|
||||
`
|
||||
|
||||
var newClientForConfigTemplate = `
|
||||
// NewForConfig creates a new $.GroupGoName$$.Version$Client for the given config.
|
||||
func NewForConfig(c *$.restConfig|raw$) (*$.GroupGoName$$.Version$Client, error) {
|
||||
config := *c
|
||||
if err := setConfigDefaults(&config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := $.restRESTClientFor|raw$(&config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &$.GroupGoName$$.Version$Client{client}, nil
|
||||
}
|
||||
`
|
||||
|
||||
var newClientForConfigOrDieTemplate = `
|
||||
// NewForConfigOrDie creates a new $.GroupGoName$$.Version$Client for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *$.restConfig|raw$) *$.GroupGoName$$.Version$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 *$.GroupGoName$$.Version$Client) RESTClient() $.restRESTClientInterface|raw$ {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.restClient
|
||||
}
|
||||
`
|
||||
|
||||
var newClientForRESTClientTemplate = `
|
||||
// New creates a new $.GroupGoName$$.Version$Client for the given RESTClient.
|
||||
func New(c $.restRESTClientInterface|raw$) *$.GroupGoName$$.Version$Client {
|
||||
return &$.GroupGoName$$.Version$Client{c}
|
||||
}
|
||||
`
|
||||
|
||||
var setInternalVersionClientDefaultsTemplate = `
|
||||
func setConfigDefaults(config *$.restConfig|raw$) error {
|
||||
config.APIPath = $.apiPath$
|
||||
if config.UserAgent == "" {
|
||||
config.UserAgent = $.restDefaultKubernetesUserAgent|raw$()
|
||||
}
|
||||
if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("$.groupName$")[0].Group {
|
||||
gv := scheme.Scheme.PrioritizedVersionsForGroup("$.groupName$")[0]
|
||||
config.GroupVersion = &gv
|
||||
}
|
||||
config.NegotiatedSerializer = scheme.Codecs
|
||||
|
||||
if config.QPS == 0 {
|
||||
config.QPS = 5
|
||||
}
|
||||
if config.Burst == 0 {
|
||||
config.Burst = 10
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
`
|
||||
|
||||
var setClientDefaultsTemplate = `
|
||||
func setConfigDefaults(config *$.restConfig|raw$) error {
|
||||
gv := $.SchemeGroupVersion|raw$
|
||||
config.GroupVersion = &gv
|
||||
config.APIPath = $.apiPath$
|
||||
config.NegotiatedSerializer = $.serializerDirectCodecFactory|raw${CodecFactory: scheme.Codecs}
|
||||
|
||||
if config.UserAgent == "" {
|
||||
config.UserAgent = $.restDefaultKubernetesUserAgent|raw$()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
`
|
579
vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_type.go
generated
vendored
Normal file
579
vendor/k8s.io/code-generator/cmd/client-gen/generators/generator_for_type.go
generated
vendored
Normal file
|
@ -0,0 +1,579 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
"k8s.io/code-generator/cmd/client-gen/generators/util"
|
||||
)
|
||||
|
||||
// genClientForType produces a file for each top-level type.
|
||||
type genClientForType struct {
|
||||
generator.DefaultGen
|
||||
outputPackage string
|
||||
clientsetPackage string
|
||||
group string
|
||||
version string
|
||||
groupGoName 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 genStatus to return true if there is a subresource path
|
||||
// registered for "status" in the API server, but we do not have that
|
||||
// information, so genStatus returns true if the type has a status field.
|
||||
func genStatus(t *types.Type) bool {
|
||||
// Default to true if we have a Status member
|
||||
hasStatus := false
|
||||
for _, m := range t.Members {
|
||||
if m.Name == "Status" {
|
||||
hasStatus = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return hasStatus && !util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)).NoStatus
|
||||
}
|
||||
|
||||
// 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)
|
||||
tags, err := util.ParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
type extendedInterfaceMethod struct {
|
||||
template string
|
||||
args map[string]interface{}
|
||||
}
|
||||
extendedMethods := []extendedInterfaceMethod{}
|
||||
for _, e := range tags.Extensions {
|
||||
inputType := *t
|
||||
resultType := *t
|
||||
// TODO: Extract this to some helper method as this code is copied into
|
||||
// 2 other places.
|
||||
if len(e.InputTypeOverride) > 0 {
|
||||
if name, pkg := e.Input(); len(pkg) > 0 {
|
||||
newType := c.Universe.Type(types.Name{Package: pkg, Name: name})
|
||||
inputType = *newType
|
||||
} else {
|
||||
inputType.Name.Name = e.InputTypeOverride
|
||||
}
|
||||
}
|
||||
if len(e.ResultTypeOverride) > 0 {
|
||||
if name, pkg := e.Result(); len(pkg) > 0 {
|
||||
newType := c.Universe.Type(types.Name{Package: pkg, Name: name})
|
||||
resultType = *newType
|
||||
} else {
|
||||
resultType.Name.Name = e.ResultTypeOverride
|
||||
}
|
||||
}
|
||||
var updatedVerbtemplate string
|
||||
if _, exists := subresourceDefaultVerbTemplates[e.VerbType]; e.IsSubresource() && exists {
|
||||
updatedVerbtemplate = e.VerbName + "(" + strings.TrimPrefix(subresourceDefaultVerbTemplates[e.VerbType], strings.Title(e.VerbType)+"(")
|
||||
} else {
|
||||
updatedVerbtemplate = e.VerbName + "(" + strings.TrimPrefix(defaultVerbTemplates[e.VerbType], strings.Title(e.VerbType)+"(")
|
||||
}
|
||||
extendedMethods = append(extendedMethods, extendedInterfaceMethod{
|
||||
template: updatedVerbtemplate,
|
||||
args: map[string]interface{}{
|
||||
"type": t,
|
||||
"inputType": &inputType,
|
||||
"resultType": &resultType,
|
||||
"DeleteOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "DeleteOptions"}),
|
||||
"ListOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "ListOptions"}),
|
||||
"GetOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "GetOptions"}),
|
||||
"PatchType": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/types", Name: "PatchType"}),
|
||||
},
|
||||
})
|
||||
}
|
||||
m := map[string]interface{}{
|
||||
"type": t,
|
||||
"inputType": t,
|
||||
"resultType": t,
|
||||
"package": pkg,
|
||||
"Package": namer.IC(pkg),
|
||||
"namespaced": !tags.NonNamespaced,
|
||||
"Group": namer.IC(g.group),
|
||||
"subresource": false,
|
||||
"subresourcePath": "",
|
||||
"GroupGoName": g.groupGoName,
|
||||
"Version": namer.IC(g.version),
|
||||
"DeleteOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "DeleteOptions"}),
|
||||
"ListOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "ListOptions"}),
|
||||
"GetOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "GetOptions"}),
|
||||
"PatchType": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/types", Name: "PatchType"}),
|
||||
"watchInterface": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/watch", Name: "Interface"}),
|
||||
"RESTClientInterface": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Interface"}),
|
||||
"schemeParameterCodec": c.Universe.Variable(types.Name{Package: filepath.Join(g.clientsetPackage, "scheme"), Name: "ParameterCodec"}),
|
||||
}
|
||||
|
||||
sw.Do(getterComment, m)
|
||||
if tags.NonNamespaced {
|
||||
sw.Do(getterNonNamespaced, m)
|
||||
} else {
|
||||
sw.Do(getterNamespaced, m)
|
||||
}
|
||||
|
||||
sw.Do(interfaceTemplate1, m)
|
||||
if !tags.NoVerbs {
|
||||
if !genStatus(t) {
|
||||
tags.SkipVerbs = append(tags.SkipVerbs, "updateStatus")
|
||||
}
|
||||
interfaceSuffix := ""
|
||||
if len(extendedMethods) > 0 {
|
||||
interfaceSuffix = "\n"
|
||||
}
|
||||
sw.Do("\n"+generateInterface(tags)+interfaceSuffix, m)
|
||||
// add extended verbs into interface
|
||||
for _, v := range extendedMethods {
|
||||
sw.Do(v.template+interfaceSuffix, v.args)
|
||||
}
|
||||
|
||||
}
|
||||
sw.Do(interfaceTemplate4, m)
|
||||
|
||||
if tags.NonNamespaced {
|
||||
sw.Do(structNonNamespaced, m)
|
||||
sw.Do(newStructNonNamespaced, m)
|
||||
} else {
|
||||
sw.Do(structNamespaced, m)
|
||||
sw.Do(newStructNamespaced, m)
|
||||
}
|
||||
|
||||
if tags.NoVerbs {
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
if tags.HasVerb("get") {
|
||||
sw.Do(getTemplate, m)
|
||||
}
|
||||
if tags.HasVerb("list") {
|
||||
sw.Do(listTemplate, m)
|
||||
}
|
||||
if tags.HasVerb("watch") {
|
||||
sw.Do(watchTemplate, m)
|
||||
}
|
||||
|
||||
if tags.HasVerb("create") {
|
||||
sw.Do(createTemplate, m)
|
||||
}
|
||||
if tags.HasVerb("update") {
|
||||
sw.Do(updateTemplate, m)
|
||||
}
|
||||
if tags.HasVerb("updateStatus") {
|
||||
sw.Do(updateStatusTemplate, m)
|
||||
}
|
||||
if tags.HasVerb("delete") {
|
||||
sw.Do(deleteTemplate, m)
|
||||
}
|
||||
if tags.HasVerb("deleteCollection") {
|
||||
sw.Do(deleteCollectionTemplate, m)
|
||||
}
|
||||
if tags.HasVerb("patch") {
|
||||
sw.Do(patchTemplate, m)
|
||||
}
|
||||
|
||||
// generate expansion methods
|
||||
for _, e := range tags.Extensions {
|
||||
inputType := *t
|
||||
resultType := *t
|
||||
if len(e.InputTypeOverride) > 0 {
|
||||
if name, pkg := e.Input(); len(pkg) > 0 {
|
||||
newType := c.Universe.Type(types.Name{Package: pkg, Name: name})
|
||||
inputType = *newType
|
||||
} else {
|
||||
inputType.Name.Name = e.InputTypeOverride
|
||||
}
|
||||
}
|
||||
if len(e.ResultTypeOverride) > 0 {
|
||||
if name, pkg := e.Result(); len(pkg) > 0 {
|
||||
newType := c.Universe.Type(types.Name{Package: pkg, Name: name})
|
||||
resultType = *newType
|
||||
} else {
|
||||
resultType.Name.Name = e.ResultTypeOverride
|
||||
}
|
||||
}
|
||||
m["inputType"] = &inputType
|
||||
m["resultType"] = &resultType
|
||||
m["subresourcePath"] = e.SubResourcePath
|
||||
|
||||
if e.HasVerb("get") {
|
||||
if e.IsSubresource() {
|
||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, getSubresourceTemplate), m)
|
||||
} else {
|
||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, getTemplate), m)
|
||||
}
|
||||
}
|
||||
|
||||
if e.HasVerb("list") {
|
||||
if e.IsSubresource() {
|
||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, listSubresourceTemplate), m)
|
||||
} else {
|
||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, listTemplate), m)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Figure out schemantic for watching a sub-resource.
|
||||
if e.HasVerb("watch") {
|
||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, watchTemplate), m)
|
||||
}
|
||||
|
||||
if e.HasVerb("create") {
|
||||
if e.IsSubresource() {
|
||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, createSubresourceTemplate), m)
|
||||
} else {
|
||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, createTemplate), m)
|
||||
}
|
||||
}
|
||||
|
||||
if e.HasVerb("update") {
|
||||
if e.IsSubresource() {
|
||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, updateSubresourceTemplate), m)
|
||||
} else {
|
||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, updateTemplate), m)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Figure out schemantic for deleting a sub-resource (what arguments
|
||||
// are passed, does it need two names? etc.
|
||||
if e.HasVerb("delete") {
|
||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, deleteTemplate), m)
|
||||
}
|
||||
|
||||
if e.HasVerb("patch") {
|
||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, patchTemplate), m)
|
||||
}
|
||||
}
|
||||
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
// adjustTemplate adjust the origin verb template using the expansion name.
|
||||
// TODO: Make the verbs in templates parametrized so the strings.Replace() is
|
||||
// not needed.
|
||||
func adjustTemplate(name, verbType, template string) string {
|
||||
return strings.Replace(template, " "+strings.Title(verbType), " "+name, -1)
|
||||
}
|
||||
|
||||
func generateInterface(tags util.Tags) string {
|
||||
// need an ordered list here to guarantee order of generated methods.
|
||||
out := []string{}
|
||||
for _, m := range util.SupportedVerbs {
|
||||
if tags.HasVerb(m) {
|
||||
out = append(out, defaultVerbTemplates[m])
|
||||
}
|
||||
}
|
||||
return strings.Join(out, "\n")
|
||||
}
|
||||
|
||||
var subresourceDefaultVerbTemplates = map[string]string{
|
||||
"create": `Create($.type|private$Name string, $.inputType|private$ *$.inputType|raw$) (*$.resultType|raw$, error)`,
|
||||
"list": `List($.type|private$Name string, opts $.ListOptions|raw$) (*$.resultType|raw$List, error)`,
|
||||
"update": `Update($.type|private$Name string, $.inputType|private$ *$.inputType|raw$) (*$.resultType|raw$, error)`,
|
||||
"get": `Get($.type|private$Name string, options $.GetOptions|raw$) (*$.resultType|raw$, error)`,
|
||||
}
|
||||
|
||||
var defaultVerbTemplates = map[string]string{
|
||||
"create": `Create(*$.inputType|raw$) (*$.resultType|raw$, error)`,
|
||||
"update": `Update(*$.inputType|raw$) (*$.resultType|raw$, error)`,
|
||||
"updateStatus": `UpdateStatus(*$.type|raw$) (*$.type|raw$, error)`,
|
||||
"delete": `Delete(name string, options *$.DeleteOptions|raw$) error`,
|
||||
"deleteCollection": `DeleteCollection(options *$.DeleteOptions|raw$, listOptions $.ListOptions|raw$) error`,
|
||||
"get": `Get(name string, options $.GetOptions|raw$) (*$.resultType|raw$, error)`,
|
||||
"list": `List(opts $.ListOptions|raw$) (*$.resultType|raw$List, error)`,
|
||||
"watch": `Watch(opts $.ListOptions|raw$) ($.watchInterface|raw$, error)`,
|
||||
"patch": `Patch(name string, pt $.PatchType|raw$, data []byte, subresources ...string) (result *$.resultType|raw$, err 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 getterNamespaced = `
|
||||
type $.type|publicPlural$Getter interface {
|
||||
$.type|publicPlural$(namespace string) $.type|public$Interface
|
||||
}
|
||||
`
|
||||
|
||||
var getterNonNamespaced = `
|
||||
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 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 *$.GroupGoName$$.Version$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 *$.GroupGoName$$.Version$Client) *$.type|privatePlural$ {
|
||||
return &$.type|privatePlural${
|
||||
client: c.RESTClient(),
|
||||
}
|
||||
}
|
||||
`
|
||||
var listTemplate = `
|
||||
// List takes label and field selectors, and returns the list of $.resultType|publicPlural$ that match those selectors.
|
||||
func (c *$.type|privatePlural$) List(opts $.ListOptions|raw$) (result *$.resultType|raw$List, err error) {
|
||||
result = &$.resultType|raw$List{}
|
||||
err = c.client.Get().
|
||||
$if .namespaced$Namespace(c.ns).$end$
|
||||
Resource("$.type|resource$").
|
||||
VersionedParams(&opts, $.schemeParameterCodec|raw$).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
`
|
||||
|
||||
var listSubresourceTemplate = `
|
||||
// List takes $.type|raw$ name, label and field selectors, and returns the list of $.resultType|publicPlural$ that match those selectors.
|
||||
func (c *$.type|privatePlural$) List($.type|private$Name string, opts $.ListOptions|raw$) (result *$.resultType|raw$List, err error) {
|
||||
result = &$.resultType|raw$List{}
|
||||
err = c.client.Get().
|
||||
$if .namespaced$Namespace(c.ns).$end$
|
||||
Resource("$.type|resource$").
|
||||
Name($.type|private$Name).
|
||||
SubResource("$.subresourcePath$").
|
||||
VersionedParams(&opts, $.schemeParameterCodec|raw$).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
`
|
||||
|
||||
var getTemplate = `
|
||||
// Get takes name of the $.type|private$, and returns the corresponding $.resultType|private$ object, and an error if there is any.
|
||||
func (c *$.type|privatePlural$) Get(name string, options $.GetOptions|raw$) (result *$.resultType|raw$, err error) {
|
||||
result = &$.resultType|raw${}
|
||||
err = c.client.Get().
|
||||
$if .namespaced$Namespace(c.ns).$end$
|
||||
Resource("$.type|resource$").
|
||||
Name(name).
|
||||
VersionedParams(&options, $.schemeParameterCodec|raw$).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
`
|
||||
|
||||
var getSubresourceTemplate = `
|
||||
// Get takes name of the $.type|private$, and returns the corresponding $.resultType|raw$ object, and an error if there is any.
|
||||
func (c *$.type|privatePlural$) Get($.type|private$Name string, options $.GetOptions|raw$) (result *$.resultType|raw$, err error) {
|
||||
result = &$.resultType|raw${}
|
||||
err = c.client.Get().
|
||||
$if .namespaced$Namespace(c.ns).$end$
|
||||
Resource("$.type|resource$").
|
||||
Name($.type|private$Name).
|
||||
SubResource("$.subresourcePath$").
|
||||
VersionedParams(&options, $.schemeParameterCodec|raw$).
|
||||
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|resource$").
|
||||
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|resource$").
|
||||
VersionedParams(&listOptions, $.schemeParameterCodec|raw$).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
`
|
||||
|
||||
var createSubresourceTemplate = `
|
||||
// Create takes the representation of a $.inputType|private$ and creates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any.
|
||||
func (c *$.type|privatePlural$) Create($.type|private$Name string, $.inputType|private$ *$.inputType|raw$) (result *$.resultType|raw$, err error) {
|
||||
result = &$.resultType|raw${}
|
||||
err = c.client.Post().
|
||||
$if .namespaced$Namespace(c.ns).$end$
|
||||
Resource("$.type|resource$").
|
||||
Name($.type|private$Name).
|
||||
SubResource("$.subresourcePath$").
|
||||
Body($.inputType|private$).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
`
|
||||
|
||||
var createTemplate = `
|
||||
// Create takes the representation of a $.inputType|private$ and creates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any.
|
||||
func (c *$.type|privatePlural$) Create($.inputType|private$ *$.inputType|raw$) (result *$.resultType|raw$, err error) {
|
||||
result = &$.resultType|raw${}
|
||||
err = c.client.Post().
|
||||
$if .namespaced$Namespace(c.ns).$end$
|
||||
Resource("$.type|resource$").
|
||||
Body($.inputType|private$).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
`
|
||||
|
||||
var updateSubresourceTemplate = `
|
||||
// Update takes the top resource name and the representation of a $.inputType|private$ and updates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any.
|
||||
func (c *$.type|privatePlural$) Update($.type|private$Name string, $.inputType|private$ *$.inputType|raw$) (result *$.resultType|raw$, err error) {
|
||||
result = &$.resultType|raw${}
|
||||
err = c.client.Put().
|
||||
$if .namespaced$Namespace(c.ns).$end$
|
||||
Resource("$.type|resource$").
|
||||
Name($.type|private$Name).
|
||||
SubResource("$.subresourcePath$").
|
||||
Body($.inputType|private$).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
`
|
||||
|
||||
var updateTemplate = `
|
||||
// Update takes the representation of a $.inputType|private$ and updates it. Returns the server's representation of the $.resultType|private$, and an error, if there is any.
|
||||
func (c *$.type|privatePlural$) Update($.inputType|private$ *$.inputType|raw$) (result *$.resultType|raw$, err error) {
|
||||
result = &$.resultType|raw${}
|
||||
err = c.client.Put().
|
||||
$if .namespaced$Namespace(c.ns).$end$
|
||||
Resource("$.type|resource$").
|
||||
Name($.inputType|private$.Name).
|
||||
Body($.inputType|private$).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
`
|
||||
|
||||
var updateStatusTemplate = `
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
|
||||
func (c *$.type|privatePlural$) UpdateStatus($.type|private$ *$.type|raw$) (result *$.type|raw$, err error) {
|
||||
result = &$.type|raw${}
|
||||
err = c.client.Put().
|
||||
$if .namespaced$Namespace(c.ns).$end$
|
||||
Resource("$.type|resource$").
|
||||
Name($.type|private$.Name).
|
||||
SubResource("status").
|
||||
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) {
|
||||
opts.Watch = true
|
||||
return c.client.Get().
|
||||
$if .namespaced$Namespace(c.ns).$end$
|
||||
Resource("$.type|resource$").
|
||||
VersionedParams(&opts, $.schemeParameterCodec|raw$).
|
||||
Watch()
|
||||
}
|
||||
`
|
||||
|
||||
var patchTemplate = `
|
||||
// Patch applies the patch and returns the patched $.resultType|private$.
|
||||
func (c *$.type|privatePlural$) Patch(name string, pt $.PatchType|raw$, data []byte, subresources ...string) (result *$.resultType|raw$, err error) {
|
||||
result = &$.resultType|raw${}
|
||||
err = c.client.Patch(pt).
|
||||
$if .namespaced$Namespace(c.ns).$end$
|
||||
Resource("$.type|resource$").
|
||||
SubResource(subresources...).
|
||||
Name(name).
|
||||
Body(data).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
`
|
183
vendor/k8s.io/code-generator/cmd/client-gen/generators/scheme/generator_for_scheme.go
generated
vendored
Normal file
183
vendor/k8s.io/code-generator/cmd/client-gen/generators/scheme/generator_for_scheme.go
generated
vendored
Normal file
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package scheme
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"k8s.io/code-generator/cmd/client-gen/path"
|
||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
)
|
||||
|
||||
// GenScheme produces a package for a clientset with the scheme, codecs and parameter codecs.
|
||||
type GenScheme struct {
|
||||
generator.DefaultGen
|
||||
OutputPackage string
|
||||
Groups []clientgentypes.GroupVersions
|
||||
GroupGoNames map[clientgentypes.GroupVersion]string
|
||||
InputPackages map[clientgentypes.GroupVersion]string
|
||||
OutputPath string
|
||||
ImportTracker namer.ImportTracker
|
||||
PrivateScheme bool
|
||||
CreateRegistry bool
|
||||
schemeGenerated bool
|
||||
}
|
||||
|
||||
func (g *GenScheme) Namers(c *generator.Context) namer.NameSystems {
|
||||
return namer.NameSystems{
|
||||
"raw": namer.NewRawNamer(g.OutputPackage, g.ImportTracker),
|
||||
}
|
||||
}
|
||||
|
||||
// We only want to call GenerateType() once.
|
||||
func (g *GenScheme) Filter(c *generator.Context, t *types.Type) bool {
|
||||
ret := !g.schemeGenerated
|
||||
g.schemeGenerated = true
|
||||
return ret
|
||||
}
|
||||
|
||||
func (g *GenScheme) Imports(c *generator.Context) (imports []string) {
|
||||
imports = append(imports, g.ImportTracker.ImportLines()...)
|
||||
for _, group := range g.Groups {
|
||||
for _, version := range group.Versions {
|
||||
packagePath := g.InputPackages[clientgentypes.GroupVersion{Group: group.Group, Version: version.Version}]
|
||||
groupAlias := strings.ToLower(g.GroupGoNames[clientgentypes.GroupVersion{Group: group.Group, Version: version.Version}])
|
||||
if g.CreateRegistry {
|
||||
// import the install package for internal clientsets instead of the type package with register.go
|
||||
if version.Version != "" {
|
||||
packagePath = filepath.Dir(packagePath)
|
||||
}
|
||||
packagePath = filepath.Join(packagePath, "install")
|
||||
imports = append(imports, strings.ToLower(fmt.Sprintf("%s \"%s\"", groupAlias, path.Vendorless(packagePath))))
|
||||
break
|
||||
} else {
|
||||
imports = append(imports, strings.ToLower(fmt.Sprintf("%s%s \"%s\"", groupAlias, version.Version.NonEmpty(), path.Vendorless(packagePath))))
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (g *GenScheme) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
|
||||
sw := generator.NewSnippetWriter(w, c, "$", "$")
|
||||
|
||||
allGroupVersions := clientgentypes.ToGroupVersionInfo(g.Groups, g.GroupGoNames)
|
||||
allInstallGroups := clientgentypes.ToGroupInstallPackages(g.Groups, g.GroupGoNames)
|
||||
|
||||
m := map[string]interface{}{
|
||||
"allGroupVersions": allGroupVersions,
|
||||
"allInstallGroups": allInstallGroups,
|
||||
"customRegister": false,
|
||||
"runtimeNewParameterCodec": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "NewParameterCodec"}),
|
||||
"runtimeNewScheme": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "NewScheme"}),
|
||||
"serializerNewCodecFactory": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/serializer", Name: "NewCodecFactory"}),
|
||||
"runtimeScheme": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "Scheme"}),
|
||||
"schemaGroupVersion": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/schema", Name: "GroupVersion"}),
|
||||
"metav1AddToGroupVersion": c.Universe.Function(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "AddToGroupVersion"}),
|
||||
}
|
||||
globals := map[string]string{
|
||||
"Scheme": "Scheme",
|
||||
"Codecs": "Codecs",
|
||||
"ParameterCodec": "ParameterCodec",
|
||||
"Registry": "Registry",
|
||||
}
|
||||
for k, v := range globals {
|
||||
if g.PrivateScheme {
|
||||
m[k] = strings.ToLower(v[0:1]) + v[1:]
|
||||
} else {
|
||||
m[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
sw.Do(globalsTemplate, m)
|
||||
|
||||
if g.OutputPath != "" {
|
||||
if _, err := os.Stat(filepath.Join(g.OutputPath, strings.ToLower("register_custom.go"))); err == nil {
|
||||
m["customRegister"] = true
|
||||
}
|
||||
}
|
||||
|
||||
if g.CreateRegistry {
|
||||
sw.Do(registryRegistration, m)
|
||||
} else {
|
||||
sw.Do(simpleRegistration, m)
|
||||
}
|
||||
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
var globalsTemplate = `
|
||||
var $.Scheme$ = $.runtimeNewScheme|raw$()
|
||||
var $.Codecs$ = $.serializerNewCodecFactory|raw$($.Scheme$)
|
||||
var $.ParameterCodec$ = $.runtimeNewParameterCodec|raw$($.Scheme$)
|
||||
`
|
||||
|
||||
var registryRegistration = `
|
||||
func init() {
|
||||
$.metav1AddToGroupVersion|raw$($.Scheme$, $.schemaGroupVersion|raw${Version: "v1"})
|
||||
Install($.Scheme$)
|
||||
}
|
||||
|
||||
// Install registers the API group and adds types to a scheme
|
||||
func Install(scheme *$.runtimeScheme|raw$) {
|
||||
$- range .allInstallGroups$
|
||||
$.InstallPackageAlias$.Install(scheme)
|
||||
$- end$
|
||||
$if .customRegister$
|
||||
ExtraInstall(scheme)
|
||||
$end -$
|
||||
}
|
||||
`
|
||||
|
||||
var simpleRegistration = `
|
||||
|
||||
|
||||
func init() {
|
||||
$.metav1AddToGroupVersion|raw$($.Scheme$, $.schemaGroupVersion|raw${Version: "v1"})
|
||||
AddToScheme($.Scheme$)
|
||||
}
|
||||
|
||||
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||
// of clientsets, like in:
|
||||
//
|
||||
// import (
|
||||
// "k8s.io/client-go/kubernetes"
|
||||
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||
// )
|
||||
//
|
||||
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||
// aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||
//
|
||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||
// correctly.
|
||||
func AddToScheme(scheme *$.runtimeScheme|raw$) {
|
||||
$- range .allGroupVersions$
|
||||
$.PackageAlias$.AddToScheme(scheme)
|
||||
$- end$
|
||||
$if .customRegister$
|
||||
ExtraAddToScheme(scheme)
|
||||
$end -$
|
||||
}
|
||||
`
|
32
vendor/k8s.io/code-generator/cmd/client-gen/generators/tags.go
generated
vendored
Normal file
32
vendor/k8s.io/code-generator/cmd/client-gen/generators/tags.go
generated
vendored
Normal 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 generators
|
||||
|
||||
import (
|
||||
"k8s.io/gengo/types"
|
||||
)
|
||||
|
||||
// extractTag gets the comment-tags for the key. If the tag did not exist, it
|
||||
// returns the empty string.
|
||||
func extractTag(key string, lines []string) string {
|
||||
val, present := types.ExtractCommentTags("+", lines)[key]
|
||||
if !present || len(val) < 1 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return val[0]
|
||||
}
|
341
vendor/k8s.io/code-generator/cmd/client-gen/generators/util/tags.go
generated
vendored
Normal file
341
vendor/k8s.io/code-generator/cmd/client-gen/generators/util/tags.go
generated
vendored
Normal file
|
@ -0,0 +1,341 @@
|
|||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"k8s.io/gengo/types"
|
||||
)
|
||||
|
||||
var supportedTags = []string{
|
||||
"genclient",
|
||||
"genclient:nonNamespaced",
|
||||
"genclient:noVerbs",
|
||||
"genclient:onlyVerbs",
|
||||
"genclient:skipVerbs",
|
||||
"genclient:noStatus",
|
||||
"genclient:readonly",
|
||||
"genclient:method",
|
||||
}
|
||||
|
||||
// SupportedVerbs is a list of supported verbs for +onlyVerbs and +skipVerbs.
|
||||
var SupportedVerbs = []string{
|
||||
"create",
|
||||
"update",
|
||||
"updateStatus",
|
||||
"delete",
|
||||
"deleteCollection",
|
||||
"get",
|
||||
"list",
|
||||
"watch",
|
||||
"patch",
|
||||
}
|
||||
|
||||
// ReadonlyVerbs represents a list of read-only verbs.
|
||||
var ReadonlyVerbs = []string{
|
||||
"get",
|
||||
"list",
|
||||
"watch",
|
||||
}
|
||||
|
||||
// genClientPrefix is the default prefix for all genclient tags.
|
||||
const genClientPrefix = "genclient:"
|
||||
|
||||
// unsupportedExtensionVerbs is a list of verbs we don't support generating
|
||||
// extension client functions for.
|
||||
var unsupportedExtensionVerbs = []string{
|
||||
"updateStatus",
|
||||
"deleteCollection",
|
||||
"watch",
|
||||
"delete",
|
||||
}
|
||||
|
||||
// inputTypeSupportedVerbs is a list of verb types that supports overriding the
|
||||
// input argument type.
|
||||
var inputTypeSupportedVerbs = []string{
|
||||
"create",
|
||||
"update",
|
||||
}
|
||||
|
||||
// resultTypeSupportedVerbs is a list of verb types that supports overriding the
|
||||
// resulting type.
|
||||
var resultTypeSupportedVerbs = []string{
|
||||
"create",
|
||||
"update",
|
||||
"get",
|
||||
"list",
|
||||
"patch",
|
||||
}
|
||||
|
||||
// Extensions allows to extend the default set of client verbs
|
||||
// (CRUD+watch+patch+list+deleteCollection) for a given type with custom defined
|
||||
// verbs. Custom verbs can have custom input and result types and also allow to
|
||||
// use a sub-resource in a request instead of top-level resource type.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// +genclient:method=UpdateScale,verb=update,subresource=scale,input=Scale,result=Scale
|
||||
//
|
||||
// type ReplicaSet struct { ... }
|
||||
//
|
||||
// The 'method=UpdateScale' is the name of the client function.
|
||||
// The 'verb=update' here means the client function will use 'PUT' action.
|
||||
// The 'subresource=scale' means we will use SubResource template to generate this client function.
|
||||
// The 'input' is the input type used for creation (function argument).
|
||||
// The 'result' (not needed in this case) is the result type returned from the
|
||||
// client function.
|
||||
//
|
||||
type extension struct {
|
||||
// VerbName is the name of the custom verb (Scale, Instantiate, etc..)
|
||||
VerbName string
|
||||
// VerbType is the type of the verb (only verbs from SupportedVerbs are
|
||||
// supported)
|
||||
VerbType string
|
||||
// SubResourcePath defines a path to a sub-resource to use in the request.
|
||||
// (optional)
|
||||
SubResourcePath string
|
||||
// InputTypeOverride overrides the input parameter type for the verb. By
|
||||
// default the original type is used. Overriding the input type only works for
|
||||
// "create" and "update" verb types. The given type must exists in the same
|
||||
// package as the original type.
|
||||
// (optional)
|
||||
InputTypeOverride string
|
||||
// ResultTypeOverride overrides the resulting object type for the verb. By
|
||||
// default the original type is used. Overriding the result type works.
|
||||
// (optional)
|
||||
ResultTypeOverride string
|
||||
}
|
||||
|
||||
// IsSubresource indicates if this extension should generate the sub-resource.
|
||||
func (e *extension) IsSubresource() bool {
|
||||
return len(e.SubResourcePath) > 0
|
||||
}
|
||||
|
||||
// HasVerb checks if the extension matches the given verb.
|
||||
func (e *extension) HasVerb(verb string) bool {
|
||||
return e.VerbType == verb
|
||||
}
|
||||
|
||||
// Input returns the input override package path and the type.
|
||||
func (e *extension) Input() (string, string) {
|
||||
parts := strings.Split(e.InputTypeOverride, ".")
|
||||
return parts[len(parts)-1], strings.Join(parts[0:len(parts)-1], ".")
|
||||
}
|
||||
|
||||
// Result returns the result override package path and the type.
|
||||
func (e *extension) Result() (string, string) {
|
||||
parts := strings.Split(e.ResultTypeOverride, ".")
|
||||
return parts[len(parts)-1], strings.Join(parts[0:len(parts)-1], ".")
|
||||
}
|
||||
|
||||
// Tags represents a genclient configuration for a single type.
|
||||
type Tags struct {
|
||||
// +genclient
|
||||
GenerateClient bool
|
||||
// +genclient:nonNamespaced
|
||||
NonNamespaced bool
|
||||
// +genclient:noStatus
|
||||
NoStatus bool
|
||||
// +genclient:noVerbs
|
||||
NoVerbs bool
|
||||
// +genclient:skipVerbs=get,update
|
||||
// +genclient:onlyVerbs=create,delete
|
||||
SkipVerbs []string
|
||||
// +genclient:method=UpdateScale,verb=update,subresource=scale,input=Scale,result=Scale
|
||||
Extensions []extension
|
||||
}
|
||||
|
||||
// HasVerb returns true if we should include the given verb in final client interface and
|
||||
// generate the function for it.
|
||||
func (t Tags) HasVerb(verb string) bool {
|
||||
if len(t.SkipVerbs) == 0 {
|
||||
return true
|
||||
}
|
||||
for _, s := range t.SkipVerbs {
|
||||
if verb == s {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// MustParseClientGenTags calls ParseClientGenTags but instead of returning error it panics.
|
||||
func MustParseClientGenTags(lines []string) Tags {
|
||||
tags, err := ParseClientGenTags(lines)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
return tags
|
||||
}
|
||||
|
||||
// ParseClientGenTags parse the provided genclient tags and validates that no unknown
|
||||
// tags are provided.
|
||||
func ParseClientGenTags(lines []string) (Tags, error) {
|
||||
ret := Tags{}
|
||||
values := types.ExtractCommentTags("+", lines)
|
||||
value := []string{}
|
||||
value, ret.GenerateClient = values["genclient"]
|
||||
// Check the old format and error when used to avoid generating client when //+genclient=false
|
||||
if len(value) > 0 && len(value[0]) > 0 {
|
||||
return ret, fmt.Errorf("+genclient=%s is invalid, use //+genclient if you want to generate client or omit it when you want to disable generation", value)
|
||||
}
|
||||
_, ret.NonNamespaced = values[genClientPrefix+"nonNamespaced"]
|
||||
// Check the old format and error when used
|
||||
if value := values["nonNamespaced"]; len(value) > 0 && len(value[0]) > 0 {
|
||||
return ret, fmt.Errorf("+nonNamespaced=%s is invalid, use //+genclient:nonNamespaced instead", value[0])
|
||||
}
|
||||
_, ret.NoVerbs = values[genClientPrefix+"noVerbs"]
|
||||
_, ret.NoStatus = values[genClientPrefix+"noStatus"]
|
||||
onlyVerbs := []string{}
|
||||
if _, isReadonly := values[genClientPrefix+"readonly"]; isReadonly {
|
||||
onlyVerbs = ReadonlyVerbs
|
||||
}
|
||||
// Check the old format and error when used
|
||||
if value := values["readonly"]; len(value) > 0 && len(value[0]) > 0 {
|
||||
return ret, fmt.Errorf("+readonly=%s is invalid, use //+genclient:readonly instead", value[0])
|
||||
}
|
||||
if v, exists := values[genClientPrefix+"skipVerbs"]; exists {
|
||||
ret.SkipVerbs = strings.Split(v[0], ",")
|
||||
}
|
||||
if v, exists := values[genClientPrefix+"onlyVerbs"]; exists || len(onlyVerbs) > 0 {
|
||||
if len(v) > 0 {
|
||||
onlyVerbs = append(onlyVerbs, strings.Split(v[0], ",")...)
|
||||
}
|
||||
skipVerbs := []string{}
|
||||
for _, m := range SupportedVerbs {
|
||||
skip := true
|
||||
for _, o := range onlyVerbs {
|
||||
if o == m {
|
||||
skip = false
|
||||
break
|
||||
}
|
||||
}
|
||||
// Check for conflicts
|
||||
for _, v := range skipVerbs {
|
||||
if v == m {
|
||||
return ret, fmt.Errorf("verb %q used both in genclient:skipVerbs and genclient:onlyVerbs", v)
|
||||
}
|
||||
}
|
||||
if skip {
|
||||
skipVerbs = append(skipVerbs, m)
|
||||
}
|
||||
}
|
||||
ret.SkipVerbs = skipVerbs
|
||||
}
|
||||
var err error
|
||||
if ret.Extensions, err = parseClientExtensions(values); err != nil {
|
||||
return ret, err
|
||||
}
|
||||
return ret, validateClientGenTags(values)
|
||||
}
|
||||
|
||||
func parseClientExtensions(tags map[string][]string) ([]extension, error) {
|
||||
var ret []extension
|
||||
for name, values := range tags {
|
||||
if !strings.HasPrefix(name, genClientPrefix+"method") {
|
||||
continue
|
||||
}
|
||||
for _, value := range values {
|
||||
// the value comes in this form: "Foo,verb=create"
|
||||
ext := extension{}
|
||||
parts := strings.Split(value, ",")
|
||||
if len(parts) == 0 {
|
||||
return nil, fmt.Errorf("invalid of empty extension verb name: %q", value)
|
||||
}
|
||||
// The first part represents the name of the extension
|
||||
ext.VerbName = parts[0]
|
||||
if len(ext.VerbName) == 0 {
|
||||
return nil, fmt.Errorf("must specify a verb name (// +genclient:method=Foo,verb=create)")
|
||||
}
|
||||
// Parse rest of the arguments
|
||||
params := parts[1:]
|
||||
for _, p := range params {
|
||||
parts := strings.Split(p, "=")
|
||||
if len(parts) != 2 {
|
||||
return nil, fmt.Errorf("invalid extension tag specification %q", p)
|
||||
}
|
||||
key, val := strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1])
|
||||
if len(val) == 0 {
|
||||
return nil, fmt.Errorf("empty value of %q for %q extension", key, ext.VerbName)
|
||||
}
|
||||
switch key {
|
||||
case "verb":
|
||||
ext.VerbType = val
|
||||
case "subresource":
|
||||
ext.SubResourcePath = val
|
||||
case "input":
|
||||
ext.InputTypeOverride = val
|
||||
case "result":
|
||||
ext.ResultTypeOverride = val
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown extension configuration key %q", key)
|
||||
}
|
||||
}
|
||||
// Validate resulting extension configuration
|
||||
if len(ext.VerbType) == 0 {
|
||||
return nil, fmt.Errorf("verb type must be specified (use '// +genclient:method=%s,verb=create')", ext.VerbName)
|
||||
}
|
||||
if len(ext.ResultTypeOverride) > 0 {
|
||||
supported := false
|
||||
for _, v := range resultTypeSupportedVerbs {
|
||||
if ext.VerbType == v {
|
||||
supported = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !supported {
|
||||
return nil, fmt.Errorf("%s: result type is not supported for %q verbs (supported verbs: %#v)", ext.VerbName, ext.VerbType, resultTypeSupportedVerbs)
|
||||
}
|
||||
}
|
||||
if len(ext.InputTypeOverride) > 0 {
|
||||
supported := false
|
||||
for _, v := range inputTypeSupportedVerbs {
|
||||
if ext.VerbType == v {
|
||||
supported = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !supported {
|
||||
return nil, fmt.Errorf("%s: input type is not supported for %q verbs (supported verbs: %#v)", ext.VerbName, ext.VerbType, inputTypeSupportedVerbs)
|
||||
}
|
||||
}
|
||||
for _, t := range unsupportedExtensionVerbs {
|
||||
if ext.VerbType == t {
|
||||
return nil, fmt.Errorf("verb %q is not supported by extension generator", ext.VerbType)
|
||||
}
|
||||
}
|
||||
ret = append(ret, ext)
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// validateTags validates that only supported genclient tags were provided.
|
||||
func validateClientGenTags(values map[string][]string) error {
|
||||
for _, k := range supportedTags {
|
||||
delete(values, k)
|
||||
}
|
||||
for key := range values {
|
||||
if strings.HasPrefix(key, strings.TrimSuffix(genClientPrefix, ":")) {
|
||||
return errors.New("unknown tag detected: " + key)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
65
vendor/k8s.io/code-generator/cmd/client-gen/main.go
generated
vendored
Normal file
65
vendor/k8s.io/code-generator/cmd/client-gen/main.go
generated
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
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 gengo.
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/gengo/args"
|
||||
|
||||
generatorargs "k8s.io/code-generator/cmd/client-gen/args"
|
||||
"k8s.io/code-generator/cmd/client-gen/generators"
|
||||
"k8s.io/code-generator/pkg/util"
|
||||
)
|
||||
|
||||
func main() {
|
||||
genericArgs, customArgs := generatorargs.NewDefaults()
|
||||
|
||||
// Override defaults.
|
||||
// TODO: move this out of client-gen
|
||||
genericArgs.GoHeaderFilePath = filepath.Join(args.DefaultSourceTree(), util.BoilerplatePath())
|
||||
genericArgs.OutputPackagePath = "k8s.io/kubernetes/pkg/client/clientset_generated/"
|
||||
|
||||
genericArgs.AddFlags(pflag.CommandLine)
|
||||
customArgs.AddFlags(pflag.CommandLine, "k8s.io/kubernetes/pkg/apis") // TODO: move this input path out of client-gen
|
||||
flag.Set("logtostderr", "true")
|
||||
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
|
||||
pflag.Parse()
|
||||
|
||||
// add group version package as input dirs for gengo
|
||||
for _, pkg := range customArgs.Groups {
|
||||
for _, v := range pkg.Versions {
|
||||
genericArgs.InputDirs = append(genericArgs.InputDirs, v.Package)
|
||||
}
|
||||
}
|
||||
|
||||
if err := generatorargs.Validate(genericArgs); err != nil {
|
||||
glog.Fatalf("Error: %v", err)
|
||||
}
|
||||
|
||||
if err := genericArgs.Execute(
|
||||
generators.NameSystems(),
|
||||
generators.DefaultNameSystem(),
|
||||
generators.Packages,
|
||||
); err != nil {
|
||||
glog.Fatalf("Error: %v", err)
|
||||
}
|
||||
}
|
31
vendor/k8s.io/code-generator/cmd/client-gen/path/path.go
generated
vendored
Normal file
31
vendor/k8s.io/code-generator/cmd/client-gen/path/path.go
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package path
|
||||
|
||||
import "strings"
|
||||
|
||||
// Vendorless removes the longest match of "*/vendor/" from the front of p.
|
||||
// It is useful if a package locates in vendor/, e.g.,
|
||||
// k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/apis/meta/v1, because gengo
|
||||
// indexes the package with its import path, e.g.,
|
||||
// k8s.io/apimachinery/pkg/apis/meta/v1,
|
||||
func Vendorless(p string) string {
|
||||
if pos := strings.LastIndex(p, "/vendor/"); pos != -1 {
|
||||
return p[pos+len("/vendor/"):]
|
||||
}
|
||||
return p
|
||||
}
|
123
vendor/k8s.io/code-generator/cmd/client-gen/types/helpers.go
generated
vendored
Normal file
123
vendor/k8s.io/code-generator/cmd/client-gen/types/helpers.go
generated
vendored
Normal file
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
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{Group(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 []PackageVersion) Version {
|
||||
var versionStrings []string
|
||||
for _, version := range versions {
|
||||
versionStrings = append(versionStrings, version.Version.String())
|
||||
}
|
||||
sort.Sort(sortableSliceOfVersions(versionStrings))
|
||||
return Version(versionStrings[len(versionStrings)-1])
|
||||
}
|
||||
|
||||
// ToGroupVersionInfo is a helper function used by generators for groups.
|
||||
func ToGroupVersionInfo(groups []GroupVersions, groupGoNames map[GroupVersion]string) []GroupVersionInfo {
|
||||
var groupVersionPackages []GroupVersionInfo
|
||||
for _, group := range groups {
|
||||
defaultVersion := defaultVersion(group.Versions)
|
||||
for _, version := range group.Versions {
|
||||
groupGoName := groupGoNames[GroupVersion{Group: group.Group, Version: version.Version}]
|
||||
groupVersionPackages = append(groupVersionPackages, GroupVersionInfo{
|
||||
Group: Group(namer.IC(group.Group.NonEmpty())),
|
||||
Version: Version(namer.IC(version.Version.String())),
|
||||
PackageAlias: strings.ToLower(groupGoName + version.Version.NonEmpty()),
|
||||
IsDefaultVersion: version.Version == defaultVersion && version.Version != "",
|
||||
GroupGoName: groupGoName,
|
||||
LowerCaseGroupGoName: namer.IL(groupGoName),
|
||||
})
|
||||
}
|
||||
}
|
||||
return groupVersionPackages
|
||||
}
|
||||
|
||||
func ToGroupInstallPackages(groups []GroupVersions, groupGoNames map[GroupVersion]string) []GroupInstallPackage {
|
||||
var groupInstallPackages []GroupInstallPackage
|
||||
for _, group := range groups {
|
||||
defaultVersion := defaultVersion(group.Versions)
|
||||
groupGoName := groupGoNames[GroupVersion{Group: group.Group, Version: defaultVersion}]
|
||||
groupInstallPackages = append(groupInstallPackages, GroupInstallPackage{
|
||||
Group: Group(namer.IC(group.Group.NonEmpty())),
|
||||
InstallPackageAlias: strings.ToLower(groupGoName),
|
||||
})
|
||||
}
|
||||
return groupInstallPackages
|
||||
}
|
||||
|
||||
// NormalizeGroupVersion calls normalizes the GroupVersion.
|
||||
//func NormalizeGroupVersion(gv GroupVersion) GroupVersion {
|
||||
// return GroupVersion{Group: gv.Group.NonEmpty(), Version: gv.Version, NonEmptyVersion: normalization.Version(gv.Version)}
|
||||
//}
|
78
vendor/k8s.io/code-generator/cmd/client-gen/types/types.go
generated
vendored
Normal file
78
vendor/k8s.io/code-generator/cmd/client-gen/types/types.go
generated
vendored
Normal 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.
|
||||
*/
|
||||
|
||||
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 PackageVersion struct {
|
||||
Version
|
||||
// The fully qualified package, e.g. k8s.io/kubernetes/pkg/apis/apps, where the types.go is found.
|
||||
Package string
|
||||
}
|
||||
|
||||
type GroupVersion struct {
|
||||
Group Group
|
||||
Version Version
|
||||
}
|
||||
|
||||
type GroupVersions struct {
|
||||
// The name of the package for this group, e.g. apps.
|
||||
PackageName string
|
||||
Group Group
|
||||
Versions []PackageVersion
|
||||
}
|
||||
|
||||
// GroupVersionInfo contains all the info around a group version.
|
||||
type GroupVersionInfo 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
|
||||
PackageAlias string
|
||||
GroupGoName string
|
||||
LowerCaseGroupGoName string
|
||||
}
|
||||
|
||||
type GroupInstallPackage struct {
|
||||
Group Group
|
||||
InstallPackageAlias string
|
||||
}
|
83
vendor/k8s.io/code-generator/cmd/conversion-gen/args/args.go
generated
vendored
Normal file
83
vendor/k8s.io/code-generator/cmd/conversion-gen/args/args.go
generated
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package args
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/gengo/args"
|
||||
)
|
||||
|
||||
// DefaultBasePeerDirs are the peer-dirs nearly everybody will use, i.e. those coming from
|
||||
// apimachinery.
|
||||
var DefaultBasePeerDirs = []string{
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"k8s.io/apimachinery/pkg/conversion",
|
||||
"k8s.io/apimachinery/pkg/runtime",
|
||||
}
|
||||
|
||||
// CustomArgs is used by the gengo framework to pass args specific to this generator.
|
||||
type CustomArgs struct {
|
||||
// Base peer dirs which nearly everybody will use, i.e. outside of Kubernetes core. Peer dirs
|
||||
// are declared to make the generator pick up manually written conversion funcs from external
|
||||
// packages.
|
||||
BasePeerDirs []string
|
||||
|
||||
// Custom peer dirs which are application specific. Peer dirs are declared to make the
|
||||
// generator pick up manually written conversion funcs from external packages.
|
||||
ExtraPeerDirs []string
|
||||
|
||||
// SkipUnsafe indicates whether to generate unsafe conversions to improve the efficiency
|
||||
// of these operations. The unsafe operation is a direct pointer assignment via unsafe
|
||||
// (within the allowed uses of unsafe) and is equivalent to a proposed Golang change to
|
||||
// allow structs that are identical to be assigned to each other.
|
||||
SkipUnsafe bool
|
||||
}
|
||||
|
||||
// NewDefaults returns default arguments for the generator.
|
||||
func NewDefaults() (*args.GeneratorArgs, *CustomArgs) {
|
||||
genericArgs := args.Default().WithoutDefaultFlagParsing()
|
||||
customArgs := &CustomArgs{
|
||||
BasePeerDirs: DefaultBasePeerDirs,
|
||||
SkipUnsafe: false,
|
||||
}
|
||||
genericArgs.CustomArgs = customArgs
|
||||
genericArgs.OutputFileBaseName = "conversion_generated"
|
||||
return genericArgs, customArgs
|
||||
}
|
||||
|
||||
// AddFlags add the generator flags to the flag set.
|
||||
func (ca *CustomArgs) AddFlags(fs *pflag.FlagSet) {
|
||||
pflag.CommandLine.StringSliceVar(&ca.BasePeerDirs, "base-peer-dirs", ca.BasePeerDirs,
|
||||
"Comma-separated list of apimachinery import paths which are considered, after tag-specified peers, for conversions. Only change these if you have very good reasons.")
|
||||
pflag.CommandLine.StringSliceVar(&ca.ExtraPeerDirs, "extra-peer-dirs", ca.ExtraPeerDirs,
|
||||
"Application specific comma-separated list of import paths which are considered, after tag-specified peers and base-peer-dirs, for conversions.")
|
||||
pflag.CommandLine.BoolVar(&ca.SkipUnsafe, "skip-unsafe", ca.SkipUnsafe,
|
||||
"If true, will not generate code using unsafe pointer conversions; resulting code may be slower.")
|
||||
}
|
||||
|
||||
// Validate checks the given arguments.
|
||||
func Validate(genericArgs *args.GeneratorArgs) error {
|
||||
_ = genericArgs.CustomArgs.(*CustomArgs)
|
||||
|
||||
if len(genericArgs.OutputFileBaseName) == 0 {
|
||||
return fmt.Errorf("output file base name cannot be empty")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
960
vendor/k8s.io/code-generator/cmd/conversion-gen/generators/conversion.go
generated
vendored
Normal file
960
vendor/k8s.io/code-generator/cmd/conversion-gen/generators/conversion.go
generated
vendored
Normal file
|
@ -0,0 +1,960 @@
|
|||
/*
|
||||
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 (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/gengo/args"
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
conversionargs "k8s.io/code-generator/cmd/conversion-gen/args"
|
||||
)
|
||||
|
||||
// These are the comment tags that carry parameters for conversion generation.
|
||||
const (
|
||||
// e.g., "+k8s:conversion-gen=<peer-pkg>" in doc.go, where <peer-pkg> is the
|
||||
// import path of the package the peer types are defined in.
|
||||
// e.g., "+k8s:conversion-gen=false" in a type's comment will let
|
||||
// conversion-gen skip that type.
|
||||
tagName = "k8s:conversion-gen"
|
||||
// e.g., "+k8s:conversion-gen-external-types=<type-pkg>" in doc.go, where
|
||||
// <type-pkg> is the relative path to the package the types are defined in.
|
||||
externalTypesTagName = "k8s:conversion-gen-external-types"
|
||||
)
|
||||
|
||||
func extractTag(comments []string) []string {
|
||||
return types.ExtractCommentTags("+", comments)[tagName]
|
||||
}
|
||||
|
||||
func extractExternalTypesTag(comments []string) []string {
|
||||
return types.ExtractCommentTags("+", comments)[externalTypesTagName]
|
||||
}
|
||||
|
||||
func isCopyOnly(comments []string) bool {
|
||||
values := types.ExtractCommentTags("+", comments)["k8s:conversion-fn"]
|
||||
return len(values) == 1 && values[0] == "copy-only"
|
||||
}
|
||||
|
||||
func isDrop(comments []string) bool {
|
||||
values := types.ExtractCommentTags("+", comments)["k8s:conversion-fn"]
|
||||
return len(values) == 1 && values[0] == "drop"
|
||||
}
|
||||
|
||||
// TODO: This is created only to reduce number of changes in a single PR.
|
||||
// Remove it and use PublicNamer instead.
|
||||
func conversionNamer() *namer.NameStrategy {
|
||||
return &namer.NameStrategy{
|
||||
Join: func(pre string, in []string, post string) string {
|
||||
return strings.Join(in, "_")
|
||||
},
|
||||
PrependPackageNames: 1,
|
||||
}
|
||||
}
|
||||
|
||||
func defaultFnNamer() *namer.NameStrategy {
|
||||
return &namer.NameStrategy{
|
||||
Prefix: "SetDefaults_",
|
||||
Join: func(pre string, in []string, post string) string {
|
||||
return pre + strings.Join(in, "_") + post
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// NameSystems returns the name system used by the generators in this package.
|
||||
func NameSystems() namer.NameSystems {
|
||||
return namer.NameSystems{
|
||||
"public": conversionNamer(),
|
||||
"raw": namer.NewRawNamer("", nil),
|
||||
"defaultfn": defaultFnNamer(),
|
||||
}
|
||||
}
|
||||
|
||||
// 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 getPeerTypeFor(context *generator.Context, t *types.Type, potenialPeerPkgs []string) *types.Type {
|
||||
for _, ppp := range potenialPeerPkgs {
|
||||
p := context.Universe.Package(ppp)
|
||||
if p == nil {
|
||||
continue
|
||||
}
|
||||
if p.Has(t.Name.Name) {
|
||||
return p.Type(t.Name.Name)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type conversionPair struct {
|
||||
inType *types.Type
|
||||
outType *types.Type
|
||||
}
|
||||
|
||||
// All of the types in conversions map are of type "DeclarationOf" with
|
||||
// the underlying type being "Func".
|
||||
type conversionFuncMap map[conversionPair]*types.Type
|
||||
|
||||
// Returns all manually-defined conversion functions in the package.
|
||||
func getManualConversionFunctions(context *generator.Context, pkg *types.Package, manualMap conversionFuncMap) {
|
||||
if pkg == nil {
|
||||
glog.Warningf("Skipping nil package passed to getManualConversionFunctions")
|
||||
return
|
||||
}
|
||||
glog.V(5).Infof("Scanning for conversion functions in %v", pkg.Name)
|
||||
|
||||
scopeName := types.Ref(conversionPackagePath, "Scope").Name
|
||||
errorName := types.Ref("", "error").Name
|
||||
buffer := &bytes.Buffer{}
|
||||
sw := generator.NewSnippetWriter(buffer, context, "$", "$")
|
||||
|
||||
for _, f := range pkg.Functions {
|
||||
if f.Underlying == nil || f.Underlying.Kind != types.Func {
|
||||
glog.Errorf("Malformed function: %#v", f)
|
||||
continue
|
||||
}
|
||||
if f.Underlying.Signature == nil {
|
||||
glog.Errorf("Function without signature: %#v", f)
|
||||
continue
|
||||
}
|
||||
glog.V(8).Infof("Considering function %s", f.Name)
|
||||
signature := f.Underlying.Signature
|
||||
// Check whether the function is conversion function.
|
||||
// Note that all of them have signature:
|
||||
// func Convert_inType_To_outType(inType, outType, conversion.Scope) error
|
||||
if signature.Receiver != nil {
|
||||
glog.V(8).Infof("%s has a receiver", f.Name)
|
||||
continue
|
||||
}
|
||||
if len(signature.Parameters) != 3 || signature.Parameters[2].Name != scopeName {
|
||||
glog.V(8).Infof("%s has wrong parameters", f.Name)
|
||||
continue
|
||||
}
|
||||
if len(signature.Results) != 1 || signature.Results[0].Name != errorName {
|
||||
glog.V(8).Infof("%s has wrong results", f.Name)
|
||||
continue
|
||||
}
|
||||
inType := signature.Parameters[0]
|
||||
outType := signature.Parameters[1]
|
||||
if inType.Kind != types.Pointer || outType.Kind != types.Pointer {
|
||||
glog.V(8).Infof("%s has wrong parameter types", f.Name)
|
||||
continue
|
||||
}
|
||||
// Now check if the name satisfies the convention.
|
||||
// TODO: This should call the Namer directly.
|
||||
args := argsFromType(inType.Elem, outType.Elem)
|
||||
sw.Do("Convert_$.inType|public$_To_$.outType|public$", args)
|
||||
if f.Name.Name == buffer.String() {
|
||||
glog.V(4).Infof("Found conversion function %s", f.Name)
|
||||
key := conversionPair{inType.Elem, outType.Elem}
|
||||
// We might scan the same package twice, and that's OK.
|
||||
if v, ok := manualMap[key]; ok && v != nil && v.Name.Package != pkg.Path {
|
||||
panic(fmt.Sprintf("duplicate static conversion defined: %s -> %s", key.inType, key.outType))
|
||||
}
|
||||
manualMap[key] = f
|
||||
} else {
|
||||
glog.V(8).Infof("%s has wrong name", f.Name)
|
||||
}
|
||||
buffer.Reset()
|
||||
}
|
||||
}
|
||||
|
||||
func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
|
||||
boilerplate, err := arguments.LoadGoBoilerplate()
|
||||
if err != nil {
|
||||
glog.Fatalf("Failed loading boilerplate: %v", err)
|
||||
}
|
||||
|
||||
packages := generator.Packages{}
|
||||
header := append([]byte(fmt.Sprintf("// +build !%s\n\n", arguments.GeneratedBuildTag)), boilerplate...)
|
||||
|
||||
// Accumulate pre-existing conversion functions.
|
||||
// TODO: This is too ad-hoc. We need a better way.
|
||||
manualConversions := conversionFuncMap{}
|
||||
|
||||
// Record types that are memory equivalent. A type is memory equivalent
|
||||
// if it has the same memory layout and no nested manual conversion is
|
||||
// defined.
|
||||
// TODO: in the future, relax the nested manual conversion requirement
|
||||
// if we can show that a large enough types are memory identical but
|
||||
// have non-trivial conversion
|
||||
memoryEquivalentTypes := equalMemoryTypes{}
|
||||
|
||||
// We are generating conversions only for packages that are explicitly
|
||||
// passed as InputDir.
|
||||
processed := map[string]bool{}
|
||||
for _, i := range context.Inputs {
|
||||
// skip duplicates
|
||||
if processed[i] {
|
||||
continue
|
||||
}
|
||||
processed[i] = true
|
||||
|
||||
glog.V(5).Infof("considering pkg %q", i)
|
||||
pkg := context.Universe[i]
|
||||
// typesPkg is where the versioned types are defined. Sometimes it is
|
||||
// different from pkg. For example, kubernetes core/v1 types are defined
|
||||
// in vendor/k8s.io/api/core/v1, while pkg is at pkg/api/v1.
|
||||
typesPkg := pkg
|
||||
if pkg == nil {
|
||||
// If the input had no Go files, for example.
|
||||
continue
|
||||
}
|
||||
|
||||
// Add conversion and defaulting functions.
|
||||
getManualConversionFunctions(context, pkg, manualConversions)
|
||||
|
||||
// Only generate conversions for packages which explicitly request it
|
||||
// by specifying one or more "+k8s:conversion-gen=<peer-pkg>"
|
||||
// in their doc.go file.
|
||||
peerPkgs := extractTag(pkg.Comments)
|
||||
if peerPkgs != nil {
|
||||
glog.V(5).Infof(" tags: %q", peerPkgs)
|
||||
} else {
|
||||
glog.V(5).Infof(" no tag")
|
||||
continue
|
||||
}
|
||||
skipUnsafe := false
|
||||
if customArgs, ok := arguments.CustomArgs.(*conversionargs.CustomArgs); ok {
|
||||
peerPkgs = append(peerPkgs, customArgs.BasePeerDirs...)
|
||||
peerPkgs = append(peerPkgs, customArgs.ExtraPeerDirs...)
|
||||
skipUnsafe = customArgs.SkipUnsafe
|
||||
}
|
||||
|
||||
// if the external types are not in the same package where the conversion functions to be generated
|
||||
externalTypesValues := extractExternalTypesTag(pkg.Comments)
|
||||
if externalTypesValues != nil {
|
||||
if len(externalTypesValues) != 1 {
|
||||
glog.Fatalf(" expect only one value for %q tag, got: %q", externalTypesTagName, externalTypesValues)
|
||||
}
|
||||
externalTypes := externalTypesValues[0]
|
||||
glog.V(5).Infof(" external types tags: %q", externalTypes)
|
||||
var err error
|
||||
typesPkg, err = context.AddDirectory(externalTypes)
|
||||
if err != nil {
|
||||
glog.Fatalf("cannot import package %s", externalTypes)
|
||||
}
|
||||
// update context.Order to the latest context.Universe
|
||||
orderer := namer.Orderer{Namer: namer.NewPublicNamer(1)}
|
||||
context.Order = orderer.OrderUniverse(context.Universe)
|
||||
}
|
||||
|
||||
// if the source path is within a /vendor/ directory (for example,
|
||||
// k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/apis/meta/v1), allow
|
||||
// generation to output to the proper relative path (under vendor).
|
||||
// Otherwise, the generator will create the file in the wrong location
|
||||
// in the output directory.
|
||||
// TODO: build a more fundamental concept in gengo for dealing with modifications
|
||||
// to vendored packages.
|
||||
vendorless := func(pkg string) string {
|
||||
if pos := strings.LastIndex(pkg, "/vendor/"); pos != -1 {
|
||||
return pkg[pos+len("/vendor/"):]
|
||||
}
|
||||
return pkg
|
||||
}
|
||||
for i := range peerPkgs {
|
||||
peerPkgs[i] = vendorless(peerPkgs[i])
|
||||
}
|
||||
|
||||
// Make sure our peer-packages are added and fully parsed.
|
||||
for _, pp := range peerPkgs {
|
||||
context.AddDir(pp)
|
||||
p := context.Universe[pp]
|
||||
if nil == p {
|
||||
glog.Fatalf("failed to find pkg: %s", pp)
|
||||
}
|
||||
getManualConversionFunctions(context, p, manualConversions)
|
||||
}
|
||||
|
||||
unsafeEquality := TypesEqual(memoryEquivalentTypes)
|
||||
if skipUnsafe {
|
||||
unsafeEquality = noEquality{}
|
||||
}
|
||||
|
||||
path := pkg.Path
|
||||
// if the source path is within a /vendor/ directory (for example,
|
||||
// k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/apis/meta/v1), allow
|
||||
// generation to output to the proper relative path (under vendor).
|
||||
// Otherwise, the generator will create the file in the wrong location
|
||||
// in the output directory.
|
||||
// TODO: build a more fundamental concept in gengo for dealing with modifications
|
||||
// to vendored packages.
|
||||
if strings.HasPrefix(pkg.SourcePath, arguments.OutputBase) {
|
||||
expandedPath := strings.TrimPrefix(pkg.SourcePath, arguments.OutputBase)
|
||||
if strings.Contains(expandedPath, "/vendor/") {
|
||||
path = expandedPath
|
||||
}
|
||||
}
|
||||
packages = append(packages,
|
||||
&generator.DefaultPackage{
|
||||
PackageName: filepath.Base(pkg.Path),
|
||||
PackagePath: path,
|
||||
HeaderText: header,
|
||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
||||
return []generator.Generator{
|
||||
NewGenConversion(arguments.OutputFileBaseName, typesPkg.Path, pkg.Path, manualConversions, peerPkgs, unsafeEquality),
|
||||
}
|
||||
},
|
||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||
return t.Name.Package == typesPkg.Path
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// If there is a manual conversion defined between two types, exclude it
|
||||
// from being a candidate for unsafe conversion
|
||||
for k, v := range manualConversions {
|
||||
if isCopyOnly(v.CommentLines) {
|
||||
glog.V(5).Infof("Conversion function %s will not block memory copy because it is copy-only", v.Name)
|
||||
continue
|
||||
}
|
||||
// this type should be excluded from all equivalence, because the converter must be called.
|
||||
memoryEquivalentTypes.Skip(k.inType, k.outType)
|
||||
}
|
||||
|
||||
return packages
|
||||
}
|
||||
|
||||
type equalMemoryTypes map[conversionPair]bool
|
||||
|
||||
func (e equalMemoryTypes) Skip(a, b *types.Type) {
|
||||
e[conversionPair{a, b}] = false
|
||||
e[conversionPair{b, a}] = false
|
||||
}
|
||||
|
||||
func (e equalMemoryTypes) Equal(a, b *types.Type) bool {
|
||||
// alreadyVisitedTypes holds all the types that have already been checked in the structural type recursion.
|
||||
alreadyVisitedTypes := make(map[*types.Type]bool)
|
||||
return e.cachingEqual(a, b, alreadyVisitedTypes)
|
||||
}
|
||||
|
||||
func (e equalMemoryTypes) cachingEqual(a, b *types.Type, alreadyVisitedTypes map[*types.Type]bool) bool {
|
||||
if a == b {
|
||||
return true
|
||||
}
|
||||
if equal, ok := e[conversionPair{a, b}]; ok {
|
||||
return equal
|
||||
}
|
||||
if equal, ok := e[conversionPair{b, a}]; ok {
|
||||
return equal
|
||||
}
|
||||
result := e.equal(a, b, alreadyVisitedTypes)
|
||||
e[conversionPair{a, b}] = result
|
||||
e[conversionPair{b, a}] = result
|
||||
return result
|
||||
}
|
||||
|
||||
func (e equalMemoryTypes) equal(a, b *types.Type, alreadyVisitedTypes map[*types.Type]bool) bool {
|
||||
in, out := unwrapAlias(a), unwrapAlias(b)
|
||||
switch {
|
||||
case in == out:
|
||||
return true
|
||||
case in.Kind == out.Kind:
|
||||
// if the type exists already, return early to avoid recursion
|
||||
if alreadyVisitedTypes[in] {
|
||||
return true
|
||||
}
|
||||
alreadyVisitedTypes[in] = true
|
||||
|
||||
switch in.Kind {
|
||||
case types.Struct:
|
||||
if len(in.Members) != len(out.Members) {
|
||||
return false
|
||||
}
|
||||
for i, inMember := range in.Members {
|
||||
outMember := out.Members[i]
|
||||
if !e.cachingEqual(inMember.Type, outMember.Type, alreadyVisitedTypes) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case types.Pointer:
|
||||
return e.cachingEqual(in.Elem, out.Elem, alreadyVisitedTypes)
|
||||
case types.Map:
|
||||
return e.cachingEqual(in.Key, out.Key, alreadyVisitedTypes) && e.cachingEqual(in.Elem, out.Elem, alreadyVisitedTypes)
|
||||
case types.Slice:
|
||||
return e.cachingEqual(in.Elem, out.Elem, alreadyVisitedTypes)
|
||||
case types.Interface:
|
||||
// TODO: determine whether the interfaces are actually equivalent - for now, they must have the
|
||||
// same type.
|
||||
return false
|
||||
case types.Builtin:
|
||||
return in.Name.Name == out.Name.Name
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func findMember(t *types.Type, name string) (types.Member, bool) {
|
||||
if t.Kind != types.Struct {
|
||||
return types.Member{}, false
|
||||
}
|
||||
for _, member := range t.Members {
|
||||
if member.Name == name {
|
||||
return member, true
|
||||
}
|
||||
}
|
||||
return types.Member{}, false
|
||||
}
|
||||
|
||||
// unwrapAlias recurses down aliased types to find the bedrock type.
|
||||
func unwrapAlias(in *types.Type) *types.Type {
|
||||
for in.Kind == types.Alias {
|
||||
in = in.Underlying
|
||||
}
|
||||
return in
|
||||
}
|
||||
|
||||
const (
|
||||
runtimePackagePath = "k8s.io/apimachinery/pkg/runtime"
|
||||
conversionPackagePath = "k8s.io/apimachinery/pkg/conversion"
|
||||
)
|
||||
|
||||
type noEquality struct{}
|
||||
|
||||
func (noEquality) Equal(_, _ *types.Type) bool { return false }
|
||||
|
||||
type TypesEqual interface {
|
||||
Equal(a, b *types.Type) bool
|
||||
}
|
||||
|
||||
// genConversion produces a file with a autogenerated conversions.
|
||||
type genConversion struct {
|
||||
generator.DefaultGen
|
||||
// the package that contains the types that conversion func are going to be
|
||||
// generated for
|
||||
typesPackage string
|
||||
// the package that the conversion funcs are going to be output to
|
||||
outputPackage string
|
||||
// packages that contain the peer of types in typesPacakge
|
||||
peerPackages []string
|
||||
manualConversions conversionFuncMap
|
||||
imports namer.ImportTracker
|
||||
types []*types.Type
|
||||
skippedFields map[*types.Type][]string
|
||||
useUnsafe TypesEqual
|
||||
}
|
||||
|
||||
func NewGenConversion(sanitizedName, typesPackage, outputPackage string, manualConversions conversionFuncMap, peerPkgs []string, useUnsafe TypesEqual) generator.Generator {
|
||||
return &genConversion{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: sanitizedName,
|
||||
},
|
||||
typesPackage: typesPackage,
|
||||
outputPackage: outputPackage,
|
||||
peerPackages: peerPkgs,
|
||||
manualConversions: manualConversions,
|
||||
imports: generator.NewImportTracker(),
|
||||
types: []*types.Type{},
|
||||
skippedFields: map[*types.Type][]string{},
|
||||
useUnsafe: useUnsafe,
|
||||
}
|
||||
}
|
||||
|
||||
func (g *genConversion) Namers(c *generator.Context) namer.NameSystems {
|
||||
// Have the raw namer for this file track what it imports.
|
||||
return namer.NameSystems{
|
||||
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
|
||||
"publicIT": &namerPlusImportTracking{
|
||||
delegate: conversionNamer(),
|
||||
tracker: g.imports,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type namerPlusImportTracking struct {
|
||||
delegate namer.Namer
|
||||
tracker namer.ImportTracker
|
||||
}
|
||||
|
||||
func (n *namerPlusImportTracking) Name(t *types.Type) string {
|
||||
n.tracker.AddType(t)
|
||||
return n.delegate.Name(t)
|
||||
}
|
||||
|
||||
func (g *genConversion) convertibleOnlyWithinPackage(inType, outType *types.Type) bool {
|
||||
var t *types.Type
|
||||
var other *types.Type
|
||||
if inType.Name.Package == g.typesPackage {
|
||||
t, other = inType, outType
|
||||
} else {
|
||||
t, other = outType, inType
|
||||
}
|
||||
|
||||
if t.Name.Package != g.typesPackage {
|
||||
return false
|
||||
}
|
||||
// If the type has opted out, skip it.
|
||||
tagvals := extractTag(t.CommentLines)
|
||||
if tagvals != nil {
|
||||
if tagvals[0] != "false" {
|
||||
glog.Fatalf("Type %v: unsupported %s value: %q", t, tagName, tagvals[0])
|
||||
}
|
||||
glog.V(5).Infof("type %v requests no conversion generation, skipping", t)
|
||||
return false
|
||||
}
|
||||
// TODO: Consider generating functions for other kinds too.
|
||||
if t.Kind != types.Struct {
|
||||
return false
|
||||
}
|
||||
// Also, filter out private types.
|
||||
if namer.IsPrivateGoName(other.Name.Name) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (g *genConversion) Filter(c *generator.Context, t *types.Type) bool {
|
||||
peerType := getPeerTypeFor(c, t, g.peerPackages)
|
||||
if peerType == nil {
|
||||
return false
|
||||
}
|
||||
if !g.convertibleOnlyWithinPackage(t, peerType) {
|
||||
return false
|
||||
}
|
||||
|
||||
g.types = append(g.types, t)
|
||||
return true
|
||||
}
|
||||
|
||||
func (g *genConversion) isOtherPackage(pkg string) bool {
|
||||
if pkg == g.outputPackage {
|
||||
return false
|
||||
}
|
||||
if strings.HasSuffix(pkg, `"`+g.outputPackage+`"`) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (g *genConversion) Imports(c *generator.Context) (imports []string) {
|
||||
var importLines []string
|
||||
for _, singleImport := range g.imports.ImportLines() {
|
||||
if g.isOtherPackage(singleImport) {
|
||||
importLines = append(importLines, singleImport)
|
||||
}
|
||||
}
|
||||
return importLines
|
||||
}
|
||||
|
||||
func argsFromType(inType, outType *types.Type) generator.Args {
|
||||
return generator.Args{
|
||||
"inType": inType,
|
||||
"outType": outType,
|
||||
}
|
||||
}
|
||||
|
||||
const nameTmpl = "Convert_$.inType|publicIT$_To_$.outType|publicIT$"
|
||||
|
||||
func (g *genConversion) preexists(inType, outType *types.Type) (*types.Type, bool) {
|
||||
function, ok := g.manualConversions[conversionPair{inType, outType}]
|
||||
return function, ok
|
||||
}
|
||||
|
||||
func (g *genConversion) Init(c *generator.Context, w io.Writer) error {
|
||||
if glog.V(5) {
|
||||
if m, ok := g.useUnsafe.(equalMemoryTypes); ok {
|
||||
var result []string
|
||||
glog.Infof("All objects without identical memory layout:")
|
||||
for k, v := range m {
|
||||
if v {
|
||||
continue
|
||||
}
|
||||
result = append(result, fmt.Sprintf(" %s -> %s = %t", k.inType, k.outType, v))
|
||||
}
|
||||
sort.Strings(result)
|
||||
for _, s := range result {
|
||||
glog.Infof(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
sw := generator.NewSnippetWriter(w, c, "$", "$")
|
||||
sw.Do("func init() {\n", nil)
|
||||
sw.Do("localSchemeBuilder.Register(RegisterConversions)\n", nil)
|
||||
sw.Do("}\n", nil)
|
||||
|
||||
scheme := c.Universe.Type(types.Name{Package: runtimePackagePath, Name: "Scheme"})
|
||||
schemePtr := &types.Type{
|
||||
Kind: types.Pointer,
|
||||
Elem: scheme,
|
||||
}
|
||||
sw.Do("// RegisterConversions adds conversion functions to the given scheme.\n", nil)
|
||||
sw.Do("// Public to allow building arbitrary schemes.\n", nil)
|
||||
sw.Do("func RegisterConversions(scheme $.|raw$) error {\n", schemePtr)
|
||||
sw.Do("return scheme.AddGeneratedConversionFuncs(\n", nil)
|
||||
for _, t := range g.types {
|
||||
peerType := getPeerTypeFor(c, t, g.peerPackages)
|
||||
sw.Do(nameTmpl+",\n", argsFromType(t, peerType))
|
||||
sw.Do(nameTmpl+",\n", argsFromType(peerType, t))
|
||||
}
|
||||
sw.Do(")\n", nil)
|
||||
sw.Do("}\n\n", nil)
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
func (g *genConversion) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
|
||||
glog.V(5).Infof("generating for type %v", t)
|
||||
peerType := getPeerTypeFor(c, t, g.peerPackages)
|
||||
sw := generator.NewSnippetWriter(w, c, "$", "$")
|
||||
g.generateConversion(t, peerType, sw)
|
||||
g.generateConversion(peerType, t, sw)
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
func (g *genConversion) generateConversion(inType, outType *types.Type, sw *generator.SnippetWriter) {
|
||||
args := argsFromType(inType, outType).
|
||||
With("Scope", types.Ref(conversionPackagePath, "Scope"))
|
||||
|
||||
sw.Do("func auto"+nameTmpl+"(in *$.inType|raw$, out *$.outType|raw$, s $.Scope|raw$) error {\n", args)
|
||||
g.generateFor(inType, outType, sw)
|
||||
sw.Do("return nil\n", nil)
|
||||
sw.Do("}\n\n", nil)
|
||||
|
||||
if _, found := g.preexists(inType, outType); found {
|
||||
// There is a public manual Conversion method: use it.
|
||||
} else if skipped := g.skippedFields[inType]; len(skipped) != 0 {
|
||||
// The inType had some fields we could not generate.
|
||||
glog.Errorf("Warning: could not find nor generate a final Conversion function for %v -> %v", inType, outType)
|
||||
glog.Errorf(" the following fields need manual conversion:")
|
||||
for _, f := range skipped {
|
||||
glog.Errorf(" - %v", f)
|
||||
}
|
||||
} else {
|
||||
// Emit a public conversion function.
|
||||
sw.Do("// "+nameTmpl+" is an autogenerated conversion function.\n", args)
|
||||
sw.Do("func "+nameTmpl+"(in *$.inType|raw$, out *$.outType|raw$, s $.Scope|raw$) error {\n", args)
|
||||
sw.Do("return auto"+nameTmpl+"(in, out, s)\n", args)
|
||||
sw.Do("}\n\n", nil)
|
||||
}
|
||||
}
|
||||
|
||||
// we use the system of shadowing 'in' and 'out' so that the same code is valid
|
||||
// at any nesting level. This makes the autogenerator easy to understand, and
|
||||
// the compiler shouldn't care.
|
||||
func (g *genConversion) generateFor(inType, outType *types.Type, sw *generator.SnippetWriter) {
|
||||
glog.V(5).Infof("generating %v -> %v", inType, outType)
|
||||
var f func(*types.Type, *types.Type, *generator.SnippetWriter)
|
||||
|
||||
switch inType.Kind {
|
||||
case types.Builtin:
|
||||
f = g.doBuiltin
|
||||
case types.Map:
|
||||
f = g.doMap
|
||||
case types.Slice:
|
||||
f = g.doSlice
|
||||
case types.Struct:
|
||||
f = g.doStruct
|
||||
case types.Pointer:
|
||||
f = g.doPointer
|
||||
case types.Alias:
|
||||
f = g.doAlias
|
||||
default:
|
||||
f = g.doUnknown
|
||||
}
|
||||
|
||||
f(inType, outType, sw)
|
||||
}
|
||||
|
||||
func (g *genConversion) doBuiltin(inType, outType *types.Type, sw *generator.SnippetWriter) {
|
||||
if inType == outType {
|
||||
sw.Do("*out = *in\n", nil)
|
||||
} else {
|
||||
sw.Do("*out = $.|raw$(*in)\n", outType)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *genConversion) doMap(inType, outType *types.Type, sw *generator.SnippetWriter) {
|
||||
sw.Do("*out = make($.|raw$, len(*in))\n", outType)
|
||||
if isDirectlyAssignable(inType.Key, outType.Key) {
|
||||
sw.Do("for key, val := range *in {\n", nil)
|
||||
if isDirectlyAssignable(inType.Elem, outType.Elem) {
|
||||
if inType.Key == outType.Key {
|
||||
sw.Do("(*out)[key] = ", nil)
|
||||
} else {
|
||||
sw.Do("(*out)[$.|raw$(key)] = ", outType.Key)
|
||||
}
|
||||
if inType.Elem == outType.Elem {
|
||||
sw.Do("val\n", nil)
|
||||
} else {
|
||||
sw.Do("$.|raw$(val)\n", outType.Elem)
|
||||
}
|
||||
} else {
|
||||
sw.Do("newVal := new($.|raw$)\n", outType.Elem)
|
||||
if function, ok := g.preexists(inType.Elem, outType.Elem); ok {
|
||||
sw.Do("if err := $.|raw$(&val, newVal, s); err != nil {\n", function)
|
||||
} else if g.convertibleOnlyWithinPackage(inType.Elem, outType.Elem) {
|
||||
sw.Do("if err := "+nameTmpl+"(&val, newVal, s); err != nil {\n", argsFromType(inType.Elem, outType.Elem))
|
||||
} else {
|
||||
sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)
|
||||
sw.Do("if err := s.Convert(&val, newVal, 0); err != nil {\n", nil)
|
||||
}
|
||||
sw.Do("return err\n", nil)
|
||||
sw.Do("}\n", nil)
|
||||
if inType.Key == outType.Key {
|
||||
sw.Do("(*out)[key] = *newVal\n", nil)
|
||||
} else {
|
||||
sw.Do("(*out)[$.|raw$(key)] = *newVal\n", outType.Key)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// TODO: Implement it when necessary.
|
||||
sw.Do("for range *in {\n", nil)
|
||||
sw.Do("// FIXME: Converting unassignable keys unsupported $.|raw$\n", inType.Key)
|
||||
}
|
||||
sw.Do("}\n", nil)
|
||||
}
|
||||
|
||||
func (g *genConversion) doSlice(inType, outType *types.Type, sw *generator.SnippetWriter) {
|
||||
sw.Do("*out = make($.|raw$, len(*in))\n", outType)
|
||||
if inType.Elem == outType.Elem && inType.Elem.Kind == types.Builtin {
|
||||
sw.Do("copy(*out, *in)\n", nil)
|
||||
} else {
|
||||
sw.Do("for i := range *in {\n", nil)
|
||||
if isDirectlyAssignable(inType.Elem, outType.Elem) {
|
||||
if inType.Elem == outType.Elem {
|
||||
sw.Do("(*out)[i] = (*in)[i]\n", nil)
|
||||
} else {
|
||||
sw.Do("(*out)[i] = $.|raw$((*in)[i])\n", outType.Elem)
|
||||
}
|
||||
} else {
|
||||
if function, ok := g.preexists(inType.Elem, outType.Elem); ok {
|
||||
sw.Do("if err := $.|raw$(&(*in)[i], &(*out)[i], s); err != nil {\n", function)
|
||||
} else if g.convertibleOnlyWithinPackage(inType.Elem, outType.Elem) {
|
||||
sw.Do("if err := "+nameTmpl+"(&(*in)[i], &(*out)[i], s); err != nil {\n", argsFromType(inType.Elem, outType.Elem))
|
||||
} else {
|
||||
// TODO: This triggers on metav1.ObjectMeta <-> metav1.ObjectMeta and
|
||||
// similar because neither package is the target package, and
|
||||
// we really don't know which package will have the conversion
|
||||
// function defined. This fires on basically every object
|
||||
// conversion outside of pkg/api/v1.
|
||||
sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)
|
||||
sw.Do("if err := s.Convert(&(*in)[i], &(*out)[i], 0); err != nil {\n", nil)
|
||||
}
|
||||
sw.Do("return err\n", nil)
|
||||
sw.Do("}\n", nil)
|
||||
}
|
||||
sw.Do("}\n", nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *genConversion) doStruct(inType, outType *types.Type, sw *generator.SnippetWriter) {
|
||||
for _, inMember := range inType.Members {
|
||||
if tagvals := extractTag(inMember.CommentLines); tagvals != nil && tagvals[0] == "false" {
|
||||
// This field is excluded from conversion.
|
||||
sw.Do("// INFO: in."+inMember.Name+" opted out of conversion generation\n", nil)
|
||||
continue
|
||||
}
|
||||
outMember, found := findMember(outType, inMember.Name)
|
||||
if !found {
|
||||
// This field doesn't exist in the peer.
|
||||
sw.Do("// WARNING: in."+inMember.Name+" requires manual conversion: does not exist in peer-type\n", nil)
|
||||
g.skippedFields[inType] = append(g.skippedFields[inType], inMember.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
inMemberType, outMemberType := inMember.Type, outMember.Type
|
||||
// create a copy of both underlying types but give them the top level alias name (since aliases
|
||||
// are assignable)
|
||||
if underlying := unwrapAlias(inMemberType); underlying != inMemberType {
|
||||
copied := *underlying
|
||||
copied.Name = inMemberType.Name
|
||||
inMemberType = &copied
|
||||
}
|
||||
if underlying := unwrapAlias(outMemberType); underlying != outMemberType {
|
||||
copied := *underlying
|
||||
copied.Name = outMemberType.Name
|
||||
outMemberType = &copied
|
||||
}
|
||||
|
||||
args := argsFromType(inMemberType, outMemberType).With("name", inMember.Name)
|
||||
|
||||
// try a direct memory copy for any type that has exactly equivalent values
|
||||
if g.useUnsafe.Equal(inMemberType, outMemberType) {
|
||||
args = args.
|
||||
With("Pointer", types.Ref("unsafe", "Pointer")).
|
||||
With("SliceHeader", types.Ref("reflect", "SliceHeader"))
|
||||
switch inMemberType.Kind {
|
||||
case types.Pointer:
|
||||
sw.Do("out.$.name$ = ($.outType|raw$)($.Pointer|raw$(in.$.name$))\n", args)
|
||||
continue
|
||||
case types.Map:
|
||||
sw.Do("out.$.name$ = *(*$.outType|raw$)($.Pointer|raw$(&in.$.name$))\n", args)
|
||||
continue
|
||||
case types.Slice:
|
||||
sw.Do("out.$.name$ = *(*$.outType|raw$)($.Pointer|raw$(&in.$.name$))\n", args)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// check based on the top level name, not the underlying names
|
||||
if function, ok := g.preexists(inMember.Type, outMember.Type); ok {
|
||||
if isDrop(function.CommentLines) {
|
||||
continue
|
||||
}
|
||||
// copy-only functions that are directly assignable can be inlined instead of invoked.
|
||||
// As an example, conversion functions exist that allow types with private fields to be
|
||||
// correctly copied between types. These functions are equivalent to a memory assignment,
|
||||
// and are necessary for the reflection path, but should not block memory conversion.
|
||||
// Convert_unversioned_Time_to_unversioned_Time is an example of this logic.
|
||||
if !isCopyOnly(function.CommentLines) || !g.isFastConversion(inMemberType, outMemberType) {
|
||||
args["function"] = function
|
||||
sw.Do("if err := $.function|raw$(&in.$.name$, &out.$.name$, s); err != nil {\n", args)
|
||||
sw.Do("return err\n", nil)
|
||||
sw.Do("}\n", nil)
|
||||
continue
|
||||
}
|
||||
glog.V(5).Infof("Skipped function %s because it is copy-only and we can use direct assignment", function.Name)
|
||||
}
|
||||
|
||||
// If we can't auto-convert, punt before we emit any code.
|
||||
if inMemberType.Kind != outMemberType.Kind {
|
||||
sw.Do("// WARNING: in."+inMember.Name+" requires manual conversion: inconvertible types ("+
|
||||
inMemberType.String()+" vs "+outMemberType.String()+")\n", nil)
|
||||
g.skippedFields[inType] = append(g.skippedFields[inType], inMember.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
switch inMemberType.Kind {
|
||||
case types.Builtin:
|
||||
if inMemberType == outMemberType {
|
||||
sw.Do("out.$.name$ = in.$.name$\n", args)
|
||||
} else {
|
||||
sw.Do("out.$.name$ = $.outType|raw$(in.$.name$)\n", args)
|
||||
}
|
||||
case types.Map, types.Slice, types.Pointer:
|
||||
if g.isDirectlyAssignable(inMemberType, outMemberType) {
|
||||
sw.Do("out.$.name$ = in.$.name$\n", args)
|
||||
continue
|
||||
}
|
||||
|
||||
sw.Do("if in.$.name$ != nil {\n", args)
|
||||
sw.Do("in, out := &in.$.name$, &out.$.name$\n", args)
|
||||
g.generateFor(inMemberType, outMemberType, sw)
|
||||
sw.Do("} else {\n", nil)
|
||||
sw.Do("out.$.name$ = nil\n", args)
|
||||
sw.Do("}\n", nil)
|
||||
case types.Struct:
|
||||
if g.isDirectlyAssignable(inMemberType, outMemberType) {
|
||||
sw.Do("out.$.name$ = in.$.name$\n", args)
|
||||
continue
|
||||
}
|
||||
if g.convertibleOnlyWithinPackage(inMemberType, outMemberType) {
|
||||
sw.Do("if err := "+nameTmpl+"(&in.$.name$, &out.$.name$, s); err != nil {\n", args)
|
||||
} else {
|
||||
sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)
|
||||
sw.Do("if err := s.Convert(&in.$.name$, &out.$.name$, 0); err != nil {\n", args)
|
||||
}
|
||||
sw.Do("return err\n", nil)
|
||||
sw.Do("}\n", nil)
|
||||
case types.Alias:
|
||||
if isDirectlyAssignable(inMemberType, outMemberType) {
|
||||
if inMemberType == outMemberType {
|
||||
sw.Do("out.$.name$ = in.$.name$\n", args)
|
||||
} else {
|
||||
sw.Do("out.$.name$ = $.outType|raw$(in.$.name$)\n", args)
|
||||
}
|
||||
} else {
|
||||
if g.convertibleOnlyWithinPackage(inMemberType, outMemberType) {
|
||||
sw.Do("if err := "+nameTmpl+"(&in.$.name$, &out.$.name$, s); err != nil {\n", args)
|
||||
} else {
|
||||
sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)
|
||||
sw.Do("if err := s.Convert(&in.$.name$, &out.$.name$, 0); err != nil {\n", args)
|
||||
}
|
||||
sw.Do("return err\n", nil)
|
||||
sw.Do("}\n", nil)
|
||||
}
|
||||
default:
|
||||
if g.convertibleOnlyWithinPackage(inMemberType, outMemberType) {
|
||||
sw.Do("if err := "+nameTmpl+"(&in.$.name$, &out.$.name$, s); err != nil {\n", args)
|
||||
} else {
|
||||
sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)
|
||||
sw.Do("if err := s.Convert(&in.$.name$, &out.$.name$, 0); err != nil {\n", args)
|
||||
}
|
||||
sw.Do("return err\n", nil)
|
||||
sw.Do("}\n", nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (g *genConversion) isFastConversion(inType, outType *types.Type) bool {
|
||||
switch inType.Kind {
|
||||
case types.Builtin:
|
||||
return true
|
||||
case types.Map, types.Slice, types.Pointer, types.Struct, types.Alias:
|
||||
return g.isDirectlyAssignable(inType, outType)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (g *genConversion) isDirectlyAssignable(inType, outType *types.Type) bool {
|
||||
return unwrapAlias(inType) == unwrapAlias(outType)
|
||||
}
|
||||
|
||||
func (g *genConversion) doPointer(inType, outType *types.Type, sw *generator.SnippetWriter) {
|
||||
sw.Do("*out = new($.Elem|raw$)\n", outType)
|
||||
if isDirectlyAssignable(inType.Elem, outType.Elem) {
|
||||
if inType.Elem == outType.Elem {
|
||||
sw.Do("**out = **in\n", nil)
|
||||
} else {
|
||||
sw.Do("**out = $.|raw$(**in)\n", outType.Elem)
|
||||
}
|
||||
} else {
|
||||
if function, ok := g.preexists(inType.Elem, outType.Elem); ok {
|
||||
sw.Do("if err := $.|raw$(*in, *out, s); err != nil {\n", function)
|
||||
} else if g.convertibleOnlyWithinPackage(inType.Elem, outType.Elem) {
|
||||
sw.Do("if err := "+nameTmpl+"(*in, *out, s); err != nil {\n", argsFromType(inType.Elem, outType.Elem))
|
||||
} else {
|
||||
sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)
|
||||
sw.Do("if err := s.Convert(*in, *out, 0); err != nil {\n", nil)
|
||||
}
|
||||
sw.Do("return err\n", nil)
|
||||
sw.Do("}\n", nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *genConversion) doAlias(inType, outType *types.Type, sw *generator.SnippetWriter) {
|
||||
// TODO: Add support for aliases.
|
||||
g.doUnknown(inType, outType, sw)
|
||||
}
|
||||
|
||||
func (g *genConversion) doUnknown(inType, outType *types.Type, sw *generator.SnippetWriter) {
|
||||
sw.Do("// FIXME: Type $.|raw$ is unsupported.\n", inType)
|
||||
}
|
||||
|
||||
func isDirectlyAssignable(inType, outType *types.Type) bool {
|
||||
// TODO: This should maybe check for actual assignability between the two
|
||||
// types, rather than superficial traits that happen to indicate it is
|
||||
// assignable in the ways we currently use this code.
|
||||
return inType.IsAssignable() && (inType.IsPrimitive() || isSamePackage(inType, outType))
|
||||
}
|
||||
|
||||
func isSamePackage(inType, outType *types.Type) bool {
|
||||
return inType.Name.Package == outType.Name.Package
|
||||
}
|
76
vendor/k8s.io/code-generator/cmd/conversion-gen/main.go
generated
vendored
Normal file
76
vendor/k8s.io/code-generator/cmd/conversion-gen/main.go
generated
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
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 (
|
||||
"flag"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/gengo/args"
|
||||
|
||||
generatorargs "k8s.io/code-generator/cmd/conversion-gen/args"
|
||||
"k8s.io/code-generator/cmd/conversion-gen/generators"
|
||||
"k8s.io/code-generator/pkg/util"
|
||||
)
|
||||
|
||||
func main() {
|
||||
genericArgs, customArgs := generatorargs.NewDefaults()
|
||||
|
||||
// Override defaults.
|
||||
// TODO: move this out of conversion-gen
|
||||
genericArgs.GoHeaderFilePath = filepath.Join(args.DefaultSourceTree(), util.BoilerplatePath())
|
||||
|
||||
genericArgs.AddFlags(pflag.CommandLine)
|
||||
customArgs.AddFlags(pflag.CommandLine)
|
||||
flag.Set("logtostderr", "true")
|
||||
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
|
||||
pflag.Parse()
|
||||
|
||||
if err := generatorargs.Validate(genericArgs); err != nil {
|
||||
glog.Fatalf("Error: %v", err)
|
||||
}
|
||||
|
||||
// Run it.
|
||||
if err := genericArgs.Execute(
|
||||
generators.NameSystems(),
|
||||
generators.DefaultNameSystem(),
|
||||
generators.Packages,
|
||||
); err != nil {
|
||||
glog.Fatalf("Error: %v", err)
|
||||
}
|
||||
glog.V(2).Info("Completed successfully.")
|
||||
}
|
54
vendor/k8s.io/code-generator/cmd/deepcopy-gen/args/args.go
generated
vendored
Normal file
54
vendor/k8s.io/code-generator/cmd/deepcopy-gen/args/args.go
generated
vendored
Normal 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 args
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/gengo/args"
|
||||
"k8s.io/gengo/examples/deepcopy-gen/generators"
|
||||
)
|
||||
|
||||
// CustomArgs is used by the gengo framework to pass args specific to this generator.
|
||||
type CustomArgs generators.CustomArgs
|
||||
|
||||
// NewDefaults returns default arguments for the generator.
|
||||
func NewDefaults() (*args.GeneratorArgs, *CustomArgs) {
|
||||
genericArgs := args.Default().WithoutDefaultFlagParsing()
|
||||
customArgs := &CustomArgs{}
|
||||
genericArgs.CustomArgs = (*generators.CustomArgs)(customArgs) // convert to upstream type to make type-casts work there
|
||||
genericArgs.OutputFileBaseName = "deepcopy_generated"
|
||||
return genericArgs, customArgs
|
||||
}
|
||||
|
||||
// AddFlags add the generator flags to the flag set.
|
||||
func (ca *CustomArgs) AddFlags(fs *pflag.FlagSet) {
|
||||
pflag.CommandLine.StringSliceVar(&ca.BoundingDirs, "bounding-dirs", ca.BoundingDirs,
|
||||
"Comma-separated list of import paths which bound the types for which deep-copies will be generated.")
|
||||
}
|
||||
|
||||
// Validate checks the given arguments.
|
||||
func Validate(genericArgs *args.GeneratorArgs) error {
|
||||
_ = genericArgs.CustomArgs.(*generators.CustomArgs)
|
||||
|
||||
if len(genericArgs.OutputFileBaseName) == 0 {
|
||||
return fmt.Errorf("output file base name cannot be empty")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
84
vendor/k8s.io/code-generator/cmd/deepcopy-gen/main.go
generated
vendored
Normal file
84
vendor/k8s.io/code-generator/cmd/deepcopy-gen/main.go
generated
vendored
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
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
|
||||
//
|
||||
// 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 (
|
||||
"flag"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/gengo/args"
|
||||
"k8s.io/gengo/examples/deepcopy-gen/generators"
|
||||
|
||||
generatorargs "k8s.io/code-generator/cmd/deepcopy-gen/args"
|
||||
"k8s.io/code-generator/pkg/util"
|
||||
)
|
||||
|
||||
func main() {
|
||||
genericArgs, customArgs := generatorargs.NewDefaults()
|
||||
|
||||
// Override defaults.
|
||||
// TODO: move this out of deepcopy-gen
|
||||
genericArgs.GoHeaderFilePath = filepath.Join(args.DefaultSourceTree(), util.BoilerplatePath())
|
||||
|
||||
genericArgs.AddFlags(pflag.CommandLine)
|
||||
customArgs.AddFlags(pflag.CommandLine)
|
||||
flag.Set("logtostderr", "true")
|
||||
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
|
||||
pflag.Parse()
|
||||
|
||||
if err := generatorargs.Validate(genericArgs); err != nil {
|
||||
glog.Fatalf("Error: %v", err)
|
||||
}
|
||||
|
||||
// Run it.
|
||||
if err := genericArgs.Execute(
|
||||
generators.NameSystems(),
|
||||
generators.DefaultNameSystem(),
|
||||
generators.Packages,
|
||||
); err != nil {
|
||||
glog.Fatalf("Error: %v", err)
|
||||
}
|
||||
glog.V(2).Info("Completed successfully.")
|
||||
}
|
54
vendor/k8s.io/code-generator/cmd/defaulter-gen/args/args.go
generated
vendored
Normal file
54
vendor/k8s.io/code-generator/cmd/defaulter-gen/args/args.go
generated
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package args
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/gengo/args"
|
||||
"k8s.io/gengo/examples/defaulter-gen/generators"
|
||||
)
|
||||
|
||||
// CustomArgs is used by the gengo framework to pass args specific to this generator.
|
||||
type CustomArgs generators.CustomArgs
|
||||
|
||||
// NewDefaults returns default arguments for the generator.
|
||||
func NewDefaults() (*args.GeneratorArgs, *CustomArgs) {
|
||||
genericArgs := args.Default().WithoutDefaultFlagParsing()
|
||||
customArgs := &CustomArgs{}
|
||||
genericArgs.CustomArgs = (*generators.CustomArgs)(customArgs) // convert to upstream type to make type-casts work there
|
||||
genericArgs.OutputFileBaseName = "zz_generated.defaults"
|
||||
return genericArgs, customArgs
|
||||
}
|
||||
|
||||
// AddFlags add the generator flags to the flag set.
|
||||
func (ca *CustomArgs) AddFlags(fs *pflag.FlagSet) {
|
||||
pflag.CommandLine.StringSliceVar(&ca.ExtraPeerDirs, "extra-peer-dirs", ca.ExtraPeerDirs,
|
||||
"Comma-separated list of import paths which are considered, after tag-specified peers, for conversions.")
|
||||
}
|
||||
|
||||
// Validate checks the given arguments.
|
||||
func Validate(genericArgs *args.GeneratorArgs) error {
|
||||
_ = genericArgs.CustomArgs.(*generators.CustomArgs)
|
||||
|
||||
if len(genericArgs.OutputFileBaseName) == 0 {
|
||||
return fmt.Errorf("output file base name cannot be empty")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
83
vendor/k8s.io/code-generator/cmd/defaulter-gen/main.go
generated
vendored
Normal file
83
vendor/k8s.io/code-generator/cmd/defaulter-gen/main.go
generated
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
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 (
|
||||
"flag"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/gengo/args"
|
||||
"k8s.io/gengo/examples/defaulter-gen/generators"
|
||||
|
||||
generatorargs "k8s.io/code-generator/cmd/defaulter-gen/args"
|
||||
"k8s.io/code-generator/pkg/util"
|
||||
)
|
||||
|
||||
func main() {
|
||||
genericArgs, customArgs := generatorargs.NewDefaults()
|
||||
|
||||
// Override defaults.
|
||||
// TODO: move this out of defaulter-gen
|
||||
genericArgs.GoHeaderFilePath = filepath.Join(args.DefaultSourceTree(), util.BoilerplatePath())
|
||||
|
||||
genericArgs.AddFlags(pflag.CommandLine)
|
||||
customArgs.AddFlags(pflag.CommandLine)
|
||||
flag.Set("logtostderr", "true")
|
||||
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
|
||||
pflag.Parse()
|
||||
|
||||
if err := generatorargs.Validate(genericArgs); err != nil {
|
||||
glog.Fatalf("Error: %v", err)
|
||||
}
|
||||
|
||||
// Run it.
|
||||
if err := genericArgs.Execute(
|
||||
generators.NameSystems(),
|
||||
generators.DefaultNameSystem(),
|
||||
generators.Packages,
|
||||
); err != nil {
|
||||
glog.Fatalf("Error: %v", err)
|
||||
}
|
||||
glog.V(2).Info("Completed successfully.")
|
||||
}
|
1
vendor/k8s.io/code-generator/cmd/go-to-protobuf/.gitignore
generated
vendored
Normal file
1
vendor/k8s.io/code-generator/cmd/go-to-protobuf/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
go-to-protobuf
|
4
vendor/k8s.io/code-generator/cmd/go-to-protobuf/OWNERS
generated
vendored
Normal file
4
vendor/k8s.io/code-generator/cmd/go-to-protobuf/OWNERS
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
approvers:
|
||||
- smarterclayton
|
||||
reviewers:
|
||||
- smarterclayton
|
39
vendor/k8s.io/code-generator/cmd/go-to-protobuf/main.go
generated
vendored
Normal file
39
vendor/k8s.io/code-generator/cmd/go-to-protobuf/main.go
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
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 (
|
||||
goflag "flag"
|
||||
|
||||
flag "github.com/spf13/pflag"
|
||||
"k8s.io/code-generator/cmd/go-to-protobuf/protobuf"
|
||||
)
|
||||
|
||||
var g = protobuf.New()
|
||||
|
||||
func init() {
|
||||
g.BindFlags(flag.CommandLine)
|
||||
goflag.Set("logtostderr", "true")
|
||||
flag.CommandLine.AddGoFlagSet(goflag.CommandLine)
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
protobuf.Run(g)
|
||||
}
|
349
vendor/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/cmd.go
generated
vendored
Normal file
349
vendor/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/cmd.go
generated
vendored
Normal file
|
@ -0,0 +1,349 @@
|
|||
/*
|
||||
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"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"k8s.io/code-generator/pkg/util"
|
||||
"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
|
||||
APIMachineryPackages string
|
||||
Packages string
|
||||
OutputBase string
|
||||
VendorOutputBase 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, util.BoilerplatePath()),
|
||||
}
|
||||
defaultProtoImport := filepath.Join(sourceTree, "k8s.io", "kubernetes", "vendor", "github.com", "gogo", "protobuf", "protobuf")
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatalf("Cannot get current directory.")
|
||||
}
|
||||
return &Generator{
|
||||
Common: common,
|
||||
OutputBase: sourceTree,
|
||||
VendorOutputBase: filepath.Join(cwd, "vendor"),
|
||||
ProtoImport: []string{defaultProtoImport},
|
||||
APIMachineryPackages: strings.Join([]string{
|
||||
`+k8s.io/apimachinery/pkg/util/intstr`,
|
||||
`+k8s.io/apimachinery/pkg/api/resource`,
|
||||
`+k8s.io/apimachinery/pkg/runtime/schema`,
|
||||
`+k8s.io/apimachinery/pkg/runtime`,
|
||||
`k8s.io/apimachinery/pkg/apis/meta/v1`,
|
||||
`k8s.io/apimachinery/pkg/apis/meta/v1beta1`,
|
||||
`k8s.io/apimachinery/pkg/apis/testapigroup/v1`,
|
||||
}, ","),
|
||||
Packages: "",
|
||||
DropEmbeddedFields: "k8s.io/apimachinery/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.StringVar(&g.APIMachineryPackages, "apimachinery-packages", g.APIMachineryPackages, "comma-separated list of directories to get apimachinery input types from which are needed by any API. 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.StringVar(&g.VendorOutputBase, "vendor-output-base", g.VendorOutputBase, "The vendor/ directory to look for packages in; defaults to $PWD/vendor/.")
|
||||
flag.StringSliceVar(&g.ProtoImport, "proto-import", g.ProtoImport, "The search path for the core protobuf .protos, required; defaults $GOPATH/src/k8s.io/kubernetes/vendor/github.com/gogo/protobuf/protobuf.")
|
||||
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 (consider using the go-header-file flag): %v", err)
|
||||
}
|
||||
|
||||
protobufNames := NewProtobufNamer()
|
||||
outputPackages := generator.Packages{}
|
||||
nonOutputPackages := map[string]struct{}{}
|
||||
|
||||
var packages []string
|
||||
if len(g.APIMachineryPackages) != 0 {
|
||||
packages = append(packages, strings.Split(g.APIMachineryPackages, ",")...)
|
||||
}
|
||||
if len(g.Packages) != 0 {
|
||||
packages = append(packages, strings.Split(g.Packages, ",")...)
|
||||
}
|
||||
if len(packages) == 0 {
|
||||
log.Fatalf("Both apimachinery-packages and packages are empty. At least one package must be specified.")
|
||||
}
|
||||
|
||||
for _, d := range 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)
|
||||
} else {
|
||||
nonOutputPackages[name] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
var vendoredOutputPackages, localOutputPackages generator.Packages
|
||||
for _, p := range protobufNames.packages {
|
||||
if _, ok := nonOutputPackages[p.Name()]; ok {
|
||||
// if we're not outputting the package, don't include it in either package list
|
||||
continue
|
||||
}
|
||||
p.Vendored = strings.Contains(c.Universe[p.PackagePath].SourcePath, "/vendor/")
|
||||
if p.Vendored {
|
||||
vendoredOutputPackages = append(vendoredOutputPackages, p)
|
||||
} else {
|
||||
localOutputPackages = append(localOutputPackages, p)
|
||||
}
|
||||
}
|
||||
|
||||
if err := protobufNames.AssignTypesToPackages(c); err != nil {
|
||||
log.Fatalf("Failed to identify Common types: %v", err)
|
||||
}
|
||||
|
||||
if err := c.ExecutePackages(g.VendorOutputBase, vendoredOutputPackages); err != nil {
|
||||
log.Fatalf("Failed executing vendor generator: %v", err)
|
||||
}
|
||||
if err := c.ExecutePackages(g.OutputBase, localOutputPackages); err != nil {
|
||||
log.Fatalf("Failed executing local 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())
|
||||
if p.Vendored {
|
||||
path = filepath.Join(g.VendorOutputBase, p.ImportPath())
|
||||
outputPath = filepath.Join(g.VendorOutputBase, 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.VendorOutputBase, vendoredOutputPackages); err != nil {
|
||||
log.Fatalf("Failed executing vendor generator: %v", err)
|
||||
}
|
||||
if err := c.ExecutePackages(g.OutputBase, localOutputPackages); err != nil {
|
||||
log.Fatalf("Failed executing local generator: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, outputPackage := range outputPackages {
|
||||
p := outputPackage.(*protobufPackage)
|
||||
|
||||
if len(p.StructTags) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
pattern := filepath.Join(g.OutputBase, p.PackagePath, "*.go")
|
||||
if p.Vendored {
|
||||
pattern = filepath.Join(g.VendorOutputBase, 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
769
vendor/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/generator.go
generated
vendored
Normal file
769
vendor/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/generator.go
generated
vendored
Normal file
|
@ -0,0 +1,769 @@
|
|||
/*
|
||||
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"
|
||||
"io"
|
||||
"log"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
)
|
||||
|
||||
// genProtoIDL produces a .proto IDL.
|
||||
type genProtoIDL struct {
|
||||
generator.DefaultGen
|
||||
localPackage types.Name
|
||||
localGoPackage types.Name
|
||||
imports namer.ImportTracker
|
||||
|
||||
generateAll bool
|
||||
omitGogo bool
|
||||
omitFieldTypes map[types.Name]struct{}
|
||||
}
|
||||
|
||||
func (g *genProtoIDL) PackageVars(c *generator.Context) []string {
|
||||
if g.omitGogo {
|
||||
return []string{
|
||||
fmt.Sprintf("option go_package = %q;", g.localGoPackage.Name),
|
||||
}
|
||||
}
|
||||
return []string{
|
||||
"option (gogoproto.marshaler_all) = true;",
|
||||
"option (gogoproto.stable_marshaler_all) = true;",
|
||||
"option (gogoproto.sizer_all) = true;",
|
||||
"option (gogoproto.goproto_stringer_all) = false;",
|
||||
"option (gogoproto.stringer_all) = true;",
|
||||
"option (gogoproto.unmarshaler_all) = true;",
|
||||
"option (gogoproto.goproto_unrecognized_all) = false;",
|
||||
"option (gogoproto.goproto_enum_prefix_all) = false;",
|
||||
"option (gogoproto.goproto_getters_all) = false;",
|
||||
fmt.Sprintf("option go_package = %q;", g.localGoPackage.Name),
|
||||
}
|
||||
}
|
||||
func (g *genProtoIDL) Filename() string { return g.OptionalName + ".proto" }
|
||||
func (g *genProtoIDL) FileType() string { return "protoidl" }
|
||||
func (g *genProtoIDL) Namers(c *generator.Context) namer.NameSystems {
|
||||
return namer.NameSystems{
|
||||
// The local namer returns the correct protobuf name for a proto type
|
||||
// in the context of a package
|
||||
"local": localNamer{g.localPackage},
|
||||
}
|
||||
}
|
||||
|
||||
// Filter ignores types that are identified as not exportable.
|
||||
func (g *genProtoIDL) Filter(c *generator.Context, t *types.Type) bool {
|
||||
tagVals := types.ExtractCommentTags("+", t.CommentLines)["protobuf"]
|
||||
if tagVals != nil {
|
||||
if tagVals[0] == "false" {
|
||||
// Type specified "false".
|
||||
return false
|
||||
}
|
||||
if tagVals[0] == "true" {
|
||||
// Type specified "true".
|
||||
return true
|
||||
}
|
||||
glog.Fatalf(`Comment tag "protobuf" must be true or false, found: %q`, tagVals[0])
|
||||
}
|
||||
if !g.generateAll {
|
||||
// We're not generating everything.
|
||||
return false
|
||||
}
|
||||
seen := map[*types.Type]bool{}
|
||||
ok := isProtoable(seen, t)
|
||||
return ok
|
||||
}
|
||||
|
||||
func isProtoable(seen map[*types.Type]bool, t *types.Type) bool {
|
||||
if seen[t] {
|
||||
// be optimistic in the case of type cycles.
|
||||
return true
|
||||
}
|
||||
seen[t] = true
|
||||
switch t.Kind {
|
||||
case types.Builtin:
|
||||
return true
|
||||
case types.Alias:
|
||||
return isProtoable(seen, t.Underlying)
|
||||
case types.Slice, types.Pointer:
|
||||
return isProtoable(seen, t.Elem)
|
||||
case types.Map:
|
||||
return isProtoable(seen, t.Key) && isProtoable(seen, t.Elem)
|
||||
case types.Struct:
|
||||
if len(t.Members) == 0 {
|
||||
return true
|
||||
}
|
||||
for _, m := range t.Members {
|
||||
if isProtoable(seen, m.Type) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
case types.Func, types.Chan:
|
||||
return false
|
||||
case types.DeclarationOf, types.Unknown, types.Unsupported:
|
||||
return false
|
||||
case types.Interface:
|
||||
return false
|
||||
default:
|
||||
log.Printf("WARNING: type %q is not portable: %s", t.Kind, t.Name)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// isOptionalAlias should return true if the specified type has an underlying type
|
||||
// (is an alias) of a map or slice and has the comment tag protobuf.nullable=true,
|
||||
// indicating that the type should be nullable in protobuf.
|
||||
func isOptionalAlias(t *types.Type) bool {
|
||||
if t.Underlying == nil || (t.Underlying.Kind != types.Map && t.Underlying.Kind != types.Slice) {
|
||||
return false
|
||||
}
|
||||
if extractBoolTagOrDie("protobuf.nullable", t.CommentLines) == false {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (g *genProtoIDL) Imports(c *generator.Context) (imports []string) {
|
||||
lines := []string{}
|
||||
// TODO: this could be expressed more cleanly
|
||||
for _, line := range g.imports.ImportLines() {
|
||||
if g.omitGogo && line == "github.com/gogo/protobuf/gogoproto/gogo.proto" {
|
||||
continue
|
||||
}
|
||||
lines = append(lines, line)
|
||||
}
|
||||
return lines
|
||||
}
|
||||
|
||||
// GenerateType makes the body of a file implementing a set for type t.
|
||||
func (g *genProtoIDL) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
|
||||
sw := generator.NewSnippetWriter(w, c, "$", "$")
|
||||
b := bodyGen{
|
||||
locator: &protobufLocator{
|
||||
namer: c.Namers["proto"].(ProtobufFromGoNamer),
|
||||
tracker: g.imports,
|
||||
universe: c.Universe,
|
||||
|
||||
localGoPackage: g.localGoPackage.Package,
|
||||
},
|
||||
localPackage: g.localPackage,
|
||||
|
||||
omitGogo: g.omitGogo,
|
||||
omitFieldTypes: g.omitFieldTypes,
|
||||
|
||||
t: t,
|
||||
}
|
||||
switch t.Kind {
|
||||
case types.Alias:
|
||||
return b.doAlias(sw)
|
||||
case types.Struct:
|
||||
return b.doStruct(sw)
|
||||
default:
|
||||
return b.unknown(sw)
|
||||
}
|
||||
}
|
||||
|
||||
// ProtobufFromGoNamer finds the protobuf name of a type (and its package, and
|
||||
// the package path) from its Go name.
|
||||
type ProtobufFromGoNamer interface {
|
||||
GoNameToProtoName(name types.Name) types.Name
|
||||
}
|
||||
|
||||
type ProtobufLocator interface {
|
||||
ProtoTypeFor(t *types.Type) (*types.Type, error)
|
||||
GoTypeForName(name types.Name) *types.Type
|
||||
CastTypeName(name types.Name) string
|
||||
}
|
||||
|
||||
type protobufLocator struct {
|
||||
namer ProtobufFromGoNamer
|
||||
tracker namer.ImportTracker
|
||||
universe types.Universe
|
||||
|
||||
localGoPackage string
|
||||
}
|
||||
|
||||
// CastTypeName returns the cast type name of a Go type
|
||||
// TODO: delegate to a new localgo namer?
|
||||
func (p protobufLocator) CastTypeName(name types.Name) string {
|
||||
if name.Package == p.localGoPackage {
|
||||
return name.Name
|
||||
}
|
||||
return name.String()
|
||||
}
|
||||
|
||||
func (p protobufLocator) GoTypeForName(name types.Name) *types.Type {
|
||||
if len(name.Package) == 0 {
|
||||
name.Package = p.localGoPackage
|
||||
}
|
||||
return p.universe.Type(name)
|
||||
}
|
||||
|
||||
// ProtoTypeFor locates a Protobuf type for the provided Go type (if possible).
|
||||
func (p protobufLocator) ProtoTypeFor(t *types.Type) (*types.Type, error) {
|
||||
switch {
|
||||
// we've already converted the type, or it's a map
|
||||
case t.Kind == types.Protobuf || t.Kind == types.Map:
|
||||
p.tracker.AddType(t)
|
||||
return t, nil
|
||||
}
|
||||
// it's a fundamental type
|
||||
if t, ok := isFundamentalProtoType(t); ok {
|
||||
p.tracker.AddType(t)
|
||||
return t, nil
|
||||
}
|
||||
// it's a message
|
||||
if t.Kind == types.Struct || isOptionalAlias(t) {
|
||||
t := &types.Type{
|
||||
Name: p.namer.GoNameToProtoName(t.Name),
|
||||
Kind: types.Protobuf,
|
||||
|
||||
CommentLines: t.CommentLines,
|
||||
}
|
||||
p.tracker.AddType(t)
|
||||
return t, nil
|
||||
}
|
||||
return nil, errUnrecognizedType
|
||||
}
|
||||
|
||||
type bodyGen struct {
|
||||
locator ProtobufLocator
|
||||
localPackage types.Name
|
||||
omitGogo bool
|
||||
omitFieldTypes map[types.Name]struct{}
|
||||
|
||||
t *types.Type
|
||||
}
|
||||
|
||||
func (b bodyGen) unknown(sw *generator.SnippetWriter) error {
|
||||
return fmt.Errorf("not sure how to generate: %#v", b.t)
|
||||
}
|
||||
|
||||
func (b bodyGen) doAlias(sw *generator.SnippetWriter) error {
|
||||
if !isOptionalAlias(b.t) {
|
||||
return nil
|
||||
}
|
||||
|
||||
var kind string
|
||||
switch b.t.Underlying.Kind {
|
||||
case types.Map:
|
||||
kind = "map"
|
||||
default:
|
||||
kind = "slice"
|
||||
}
|
||||
optional := &types.Type{
|
||||
Name: b.t.Name,
|
||||
Kind: types.Struct,
|
||||
|
||||
CommentLines: b.t.CommentLines,
|
||||
SecondClosestCommentLines: b.t.SecondClosestCommentLines,
|
||||
Members: []types.Member{
|
||||
{
|
||||
Name: "Items",
|
||||
CommentLines: []string{fmt.Sprintf("items, if empty, will result in an empty %s\n", kind)},
|
||||
Type: b.t.Underlying,
|
||||
},
|
||||
},
|
||||
}
|
||||
nested := b
|
||||
nested.t = optional
|
||||
return nested.doStruct(sw)
|
||||
}
|
||||
|
||||
func (b bodyGen) doStruct(sw *generator.SnippetWriter) error {
|
||||
if len(b.t.Name.Name) == 0 {
|
||||
return nil
|
||||
}
|
||||
if namer.IsPrivateGoName(b.t.Name.Name) {
|
||||
return nil
|
||||
}
|
||||
|
||||
var alias *types.Type
|
||||
var fields []protoField
|
||||
options := []string{}
|
||||
allOptions := types.ExtractCommentTags("+", b.t.CommentLines)
|
||||
for k, v := range allOptions {
|
||||
switch {
|
||||
case strings.HasPrefix(k, "protobuf.options."):
|
||||
key := strings.TrimPrefix(k, "protobuf.options.")
|
||||
switch key {
|
||||
case "marshal":
|
||||
if v[0] == "false" {
|
||||
if !b.omitGogo {
|
||||
options = append(options,
|
||||
"(gogoproto.marshaler) = false",
|
||||
"(gogoproto.unmarshaler) = false",
|
||||
"(gogoproto.sizer) = false",
|
||||
)
|
||||
}
|
||||
}
|
||||
default:
|
||||
if !b.omitGogo || !strings.HasPrefix(key, "(gogoproto.") {
|
||||
if key == "(gogoproto.goproto_stringer)" && v[0] == "false" {
|
||||
options = append(options, "(gogoproto.stringer) = false")
|
||||
}
|
||||
options = append(options, fmt.Sprintf("%s = %s", key, v[0]))
|
||||
}
|
||||
}
|
||||
// protobuf.as allows a type to have the same message contents as another Go type
|
||||
case k == "protobuf.as":
|
||||
fields = nil
|
||||
if alias = b.locator.GoTypeForName(types.Name{Name: v[0]}); alias == nil {
|
||||
return fmt.Errorf("type %v references alias %q which does not exist", b.t, v[0])
|
||||
}
|
||||
// protobuf.embed instructs the generator to use the named type in this package
|
||||
// as an embedded message.
|
||||
case k == "protobuf.embed":
|
||||
fields = []protoField{
|
||||
{
|
||||
Tag: 1,
|
||||
Name: v[0],
|
||||
Type: &types.Type{
|
||||
Name: types.Name{
|
||||
Name: v[0],
|
||||
Package: b.localPackage.Package,
|
||||
Path: b.localPackage.Path,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
if alias == nil {
|
||||
alias = b.t
|
||||
}
|
||||
|
||||
// If we don't explicitly embed anything, generate fields by traversing fields.
|
||||
if fields == nil {
|
||||
memberFields, err := membersToFields(b.locator, alias, b.localPackage, b.omitFieldTypes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("type %v cannot be converted to protobuf: %v", b.t, err)
|
||||
}
|
||||
fields = memberFields
|
||||
}
|
||||
|
||||
out := sw.Out()
|
||||
genComment(out, b.t.CommentLines, "")
|
||||
sw.Do(`message $.Name.Name$ {
|
||||
`, b.t)
|
||||
|
||||
if len(options) > 0 {
|
||||
sort.Sort(sort.StringSlice(options))
|
||||
for _, s := range options {
|
||||
fmt.Fprintf(out, " option %s;\n", s)
|
||||
}
|
||||
fmt.Fprintln(out)
|
||||
}
|
||||
|
||||
for i, field := range fields {
|
||||
genComment(out, field.CommentLines, " ")
|
||||
fmt.Fprintf(out, " ")
|
||||
switch {
|
||||
case field.Map:
|
||||
case field.Repeated:
|
||||
fmt.Fprintf(out, "repeated ")
|
||||
case field.Required:
|
||||
fmt.Fprintf(out, "required ")
|
||||
default:
|
||||
fmt.Fprintf(out, "optional ")
|
||||
}
|
||||
sw.Do(`$.Type|local$ $.Name$ = $.Tag$`, field)
|
||||
if len(field.Extras) > 0 {
|
||||
extras := []string{}
|
||||
for k, v := range field.Extras {
|
||||
if b.omitGogo && strings.HasPrefix(k, "(gogoproto.") {
|
||||
continue
|
||||
}
|
||||
extras = append(extras, fmt.Sprintf("%s = %s", k, v))
|
||||
}
|
||||
sort.Sort(sort.StringSlice(extras))
|
||||
if len(extras) > 0 {
|
||||
fmt.Fprintf(out, " [")
|
||||
fmt.Fprint(out, strings.Join(extras, ", "))
|
||||
fmt.Fprintf(out, "]")
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(out, ";\n")
|
||||
if i != len(fields)-1 {
|
||||
fmt.Fprintf(out, "\n")
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(out, "}\n\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
type protoField struct {
|
||||
LocalPackage types.Name
|
||||
|
||||
Tag int
|
||||
Name string
|
||||
Type *types.Type
|
||||
Map bool
|
||||
Repeated bool
|
||||
Optional bool
|
||||
Required bool
|
||||
Nullable bool
|
||||
Extras map[string]string
|
||||
|
||||
CommentLines []string
|
||||
}
|
||||
|
||||
var (
|
||||
errUnrecognizedType = fmt.Errorf("did not recognize the provided type")
|
||||
)
|
||||
|
||||
func isFundamentalProtoType(t *types.Type) (*types.Type, bool) {
|
||||
// TODO: when we enable proto3, also include other fundamental types in the google.protobuf package
|
||||
// switch {
|
||||
// case t.Kind == types.Struct && t.Name == types.Name{Package: "time", Name: "Time"}:
|
||||
// return &types.Type{
|
||||
// Kind: types.Protobuf,
|
||||
// Name: types.Name{Path: "google/protobuf/timestamp.proto", Package: "google.protobuf", Name: "Timestamp"},
|
||||
// }, true
|
||||
// }
|
||||
switch t.Kind {
|
||||
case types.Slice:
|
||||
if t.Elem.Name.Name == "byte" && len(t.Elem.Name.Package) == 0 {
|
||||
return &types.Type{Name: types.Name{Name: "bytes"}, Kind: types.Protobuf}, true
|
||||
}
|
||||
case types.Builtin:
|
||||
switch t.Name.Name {
|
||||
case "string", "uint32", "int32", "uint64", "int64", "bool":
|
||||
return &types.Type{Name: types.Name{Name: t.Name.Name}, Kind: types.Protobuf}, true
|
||||
case "int":
|
||||
return &types.Type{Name: types.Name{Name: "int64"}, Kind: types.Protobuf}, true
|
||||
case "uint":
|
||||
return &types.Type{Name: types.Name{Name: "uint64"}, Kind: types.Protobuf}, true
|
||||
case "float64", "float":
|
||||
return &types.Type{Name: types.Name{Name: "double"}, Kind: types.Protobuf}, true
|
||||
case "float32":
|
||||
return &types.Type{Name: types.Name{Name: "float"}, Kind: types.Protobuf}, true
|
||||
case "uintptr":
|
||||
return &types.Type{Name: types.Name{Name: "uint64"}, Kind: types.Protobuf}, true
|
||||
}
|
||||
// TODO: complex?
|
||||
}
|
||||
return t, false
|
||||
}
|
||||
|
||||
func memberTypeToProtobufField(locator ProtobufLocator, field *protoField, t *types.Type) error {
|
||||
var err error
|
||||
switch t.Kind {
|
||||
case types.Protobuf:
|
||||
field.Type, err = locator.ProtoTypeFor(t)
|
||||
case types.Builtin:
|
||||
field.Type, err = locator.ProtoTypeFor(t)
|
||||
case types.Map:
|
||||
valueField := &protoField{}
|
||||
if err := memberTypeToProtobufField(locator, valueField, t.Elem); err != nil {
|
||||
return err
|
||||
}
|
||||
keyField := &protoField{}
|
||||
if err := memberTypeToProtobufField(locator, keyField, t.Key); err != nil {
|
||||
return err
|
||||
}
|
||||
// All other protobuf types have kind types.Protobuf, so setting types.Map
|
||||
// here would be very misleading.
|
||||
field.Type = &types.Type{
|
||||
Kind: types.Protobuf,
|
||||
Key: keyField.Type,
|
||||
Elem: valueField.Type,
|
||||
}
|
||||
if !strings.HasPrefix(t.Name.Name, "map[") {
|
||||
field.Extras["(gogoproto.casttype)"] = strconv.Quote(locator.CastTypeName(t.Name))
|
||||
}
|
||||
if k, ok := keyField.Extras["(gogoproto.casttype)"]; ok {
|
||||
field.Extras["(gogoproto.castkey)"] = k
|
||||
}
|
||||
if v, ok := valueField.Extras["(gogoproto.casttype)"]; ok {
|
||||
field.Extras["(gogoproto.castvalue)"] = v
|
||||
}
|
||||
field.Map = true
|
||||
case types.Pointer:
|
||||
if err := memberTypeToProtobufField(locator, field, t.Elem); err != nil {
|
||||
return err
|
||||
}
|
||||
field.Nullable = true
|
||||
case types.Alias:
|
||||
if isOptionalAlias(t) {
|
||||
field.Type, err = locator.ProtoTypeFor(t)
|
||||
field.Nullable = true
|
||||
} else {
|
||||
if err := memberTypeToProtobufField(locator, field, t.Underlying); err != nil {
|
||||
log.Printf("failed to alias: %s %s: err %v", t.Name, t.Underlying.Name, err)
|
||||
return err
|
||||
}
|
||||
// If this is not an alias to a slice, cast to the alias
|
||||
if !field.Repeated {
|
||||
if field.Extras == nil {
|
||||
field.Extras = make(map[string]string)
|
||||
}
|
||||
field.Extras["(gogoproto.casttype)"] = strconv.Quote(locator.CastTypeName(t.Name))
|
||||
}
|
||||
}
|
||||
case types.Slice:
|
||||
if t.Elem.Name.Name == "byte" && len(t.Elem.Name.Package) == 0 {
|
||||
field.Type = &types.Type{Name: types.Name{Name: "bytes"}, Kind: types.Protobuf}
|
||||
return nil
|
||||
}
|
||||
if err := memberTypeToProtobufField(locator, field, t.Elem); err != nil {
|
||||
return err
|
||||
}
|
||||
field.Repeated = true
|
||||
case types.Struct:
|
||||
if len(t.Name.Name) == 0 {
|
||||
return errUnrecognizedType
|
||||
}
|
||||
field.Type, err = locator.ProtoTypeFor(t)
|
||||
field.Nullable = false
|
||||
default:
|
||||
return errUnrecognizedType
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// protobufTagToField extracts information from an existing protobuf tag
|
||||
func protobufTagToField(tag string, field *protoField, m types.Member, t *types.Type, localPackage types.Name) error {
|
||||
if len(tag) == 0 || tag == "-" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// protobuf:"bytes,3,opt,name=Id,customtype=github.com/gogo/protobuf/test.Uuid"
|
||||
parts := strings.Split(tag, ",")
|
||||
if len(parts) < 3 {
|
||||
return fmt.Errorf("member %q of %q malformed 'protobuf' tag, not enough segments\n", m.Name, t.Name)
|
||||
}
|
||||
protoTag, err := strconv.Atoi(parts[1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("member %q of %q malformed 'protobuf' tag, field ID is %q which is not an integer: %v\n", m.Name, t.Name, parts[1], err)
|
||||
}
|
||||
field.Tag = protoTag
|
||||
|
||||
// In general there is doesn't make sense to parse the protobuf tags to get the type,
|
||||
// as all auto-generated once will have wire type "bytes", "varint" or "fixed64".
|
||||
// However, sometimes we explicitly set them to have a custom serialization, e.g.:
|
||||
// type Time struct {
|
||||
// time.Time `protobuf:"Timestamp,1,req,name=time"`
|
||||
// }
|
||||
// to force the generator to use a given type (that we manually wrote serialization &
|
||||
// deserialization methods for).
|
||||
switch parts[0] {
|
||||
case "varint", "fixed32", "fixed64", "bytes", "group":
|
||||
default:
|
||||
name := types.Name{}
|
||||
if last := strings.LastIndex(parts[0], "."); last != -1 {
|
||||
prefix := parts[0][:last]
|
||||
name = types.Name{
|
||||
Name: parts[0][last+1:],
|
||||
Package: prefix,
|
||||
Path: strings.Replace(prefix, ".", "/", -1),
|
||||
}
|
||||
} else {
|
||||
name = types.Name{
|
||||
Name: parts[0],
|
||||
Package: localPackage.Package,
|
||||
Path: localPackage.Path,
|
||||
}
|
||||
}
|
||||
field.Type = &types.Type{
|
||||
Name: name,
|
||||
Kind: types.Protobuf,
|
||||
}
|
||||
}
|
||||
|
||||
protoExtra := make(map[string]string)
|
||||
for i, extra := range parts[3:] {
|
||||
parts := strings.SplitN(extra, "=", 2)
|
||||
if len(parts) != 2 {
|
||||
return fmt.Errorf("member %q of %q malformed 'protobuf' tag, tag %d should be key=value, got %q\n", m.Name, t.Name, i+4, extra)
|
||||
}
|
||||
switch parts[0] {
|
||||
case "name":
|
||||
protoExtra[parts[0]] = parts[1]
|
||||
case "casttype", "castkey", "castvalue":
|
||||
parts[0] = fmt.Sprintf("(gogoproto.%s)", parts[0])
|
||||
protoExtra[parts[0]] = strconv.Quote(parts[1])
|
||||
}
|
||||
}
|
||||
|
||||
field.Extras = protoExtra
|
||||
if name, ok := protoExtra["name"]; ok {
|
||||
field.Name = name
|
||||
delete(protoExtra, "name")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func membersToFields(locator ProtobufLocator, t *types.Type, localPackage types.Name, omitFieldTypes map[types.Name]struct{}) ([]protoField, error) {
|
||||
fields := []protoField{}
|
||||
|
||||
for _, m := range t.Members {
|
||||
if namer.IsPrivateGoName(m.Name) {
|
||||
// skip private fields
|
||||
continue
|
||||
}
|
||||
if _, ok := omitFieldTypes[types.Name{Name: m.Type.Name.Name, Package: m.Type.Name.Package}]; ok {
|
||||
continue
|
||||
}
|
||||
tags := reflect.StructTag(m.Tags)
|
||||
field := protoField{
|
||||
LocalPackage: localPackage,
|
||||
|
||||
Tag: -1,
|
||||
Extras: make(map[string]string),
|
||||
}
|
||||
|
||||
protobufTag := tags.Get("protobuf")
|
||||
if protobufTag == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := protobufTagToField(protobufTag, &field, m, t, localPackage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// extract information from JSON field tag
|
||||
if tag := tags.Get("json"); len(tag) > 0 {
|
||||
parts := strings.Split(tag, ",")
|
||||
if len(field.Name) == 0 && len(parts[0]) != 0 {
|
||||
field.Name = parts[0]
|
||||
}
|
||||
if field.Tag == -1 && field.Name == "-" {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if field.Type == nil {
|
||||
if err := memberTypeToProtobufField(locator, &field, m.Type); err != nil {
|
||||
return nil, fmt.Errorf("unable to embed type %q as field %q in %q: %v", m.Type, field.Name, t.Name, err)
|
||||
}
|
||||
}
|
||||
if len(field.Name) == 0 {
|
||||
field.Name = namer.IL(m.Name)
|
||||
}
|
||||
|
||||
if field.Map && field.Repeated {
|
||||
// maps cannot be repeated
|
||||
field.Repeated = false
|
||||
field.Nullable = true
|
||||
}
|
||||
|
||||
if !field.Nullable {
|
||||
field.Extras["(gogoproto.nullable)"] = "false"
|
||||
}
|
||||
if (field.Type.Name.Name == "bytes" && field.Type.Name.Package == "") || (field.Repeated && field.Type.Name.Package == "" && namer.IsPrivateGoName(field.Type.Name.Name)) {
|
||||
delete(field.Extras, "(gogoproto.nullable)")
|
||||
}
|
||||
if field.Name != m.Name {
|
||||
field.Extras["(gogoproto.customname)"] = strconv.Quote(m.Name)
|
||||
}
|
||||
field.CommentLines = m.CommentLines
|
||||
fields = append(fields, field)
|
||||
}
|
||||
|
||||
// assign tags
|
||||
highest := 0
|
||||
byTag := make(map[int]*protoField)
|
||||
// fields are in Go struct order, which we preserve
|
||||
for i := range fields {
|
||||
field := &fields[i]
|
||||
tag := field.Tag
|
||||
if tag != -1 {
|
||||
if existing, ok := byTag[tag]; ok {
|
||||
return nil, fmt.Errorf("field %q and %q both have tag %d", field.Name, existing.Name, tag)
|
||||
}
|
||||
byTag[tag] = field
|
||||
}
|
||||
if tag > highest {
|
||||
highest = tag
|
||||
}
|
||||
}
|
||||
// starting from the highest observed tag, assign new field tags
|
||||
for i := range fields {
|
||||
field := &fields[i]
|
||||
if field.Tag != -1 {
|
||||
continue
|
||||
}
|
||||
highest++
|
||||
field.Tag = highest
|
||||
byTag[field.Tag] = field
|
||||
}
|
||||
return fields, nil
|
||||
}
|
||||
|
||||
func genComment(out io.Writer, lines []string, indent string) {
|
||||
for {
|
||||
l := len(lines)
|
||||
if l == 0 || len(lines[l-1]) != 0 {
|
||||
break
|
||||
}
|
||||
lines = lines[:l-1]
|
||||
}
|
||||
for _, c := range lines {
|
||||
fmt.Fprintf(out, "%s// %s\n", indent, c)
|
||||
}
|
||||
}
|
||||
|
||||
func formatProtoFile(source []byte) ([]byte, error) {
|
||||
// TODO; Is there any protobuf formatter?
|
||||
return source, nil
|
||||
}
|
||||
|
||||
func assembleProtoFile(w io.Writer, f *generator.File) {
|
||||
w.Write(f.Header)
|
||||
|
||||
fmt.Fprint(w, "syntax = 'proto2';\n\n")
|
||||
|
||||
if len(f.PackageName) > 0 {
|
||||
fmt.Fprintf(w, "package %s;\n\n", f.PackageName)
|
||||
}
|
||||
|
||||
if len(f.Imports) > 0 {
|
||||
imports := []string{}
|
||||
for i := range f.Imports {
|
||||
imports = append(imports, i)
|
||||
}
|
||||
sort.Strings(imports)
|
||||
for _, s := range imports {
|
||||
fmt.Fprintf(w, "import %q;\n", s)
|
||||
}
|
||||
fmt.Fprint(w, "\n")
|
||||
}
|
||||
|
||||
if f.Vars.Len() > 0 {
|
||||
fmt.Fprintf(w, "%s\n", f.Vars.String())
|
||||
}
|
||||
|
||||
w.Write(f.Body.Bytes())
|
||||
}
|
||||
|
||||
func NewProtoFile() *generator.DefaultFileType {
|
||||
return &generator.DefaultFileType{
|
||||
Format: formatProtoFile,
|
||||
Assemble: assembleProtoFile,
|
||||
}
|
||||
}
|
50
vendor/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/import_tracker.go
generated
vendored
Normal file
50
vendor/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/import_tracker.go
generated
vendored
Normal 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",
|
||||
},
|
||||
})
|
||||
}
|
208
vendor/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/namer.go
generated
vendored
Normal file
208
vendor/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/namer.go
generated
vendored
Normal file
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
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
|
||||
}
|
||||
if t.Name.Package == p.PackagePath {
|
||||
// Associate types only to their own package
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// isTypeApplicableToProtobuf checks to see if a type is relevant for protobuf processing.
|
||||
// Currently, it filters out functions and private types.
|
||||
func isTypeApplicableToProtobuf(t *types.Type) bool {
|
||||
// skip functions -- we don't care about them for protobuf
|
||||
if t.Kind == types.Func || (t.Kind == types.DeclarationOf && t.Underlying.Kind == types.Func) {
|
||||
return false
|
||||
}
|
||||
// skip private types
|
||||
if namer.IsPrivateGoName(t.Name.Name) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
if !isTypeApplicableToProtobuf(t) {
|
||||
// skip types that we don't care about, like functions
|
||||
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
|
||||
}
|
215
vendor/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/package.go
generated
vendored
Normal file
215
vendor/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/package.go
generated
vendored
Normal file
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
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, this package has been vendored into our source tree and thus can
|
||||
// only be generated by changing the vendor tree.
|
||||
Vendored bool
|
||||
|
||||
// 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{})
|
||||
)
|
452
vendor/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/parser.go
generated
vendored
Normal file
452
vendor/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/parser.go
generated
vendored
Normal 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/code-generator/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
|
||||
}
|
33
vendor/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/tags.go
generated
vendored
Normal file
33
vendor/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/tags.go
generated
vendored
Normal 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.Fatal(err)
|
||||
}
|
||||
return val
|
||||
}
|
32
vendor/k8s.io/code-generator/cmd/go-to-protobuf/protoc-gen-gogo/main.go
generated
vendored
Normal file
32
vendor/k8s.io/code-generator/cmd/go-to-protobuf/protoc-gen-gogo/main.go
generated
vendored
Normal 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()))
|
||||
}
|
1
vendor/k8s.io/code-generator/cmd/import-boss/.gitignore
generated
vendored
Normal file
1
vendor/k8s.io/code-generator/cmd/import-boss/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
import-boss
|
89
vendor/k8s.io/code-generator/cmd/import-boss/main.go
generated
vendored
Normal file
89
vendor/k8s.io/code-generator/cmd/import-boss/main.go
generated
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
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 second block explicitly matches the unsafe package, and forbids it
|
||||
// ("" is a prefix of everything).
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"k8s.io/code-generator/pkg/util"
|
||||
"k8s.io/gengo/args"
|
||||
"k8s.io/gengo/examples/import-boss/generators"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
arguments := args.Default()
|
||||
|
||||
// Override defaults.
|
||||
arguments.GoHeaderFilePath = filepath.Join(args.DefaultSourceTree(), util.BoilerplatePath())
|
||||
arguments.InputDirs = []string{
|
||||
"k8s.io/kubernetes/pkg/...",
|
||||
"k8s.io/kubernetes/cmd/...",
|
||||
"k8s.io/kubernetes/plugin/...",
|
||||
}
|
||||
|
||||
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.")
|
||||
}
|
77
vendor/k8s.io/code-generator/cmd/informer-gen/args/args.go
generated
vendored
Normal file
77
vendor/k8s.io/code-generator/cmd/informer-gen/args/args.go
generated
vendored
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package args
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
codegenutil "k8s.io/code-generator/pkg/util"
|
||||
"k8s.io/gengo/args"
|
||||
)
|
||||
|
||||
// CustomArgs is used by the gengo framework to pass args specific to this generator.
|
||||
type CustomArgs struct {
|
||||
VersionedClientSetPackage string
|
||||
InternalClientSetPackage string
|
||||
ListersPackage string
|
||||
SingleDirectory bool
|
||||
}
|
||||
|
||||
// NewDefaults returns default arguments for the generator.
|
||||
func NewDefaults() (*args.GeneratorArgs, *CustomArgs) {
|
||||
genericArgs := args.Default().WithoutDefaultFlagParsing()
|
||||
customArgs := &CustomArgs{
|
||||
SingleDirectory: false,
|
||||
}
|
||||
genericArgs.CustomArgs = customArgs
|
||||
|
||||
if pkg := codegenutil.CurrentPackage(); len(pkg) != 0 {
|
||||
genericArgs.OutputPackagePath = path.Join(pkg, "pkg/client/informers")
|
||||
customArgs.VersionedClientSetPackage = path.Join(pkg, "pkg/client/clientset/versioned")
|
||||
customArgs.InternalClientSetPackage = path.Join(pkg, "pkg/client/clientset/internalversion")
|
||||
customArgs.ListersPackage = path.Join(pkg, "pkg/client/listers")
|
||||
}
|
||||
|
||||
return genericArgs, customArgs
|
||||
}
|
||||
|
||||
// AddFlags add the generator flags to the flag set.
|
||||
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")
|
||||
fs.BoolVar(&ca.SingleDirectory, "single-directory", ca.SingleDirectory, "if true, omit the intermediate \"internalversion\" and \"externalversions\" subdirectories")
|
||||
}
|
||||
|
||||
// Validate checks the given arguments.
|
||||
func Validate(genericArgs *args.GeneratorArgs) error {
|
||||
customArgs := genericArgs.CustomArgs.(*CustomArgs)
|
||||
|
||||
if len(genericArgs.OutputPackagePath) == 0 {
|
||||
return fmt.Errorf("output package cannot be empty")
|
||||
}
|
||||
if len(customArgs.VersionedClientSetPackage) == 0 {
|
||||
return fmt.Errorf("versioned clientset package cannot be empty")
|
||||
}
|
||||
if len(customArgs.ListersPackage) == 0 {
|
||||
return fmt.Errorf("listers package cannot be empty")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
258
vendor/k8s.io/code-generator/cmd/informer-gen/generators/factory.go
generated
vendored
Normal file
258
vendor/k8s.io/code-generator/cmd/informer-gen/generators/factory.go
generated
vendored
Normal file
|
@ -0,0 +1,258 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/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
|
||||
gvGoNames map[string]string
|
||||
clientSetPackage string
|
||||
internalInterfacesPackage 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 groupPkgName := range g.groupVersions {
|
||||
gvInterfaces[groupPkgName] = c.Universe.Type(types.Name{Package: path.Join(g.outputPackage, groupPkgName), Name: "Interface"})
|
||||
gvNewFuncs[groupPkgName] = c.Universe.Function(types.Name{Package: path.Join(g.outputPackage, groupPkgName), Name: "New"})
|
||||
}
|
||||
m := map[string]interface{}{
|
||||
"cacheSharedIndexInformer": c.Universe.Type(cacheSharedIndexInformer),
|
||||
"groupVersions": g.groupVersions,
|
||||
"gvInterfaces": gvInterfaces,
|
||||
"gvNewFuncs": gvNewFuncs,
|
||||
"gvGoNames": g.gvGoNames,
|
||||
"interfacesNewInformerFunc": c.Universe.Type(types.Name{Package: g.internalInterfacesPackage, Name: "NewInformerFunc"}),
|
||||
"interfacesTweakListOptionsFunc": c.Universe.Type(types.Name{Package: g.internalInterfacesPackage, Name: "TweakListOptionsFunc"}),
|
||||
"informerFactoryInterface": c.Universe.Type(types.Name{Package: g.internalInterfacesPackage, Name: "SharedInformerFactory"}),
|
||||
"clientSetInterface": c.Universe.Type(types.Name{Package: g.clientSetPackage, Name: "Interface"}),
|
||||
"reflectType": c.Universe.Type(reflectType),
|
||||
"runtimeObject": c.Universe.Type(runtimeObject),
|
||||
"schemaGroupVersionResource": c.Universe.Type(schemaGroupVersionResource),
|
||||
"syncMutex": c.Universe.Type(syncMutex),
|
||||
"timeDuration": c.Universe.Type(timeDuration),
|
||||
"namespaceAll": c.Universe.Type(metav1NamespaceAll),
|
||||
"object": c.Universe.Type(metav1Object),
|
||||
}
|
||||
|
||||
sw.Do(sharedInformerFactoryStruct, m)
|
||||
sw.Do(sharedInformerFactoryInterface, m)
|
||||
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
var sharedInformerFactoryStruct = `
|
||||
// SharedInformerOption defines the functional option type for SharedInformerFactory.
|
||||
type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory
|
||||
|
||||
type sharedInformerFactory struct {
|
||||
client {{.clientSetInterface|raw}}
|
||||
namespace string
|
||||
tweakListOptions {{.interfacesTweakListOptionsFunc|raw}}
|
||||
lock {{.syncMutex|raw}}
|
||||
defaultResync {{.timeDuration|raw}}
|
||||
customResync map[{{.reflectType|raw}}]{{.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
|
||||
}
|
||||
|
||||
// WithCustomResyncConfig sets a custom resync period for the specified informer types.
|
||||
func WithCustomResyncConfig(resyncConfig map[{{.object|raw}}]{{.timeDuration|raw}}) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
for k, v := range resyncConfig {
|
||||
factory.customResync[reflect.TypeOf(k)] = v
|
||||
}
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory.
|
||||
func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
factory.tweakListOptions = tweakListOptions
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// WithNamespace limits the SharedInformerFactory to the specified namespace.
|
||||
func WithNamespace(namespace string) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
factory.namespace = namespace
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces.
|
||||
func NewSharedInformerFactory(client {{.clientSetInterface|raw}}, defaultResync {{.timeDuration|raw}}) SharedInformerFactory {
|
||||
return NewSharedInformerFactoryWithOptions(client, defaultResync)
|
||||
}
|
||||
|
||||
// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory.
|
||||
// Listers obtained via this SharedInformerFactory will be subject to the same filters
|
||||
// as specified here.
|
||||
// Deprecated: Please use NewSharedInformerFactoryWithOptions instead
|
||||
func NewFilteredSharedInformerFactory(client {{.clientSetInterface|raw}}, defaultResync {{.timeDuration|raw}}, namespace string, tweakListOptions {{.interfacesTweakListOptionsFunc|raw}}) SharedInformerFactory {
|
||||
return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions))
|
||||
}
|
||||
|
||||
// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options.
|
||||
func NewSharedInformerFactoryWithOptions(client {{.clientSetInterface|raw}}, defaultResync {{.timeDuration|raw}}, options ...SharedInformerOption) SharedInformerFactory {
|
||||
factory := &sharedInformerFactory{
|
||||
client: client,
|
||||
namespace: v1.NamespaceAll,
|
||||
defaultResync: defaultResync,
|
||||
informers: make(map[{{.reflectType|raw}}]{{.cacheSharedIndexInformer|raw}}),
|
||||
startedInformers: make(map[{{.reflectType|raw}}]bool),
|
||||
customResync: make(map[{{.reflectType|raw}}]{{.timeDuration|raw}}),
|
||||
}
|
||||
|
||||
// Apply all options
|
||||
for _, opt := range options {
|
||||
factory = opt(factory)
|
||||
}
|
||||
|
||||
return factory
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WaitForCacheSync waits for all started informers' cache were synced.
|
||||
func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool {
|
||||
informers := func()map[reflect.Type]cache.SharedIndexInformer{
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
informers := map[reflect.Type]cache.SharedIndexInformer{}
|
||||
for informerType, informer := range f.informers {
|
||||
if f.startedInformers[informerType] {
|
||||
informers[informerType] = informer
|
||||
}
|
||||
}
|
||||
return informers
|
||||
}()
|
||||
|
||||
res := map[reflect.Type]bool{}
|
||||
for informType, informer := range informers {
|
||||
res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// InternalInformerFor returns the SharedIndexInformer for obj using an internal
|
||||
// client.
|
||||
func (f *sharedInformerFactory) InformerFor(obj {{.runtimeObject|raw}}, newFunc {{.interfacesNewInformerFunc|raw}}) {{.cacheSharedIndexInformer|raw}} {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
informerType := reflect.TypeOf(obj)
|
||||
informer, exists := f.informers[informerType]
|
||||
if exists {
|
||||
return informer
|
||||
}
|
||||
|
||||
resyncPeriod, exists := f.customResync[informerType]
|
||||
if !exists {
|
||||
resyncPeriod = f.defaultResync
|
||||
}
|
||||
|
||||
informer = newFunc(f.client, resyncPeriod)
|
||||
f.informers[informerType] = informer
|
||||
|
||||
return informer
|
||||
}
|
||||
|
||||
`
|
||||
|
||||
var sharedInformerFactoryInterface = `
|
||||
// SharedInformerFactory provides shared informers for resources in all known
|
||||
// API group versions.
|
||||
type SharedInformerFactory interface {
|
||||
{{.informerFactoryInterface|raw}}
|
||||
ForResource(resource {{.schemaGroupVersionResource|raw}}) (GenericInformer, error)
|
||||
WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
|
||||
|
||||
{{$gvInterfaces := .gvInterfaces}}
|
||||
{{$gvGoNames := .gvGoNames}}
|
||||
{{range $groupName, $group := .groupVersions}}{{index $gvGoNames $groupName}}() {{index $gvInterfaces $groupName|raw}}
|
||||
{{end}}
|
||||
}
|
||||
|
||||
{{$gvNewFuncs := .gvNewFuncs}}
|
||||
{{$gvGoNames := .gvGoNames}}
|
||||
{{range $groupPkgName, $group := .groupVersions}}
|
||||
func (f *sharedInformerFactory) {{index $gvGoNames $groupPkgName}}() {{index $gvInterfaces $groupPkgName|raw}} {
|
||||
return {{index $gvNewFuncs $groupPkgName|raw}}(f, f.namespace, f.tweakListOptions)
|
||||
}
|
||||
{{end}}
|
||||
`
|
88
vendor/k8s.io/code-generator/cmd/informer-gen/generators/factoryinterface.go
generated
vendored
Normal file
88
vendor/k8s.io/code-generator/cmd/informer-gen/generators/factoryinterface.go
generated
vendored
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
// factoryInterfaceGenerator produces a file of interfaces used to break a dependency cycle for
|
||||
// informer registration
|
||||
type factoryInterfaceGenerator struct {
|
||||
generator.DefaultGen
|
||||
outputPackage string
|
||||
imports namer.ImportTracker
|
||||
clientSetPackage string
|
||||
filtered bool
|
||||
}
|
||||
|
||||
var _ generator.Generator = &factoryInterfaceGenerator{}
|
||||
|
||||
func (g *factoryInterfaceGenerator) Filter(c *generator.Context, t *types.Type) bool {
|
||||
if !g.filtered {
|
||||
g.filtered = true
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *factoryInterfaceGenerator) Namers(c *generator.Context) namer.NameSystems {
|
||||
return namer.NameSystems{
|
||||
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *factoryInterfaceGenerator) Imports(c *generator.Context) (imports []string) {
|
||||
imports = append(imports, g.imports.ImportLines()...)
|
||||
return
|
||||
}
|
||||
|
||||
func (g *factoryInterfaceGenerator) 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{}{
|
||||
"cacheSharedIndexInformer": c.Universe.Type(cacheSharedIndexInformer),
|
||||
"clientSetPackage": c.Universe.Type(types.Name{Package: g.clientSetPackage, Name: "Interface"}),
|
||||
"runtimeObject": c.Universe.Type(runtimeObject),
|
||||
"timeDuration": c.Universe.Type(timeDuration),
|
||||
"v1ListOptions": c.Universe.Type(v1ListOptions),
|
||||
}
|
||||
|
||||
sw.Do(externalSharedInformerFactoryInterface, m)
|
||||
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
var externalSharedInformerFactoryInterface = `
|
||||
type NewInformerFunc func({{.clientSetPackage|raw}}, {{.timeDuration|raw}}) cache.SharedIndexInformer
|
||||
|
||||
// SharedInformerFactory a small interface to allow for adding an informer without an import cycle
|
||||
type SharedInformerFactory interface {
|
||||
Start(stopCh <-chan struct{})
|
||||
InformerFor(obj {{.runtimeObject|raw}}, newFunc NewInformerFunc) {{.cacheSharedIndexInformer|raw}}
|
||||
}
|
||||
|
||||
type TweakListOptionsFunc func(*{{.v1ListOptions|raw}})
|
||||
`
|
180
vendor/k8s.io/code-generator/cmd/informer-gen/generators/generic.go
generated
vendored
Normal file
180
vendor/k8s.io/code-generator/cmd/informer-gen/generators/generic.go
generated
vendored
Normal file
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
)
|
||||
|
||||
// genericGenerator generates the generic informer.
|
||||
type genericGenerator struct {
|
||||
generator.DefaultGen
|
||||
outputPackage string
|
||||
imports namer.ImportTracker
|
||||
groupVersions map[string]clientgentypes.GroupVersions
|
||||
groupGoNames map[string]string
|
||||
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 {
|
||||
GroupGoName string
|
||||
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
|
||||
GoName 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 groupPackageName, groupVersions := range g.groupVersions {
|
||||
group := group{
|
||||
GroupGoName: g.groupGoNames[groupPackageName],
|
||||
Name: groupVersions.Group.NonEmpty(),
|
||||
Versions: []*version{},
|
||||
}
|
||||
for _, v := range groupVersions.Versions {
|
||||
gv := clientgentypes.GroupVersion{Group: groupVersions.Group, Version: v.Version}
|
||||
version := &version{
|
||||
Name: v.Version.NonEmpty(),
|
||||
GoName: namer.IC(v.Version.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 -}}{{$GroupGoName := .GroupGoName -}}
|
||||
{{range $version := .Versions -}}
|
||||
// Group={{$group.Name}}, Version={{.Name}}
|
||||
{{range .Resources -}}
|
||||
case {{index $.schemeGVs $version|raw}}.WithResource("{{.|allLowercasePlural}}"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.{{$GroupGoName}}().{{$version.GoName}}().{{.|publicPlural}}().Informer()}, nil
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end -}}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no informer found for %v", resource)
|
||||
}
|
||||
`
|
118
vendor/k8s.io/code-generator/cmd/informer-gen/generators/groupinterface.go
generated
vendored
Normal file
118
vendor/k8s.io/code-generator/cmd/informer-gen/generators/groupinterface.go
generated
vendored
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
)
|
||||
|
||||
// groupInterfaceGenerator generates the per-group interface file.
|
||||
type groupInterfaceGenerator struct {
|
||||
generator.DefaultGen
|
||||
outputPackage string
|
||||
imports namer.ImportTracker
|
||||
groupVersions clientgentypes.GroupVersions
|
||||
filtered bool
|
||||
internalInterfacesPackage string
|
||||
}
|
||||
|
||||
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.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.Version.NonEmpty()),
|
||||
Interface: iface,
|
||||
New: c.Universe.Function(types.Name{Package: versionPackage, Name: "New"}),
|
||||
})
|
||||
}
|
||||
m := map[string]interface{}{
|
||||
"interfacesTweakListOptionsFunc": c.Universe.Type(types.Name{Package: g.internalInterfacesPackage, Name: "TweakListOptionsFunc"}),
|
||||
"interfacesSharedInformerFactory": c.Universe.Type(types.Name{Package: g.internalInterfacesPackage, Name: "SharedInformerFactory"}),
|
||||
"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 {
|
||||
factory $.interfacesSharedInformerFactory|raw$
|
||||
namespace string
|
||||
tweakListOptions $.interfacesTweakListOptionsFunc|raw$
|
||||
}
|
||||
|
||||
// New returns a new Interface.
|
||||
func New(f $.interfacesSharedInformerFactory|raw$, namespace string, tweakListOptions $.interfacesTweakListOptionsFunc|raw$) Interface {
|
||||
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||
}
|
||||
|
||||
$range .versions$
|
||||
// $.Name$ returns a new $.Interface|raw$.
|
||||
func (g *group) $.Name$() $.Interface|raw$ {
|
||||
return $.New|raw$(g.factory, g.namespace, g.tweakListOptions)
|
||||
}
|
||||
$end$
|
||||
`
|
186
vendor/k8s.io/code-generator/cmd/informer-gen/generators/informer.go
generated
vendored
Normal file
186
vendor/k8s.io/code-generator/cmd/informer-gen/generators/informer.go
generated
vendored
Normal file
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
"k8s.io/code-generator/cmd/client-gen/generators/util"
|
||||
clientgentypes "k8s.io/code-generator/cmd/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
|
||||
groupPkgName string
|
||||
groupVersion clientgentypes.GroupVersion
|
||||
groupGoName string
|
||||
typeToGenerate *types.Type
|
||||
imports namer.ImportTracker
|
||||
clientSetPackage string
|
||||
listersPackage string
|
||||
internalInterfacesPackage 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 := fmt.Sprintf("%s/%s/%s", g.listersPackage, g.groupPkgName, strings.ToLower(g.groupVersion.Version.NonEmpty()))
|
||||
clientSetInterface := c.Universe.Type(types.Name{Package: g.clientSetPackage, Name: "Interface"})
|
||||
informerFor := "InformerFor"
|
||||
|
||||
tags, err := util.ParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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.groupGoName),
|
||||
"informerFor": informerFor,
|
||||
"interfacesTweakListOptionsFunc": c.Universe.Type(types.Name{Package: g.internalInterfacesPackage, Name: "TweakListOptionsFunc"}),
|
||||
"interfacesSharedInformerFactory": c.Universe.Type(types.Name{Package: g.internalInterfacesPackage, Name: "SharedInformerFactory"}),
|
||||
"listOptions": c.Universe.Type(listOptions),
|
||||
"lister": c.Universe.Type(types.Name{Package: listerPackage, Name: t.Name.Name + "Lister"}),
|
||||
"namespaceAll": c.Universe.Type(metav1NamespaceAll),
|
||||
"namespaced": !tags.NonNamespaced,
|
||||
"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)
|
||||
sw.Do(typeInformerPublicConstructor, m)
|
||||
sw.Do(typeFilteredInformerPublicConstructor, m)
|
||||
sw.Do(typeInformerConstructor, 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$
|
||||
tweakListOptions $.interfacesTweakListOptionsFunc|raw$
|
||||
$if .namespaced$namespace string$end$
|
||||
}
|
||||
`
|
||||
|
||||
var typeInformerPublicConstructor = `
|
||||
// New$.type|public$Informer constructs a new informer for $.type|public$ type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func New$.type|public$Informer(client $.clientSetInterface|raw$$if .namespaced$, namespace string$end$, resyncPeriod $.timeDuration|raw$, indexers $.cacheIndexers|raw$) $.cacheSharedIndexInformer|raw$ {
|
||||
return NewFiltered$.type|public$Informer(client$if .namespaced$, namespace$end$, resyncPeriod, indexers, nil)
|
||||
}
|
||||
`
|
||||
|
||||
var typeFilteredInformerPublicConstructor = `
|
||||
// NewFiltered$.type|public$Informer constructs a new informer for $.type|public$ type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewFiltered$.type|public$Informer(client $.clientSetInterface|raw$$if .namespaced$, namespace string$end$, resyncPeriod $.timeDuration|raw$, indexers $.cacheIndexers|raw$, tweakListOptions $.interfacesTweakListOptionsFunc|raw$) $.cacheSharedIndexInformer|raw$ {
|
||||
return $.cacheNewSharedIndexInformer|raw$(
|
||||
&$.cacheListWatch|raw${
|
||||
ListFunc: func(options $.v1ListOptions|raw$) ($.runtimeObject|raw$, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.$.group$$.version$().$.type|publicPlural$($if .namespaced$namespace$end$).List(options)
|
||||
},
|
||||
WatchFunc: func(options $.v1ListOptions|raw$) ($.watchInterface|raw$, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.$.group$$.version$().$.type|publicPlural$($if .namespaced$namespace$end$).Watch(options)
|
||||
},
|
||||
},
|
||||
&$.type|raw${},
|
||||
resyncPeriod,
|
||||
indexers,
|
||||
)
|
||||
}
|
||||
`
|
||||
|
||||
var typeInformerConstructor = `
|
||||
func (f *$.type|private$Informer) defaultInformer(client $.clientSetInterface|raw$, resyncPeriod $.timeDuration|raw$) $.cacheSharedIndexInformer|raw$ {
|
||||
return NewFiltered$.type|public$Informer(client$if .namespaced$, f.namespace$end$, resyncPeriod, $.cacheIndexers|raw${$.cacheNamespaceIndex|raw$: $.cacheMetaNamespaceIndexFunc|raw$}, f.tweakListOptions)
|
||||
}
|
||||
`
|
||||
|
||||
var typeInformerInformer = `
|
||||
func (f *$.type|private$Informer) Informer() $.cacheSharedIndexInformer|raw$ {
|
||||
return f.factory.$.informerFor$(&$.type|raw${}, f.defaultInformer)
|
||||
}
|
||||
`
|
||||
|
||||
var typeInformerLister = `
|
||||
func (f *$.type|private$Informer) Lister() $.lister|raw$ {
|
||||
return $.newLister|raw$(f.Informer().GetIndexer())
|
||||
}
|
||||
`
|
352
vendor/k8s.io/code-generator/cmd/informer-gen/generators/packages.go
generated
vendored
Normal file
352
vendor/k8s.io/code-generator/cmd/informer-gen/generators/packages.go
generated
vendored
Normal file
|
@ -0,0 +1,352 @@
|
|||
/*
|
||||
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"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/gengo/args"
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
|
||||
"k8s.io/code-generator/cmd/client-gen/generators/util"
|
||||
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
|
||||
informergenargs "k8s.io/code-generator/cmd/informer-gen/args"
|
||||
)
|
||||
|
||||
// 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"
|
||||
}
|
||||
|
||||
// objectMetaForPackage returns the type of ObjectMeta used by package p.
|
||||
func objectMetaForPackage(p *types.Package) (*types.Type, bool, error) {
|
||||
generatingForPackage := false
|
||||
for _, t := range p.Types {
|
||||
if !util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)).GenerateClient {
|
||||
continue
|
||||
}
|
||||
generatingForPackage = true
|
||||
for _, member := range t.Members {
|
||||
if member.Name == "ObjectMeta" {
|
||||
return member.Type, isInternal(member), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
if generatingForPackage {
|
||||
return nil, false, fmt.Errorf("unable to find ObjectMeta for any types in package %s", p.Path)
|
||||
}
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
// isInternal returns true if the tags for a member do not contain a json tag
|
||||
func isInternal(m types.Member) bool {
|
||||
return !strings.Contains(m.Tags, "json")
|
||||
}
|
||||
|
||||
func packageForInternalInterfaces(base string) string {
|
||||
return filepath.Join(base, "internalinterfaces")
|
||||
}
|
||||
|
||||
func vendorless(p string) string {
|
||||
if pos := strings.LastIndex(p, "/vendor/"); pos != -1 {
|
||||
return p[pos+len("/vendor/"):]
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// 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.(*informergenargs.CustomArgs)
|
||||
if !ok {
|
||||
glog.Fatalf("Wrong CustomArgs type: %T", arguments.CustomArgs)
|
||||
}
|
||||
|
||||
internalVersionPackagePath := filepath.Join(arguments.OutputPackagePath)
|
||||
externalVersionPackagePath := filepath.Join(arguments.OutputPackagePath)
|
||||
if !customArgs.SingleDirectory {
|
||||
internalVersionPackagePath = filepath.Join(arguments.OutputPackagePath, "internalversion")
|
||||
externalVersionPackagePath = filepath.Join(arguments.OutputPackagePath, "externalversions")
|
||||
}
|
||||
|
||||
var packageList generator.Packages
|
||||
typesForGroupVersion := make(map[clientgentypes.GroupVersion][]*types.Type)
|
||||
|
||||
externalGroupVersions := make(map[string]clientgentypes.GroupVersions)
|
||||
internalGroupVersions := make(map[string]clientgentypes.GroupVersions)
|
||||
groupGoNames := make(map[string]string)
|
||||
for _, inputDir := range arguments.InputDirs {
|
||||
p := context.Universe.Package(vendorless(inputDir))
|
||||
|
||||
objectMeta, internal, 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 targetGroupVersions map[string]clientgentypes.GroupVersions
|
||||
|
||||
if internal {
|
||||
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:])
|
||||
targetGroupVersions = internalGroupVersions
|
||||
} else {
|
||||
parts := strings.Split(p.Path, "/")
|
||||
gv.Group = clientgentypes.Group(parts[len(parts)-2])
|
||||
gv.Version = clientgentypes.Version(parts[len(parts)-1])
|
||||
targetGroupVersions = externalGroupVersions
|
||||
}
|
||||
groupPackageName := gv.Group.NonEmpty()
|
||||
gvPackage := path.Clean(p.Path)
|
||||
|
||||
// If there's a comment of the form "// +groupName=somegroup" or
|
||||
// "// +groupName=somegroup.foo.bar.io", use the first field (somegroup) as the name of the
|
||||
// group when generating.
|
||||
if override := types.ExtractCommentTags("+", p.Comments)["groupName"]; override != nil {
|
||||
gv.Group = clientgentypes.Group(override[0])
|
||||
}
|
||||
|
||||
// If there's a comment of the form "// +groupGoName=SomeUniqueShortName", use that as
|
||||
// the Go group identifier in CamelCase. It defaults
|
||||
groupGoNames[groupPackageName] = namer.IC(strings.Split(gv.Group.NonEmpty(), ".")[0])
|
||||
if override := types.ExtractCommentTags("+", p.Comments)["groupGoName"]; override != nil {
|
||||
groupGoNames[groupPackageName] = namer.IC(override[0])
|
||||
}
|
||||
|
||||
var typesToGenerate []*types.Type
|
||||
for _, t := range p.Types {
|
||||
tags := util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
if !tags.GenerateClient || tags.NoVerbs || !tags.HasVerb("list") || !tags.HasVerb("watch") {
|
||||
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
|
||||
}
|
||||
|
||||
groupVersionsEntry, ok := targetGroupVersions[groupPackageName]
|
||||
if !ok {
|
||||
groupVersionsEntry = clientgentypes.GroupVersions{
|
||||
PackageName: groupPackageName,
|
||||
Group: gv.Group,
|
||||
}
|
||||
}
|
||||
groupVersionsEntry.Versions = append(groupVersionsEntry.Versions, clientgentypes.PackageVersion{Version: gv.Version, Package: gvPackage})
|
||||
targetGroupVersions[groupPackageName] = groupVersionsEntry
|
||||
|
||||
orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)}
|
||||
typesToGenerate = orderer.OrderTypes(typesToGenerate)
|
||||
|
||||
if internal {
|
||||
packageList = append(packageList, versionPackage(internalVersionPackagePath, groupPackageName, gv, groupGoNames[groupPackageName], boilerplate, typesToGenerate, customArgs.InternalClientSetPackage, customArgs.ListersPackage))
|
||||
} else {
|
||||
packageList = append(packageList, versionPackage(externalVersionPackagePath, groupPackageName, gv, groupGoNames[groupPackageName], boilerplate, typesToGenerate, customArgs.VersionedClientSetPackage, customArgs.ListersPackage))
|
||||
}
|
||||
}
|
||||
|
||||
if len(externalGroupVersions) != 0 {
|
||||
packageList = append(packageList, factoryInterfacePackage(externalVersionPackagePath, boilerplate, customArgs.VersionedClientSetPackage))
|
||||
packageList = append(packageList, factoryPackage(externalVersionPackagePath, boilerplate, groupGoNames, externalGroupVersions, customArgs.VersionedClientSetPackage, typesForGroupVersion))
|
||||
for _, gvs := range externalGroupVersions {
|
||||
packageList = append(packageList, groupPackage(externalVersionPackagePath, gvs, boilerplate))
|
||||
}
|
||||
}
|
||||
|
||||
if len(internalGroupVersions) != 0 {
|
||||
packageList = append(packageList, factoryInterfacePackage(internalVersionPackagePath, boilerplate, customArgs.InternalClientSetPackage))
|
||||
packageList = append(packageList, factoryPackage(internalVersionPackagePath, boilerplate, groupGoNames, internalGroupVersions, customArgs.InternalClientSetPackage, typesForGroupVersion))
|
||||
for _, gvs := range internalGroupVersions {
|
||||
packageList = append(packageList, groupPackage(internalVersionPackagePath, gvs, boilerplate))
|
||||
}
|
||||
}
|
||||
|
||||
return packageList
|
||||
}
|
||||
|
||||
func factoryPackage(basePackage string, boilerplate []byte, groupGoNames map[string]string, groupVersions map[string]clientgentypes.GroupVersions, clientSetPackage 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,
|
||||
clientSetPackage: clientSetPackage,
|
||||
internalInterfacesPackage: packageForInternalInterfaces(basePackage),
|
||||
gvGoNames: groupGoNames,
|
||||
})
|
||||
|
||||
generators = append(generators, &genericGenerator{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: "generic",
|
||||
},
|
||||
outputPackage: basePackage,
|
||||
imports: generator.NewImportTracker(),
|
||||
groupVersions: groupVersions,
|
||||
typesForGroupVersion: typesForGroupVersion,
|
||||
groupGoNames: groupGoNames,
|
||||
})
|
||||
|
||||
return generators
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func factoryInterfacePackage(basePackage string, boilerplate []byte, clientSetPackage string) generator.Package {
|
||||
packagePath := packageForInternalInterfaces(basePackage)
|
||||
|
||||
return &generator.DefaultPackage{
|
||||
PackageName: filepath.Base(packagePath),
|
||||
PackagePath: packagePath,
|
||||
HeaderText: boilerplate,
|
||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
||||
generators = append(generators, &factoryInterfaceGenerator{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: "factory_interfaces",
|
||||
},
|
||||
outputPackage: packagePath,
|
||||
imports: generator.NewImportTracker(),
|
||||
clientSetPackage: clientSetPackage,
|
||||
})
|
||||
|
||||
return generators
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func groupPackage(basePackage string, groupVersions clientgentypes.GroupVersions, boilerplate []byte) generator.Package {
|
||||
packagePath := filepath.Join(basePackage, groupVersions.PackageName)
|
||||
groupPkgName := strings.Split(string(groupVersions.Group), ".")[0]
|
||||
|
||||
return &generator.DefaultPackage{
|
||||
PackageName: groupPkgName,
|
||||
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(),
|
||||
internalInterfacesPackage: packageForInternalInterfaces(basePackage),
|
||||
})
|
||||
return generators
|
||||
},
|
||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||
tags := util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
return tags.GenerateClient && tags.HasVerb("list") && tags.HasVerb("watch")
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func versionPackage(basePackage string, groupPkgName string, gv clientgentypes.GroupVersion, groupGoName string, boilerplate []byte, typesToGenerate []*types.Type, clientSetPackage, listersPackage string) generator.Package {
|
||||
packagePath := filepath.Join(basePackage, groupPkgName, 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,
|
||||
internalInterfacesPackage: packageForInternalInterfaces(basePackage),
|
||||
})
|
||||
|
||||
for _, t := range typesToGenerate {
|
||||
generators = append(generators, &informerGenerator{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: strings.ToLower(t.Name.Name),
|
||||
},
|
||||
outputPackage: packagePath,
|
||||
groupPkgName: groupPkgName,
|
||||
groupVersion: gv,
|
||||
groupGoName: groupGoName,
|
||||
typeToGenerate: t,
|
||||
imports: generator.NewImportTracker(),
|
||||
clientSetPackage: clientSetPackage,
|
||||
listersPackage: listersPackage,
|
||||
internalInterfacesPackage: packageForInternalInterfaces(basePackage),
|
||||
})
|
||||
}
|
||||
return generators
|
||||
},
|
||||
FilterFunc: func(c *generator.Context, t *types.Type) bool {
|
||||
tags := util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
return tags.GenerateClient && tags.HasVerb("list") && tags.HasVerb("watch")
|
||||
},
|
||||
}
|
||||
}
|
33
vendor/k8s.io/code-generator/cmd/informer-gen/generators/tags.go
generated
vendored
Normal file
33
vendor/k8s.io/code-generator/cmd/informer-gen/generators/tags.go
generated
vendored
Normal 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.Fatal(err)
|
||||
}
|
||||
return val
|
||||
}
|
42
vendor/k8s.io/code-generator/cmd/informer-gen/generators/types.go
generated
vendored
Normal file
42
vendor/k8s.io/code-generator/cmd/informer-gen/generators/types.go
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
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 (
|
||||
apiScheme = types.Name{Package: "k8s.io/kubernetes/pkg/api/legacyscheme", Name: "Scheme"}
|
||||
cacheGenericLister = types.Name{Package: "k8s.io/client-go/tools/cache", Name: "GenericLister"}
|
||||
cacheIndexers = types.Name{Package: "k8s.io/client-go/tools/cache", Name: "Indexers"}
|
||||
cacheListWatch = types.Name{Package: "k8s.io/client-go/tools/cache", Name: "ListWatch"}
|
||||
cacheMetaNamespaceIndexFunc = types.Name{Package: "k8s.io/client-go/tools/cache", Name: "MetaNamespaceIndexFunc"}
|
||||
cacheNamespaceIndex = types.Name{Package: "k8s.io/client-go/tools/cache", Name: "NamespaceIndex"}
|
||||
cacheNewGenericLister = types.Name{Package: "k8s.io/client-go/tools/cache", Name: "NewGenericLister"}
|
||||
cacheNewSharedIndexInformer = types.Name{Package: "k8s.io/client-go/tools/cache", Name: "NewSharedIndexInformer"}
|
||||
cacheSharedIndexInformer = types.Name{Package: "k8s.io/client-go/tools/cache", Name: "SharedIndexInformer"}
|
||||
listOptions = types.Name{Package: "k8s.io/kubernetes/pkg/apis/core", Name: "ListOptions"}
|
||||
reflectType = types.Name{Package: "reflect", Name: "Type"}
|
||||
runtimeObject = types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "Object"}
|
||||
schemaGroupResource = types.Name{Package: "k8s.io/apimachinery/pkg/runtime/schema", Name: "GroupResource"}
|
||||
schemaGroupVersionResource = types.Name{Package: "k8s.io/apimachinery/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/apimachinery/pkg/apis/meta/v1", Name: "ListOptions"}
|
||||
metav1NamespaceAll = types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "NamespaceAll"}
|
||||
metav1Object = types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "Object"}
|
||||
watchInterface = types.Name{Package: "k8s.io/apimachinery/pkg/watch", Name: "Interface"}
|
||||
)
|
109
vendor/k8s.io/code-generator/cmd/informer-gen/generators/versioninterface.go
generated
vendored
Normal file
109
vendor/k8s.io/code-generator/cmd/informer-gen/generators/versioninterface.go
generated
vendored
Normal file
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
"k8s.io/code-generator/cmd/client-gen/generators/util"
|
||||
)
|
||||
|
||||
// versionInterfaceGenerator generates the per-version interface file.
|
||||
type versionInterfaceGenerator struct {
|
||||
generator.DefaultGen
|
||||
outputPackage string
|
||||
imports namer.ImportTracker
|
||||
types []*types.Type
|
||||
filtered bool
|
||||
internalInterfacesPackage string
|
||||
}
|
||||
|
||||
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{}{
|
||||
"interfacesTweakListOptionsFunc": c.Universe.Type(types.Name{Package: g.internalInterfacesPackage, Name: "TweakListOptionsFunc"}),
|
||||
"interfacesSharedInformerFactory": c.Universe.Type(types.Name{Package: g.internalInterfacesPackage, Name: "SharedInformerFactory"}),
|
||||
"types": g.types,
|
||||
}
|
||||
|
||||
sw.Do(versionTemplate, m)
|
||||
for _, typeDef := range g.types {
|
||||
tags, err := util.ParseClientGenTags(typeDef.SecondClosestCommentLines)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m["namespaced"] = !tags.NonNamespaced
|
||||
m["type"] = typeDef
|
||||
sw.Do(versionFuncTemplate, 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 {
|
||||
factory $.interfacesSharedInformerFactory|raw$
|
||||
namespace string
|
||||
tweakListOptions $.interfacesTweakListOptionsFunc|raw$
|
||||
}
|
||||
|
||||
// New returns a new Interface.
|
||||
func New(f $.interfacesSharedInformerFactory|raw$, namespace string, tweakListOptions $.interfacesTweakListOptionsFunc|raw$) Interface {
|
||||
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||
}
|
||||
`
|
||||
|
||||
var versionFuncTemplate = `
|
||||
// $.type|publicPlural$ returns a $.type|public$Informer.
|
||||
func (v *version) $.type|publicPlural$() $.type|public$Informer {
|
||||
return &$.type|private$Informer{factory: v.factory$if .namespaced$, namespace: v.namespace$end$, tweakListOptions: v.tweakListOptions}
|
||||
}
|
||||
`
|
62
vendor/k8s.io/code-generator/cmd/informer-gen/main.go
generated
vendored
Normal file
62
vendor/k8s.io/code-generator/cmd/informer-gen/main.go
generated
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
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 (
|
||||
"flag"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/code-generator/cmd/informer-gen/generators"
|
||||
"k8s.io/code-generator/pkg/util"
|
||||
"k8s.io/gengo/args"
|
||||
|
||||
generatorargs "k8s.io/code-generator/cmd/informer-gen/args"
|
||||
)
|
||||
|
||||
func main() {
|
||||
genericArgs, customArgs := generatorargs.NewDefaults()
|
||||
|
||||
// Override defaults.
|
||||
// TODO: move out of informer-gen
|
||||
genericArgs.GoHeaderFilePath = filepath.Join(args.DefaultSourceTree(), util.BoilerplatePath())
|
||||
genericArgs.OutputPackagePath = "k8s.io/kubernetes/pkg/client/informers/informers_generated"
|
||||
customArgs.VersionedClientSetPackage = "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||
customArgs.InternalClientSetPackage = "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
customArgs.ListersPackage = "k8s.io/kubernetes/pkg/client/listers"
|
||||
|
||||
genericArgs.AddFlags(pflag.CommandLine)
|
||||
customArgs.AddFlags(pflag.CommandLine)
|
||||
flag.Set("logtostderr", "true")
|
||||
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
|
||||
pflag.Parse()
|
||||
|
||||
if err := generatorargs.Validate(genericArgs); err != nil {
|
||||
glog.Fatalf("Error: %v", err)
|
||||
}
|
||||
|
||||
// Run it.
|
||||
if err := genericArgs.Execute(
|
||||
generators.NameSystems(),
|
||||
generators.DefaultNameSystem(),
|
||||
generators.Packages,
|
||||
); err != nil {
|
||||
glog.Fatalf("Error: %v", err)
|
||||
}
|
||||
glog.V(2).Info("Completed successfully.")
|
||||
}
|
1
vendor/k8s.io/code-generator/cmd/lister-gen/.import-restrictions
generated
vendored
Normal file
1
vendor/k8s.io/code-generator/cmd/lister-gen/.import-restrictions
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
{}
|
56
vendor/k8s.io/code-generator/cmd/lister-gen/args/args.go
generated
vendored
Normal file
56
vendor/k8s.io/code-generator/cmd/lister-gen/args/args.go
generated
vendored
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package args
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
codegenutil "k8s.io/code-generator/pkg/util"
|
||||
"k8s.io/gengo/args"
|
||||
)
|
||||
|
||||
// CustomArgs is used by the gengo framework to pass args specific to this generator.
|
||||
type CustomArgs struct{}
|
||||
|
||||
// NewDefaults returns default arguments for the generator.
|
||||
func NewDefaults() (*args.GeneratorArgs, *CustomArgs) {
|
||||
genericArgs := args.Default().WithoutDefaultFlagParsing()
|
||||
customArgs := &CustomArgs{}
|
||||
genericArgs.CustomArgs = customArgs
|
||||
|
||||
if pkg := codegenutil.CurrentPackage(); len(pkg) != 0 {
|
||||
genericArgs.OutputPackagePath = path.Join(pkg, "pkg/client/listers")
|
||||
}
|
||||
|
||||
return genericArgs, customArgs
|
||||
}
|
||||
|
||||
// AddFlags add the generator flags to the flag set.
|
||||
func (ca *CustomArgs) AddFlags(fs *pflag.FlagSet) {}
|
||||
|
||||
// Validate checks the given arguments.
|
||||
func Validate(genericArgs *args.GeneratorArgs) error {
|
||||
_ = genericArgs.CustomArgs.(*CustomArgs)
|
||||
|
||||
if len(genericArgs.OutputPackagePath) == 0 {
|
||||
return fmt.Errorf("output package cannot be empty")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
67
vendor/k8s.io/code-generator/cmd/lister-gen/generators/expansion.go
generated
vendored
Normal file
67
vendor/k8s.io/code-generator/cmd/lister-gen/generators/expansion.go
generated
vendored
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
"k8s.io/code-generator/cmd/client-gen/generators/util"
|
||||
)
|
||||
|
||||
// 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 {
|
||||
tags := util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
if _, err := os.Stat(filepath.Join(g.packagePath, strings.ToLower(t.Name.Name+"_expansion.go"))); os.IsNotExist(err) {
|
||||
sw.Do(expansionInterfaceTemplate, t)
|
||||
if !tags.NonNamespaced {
|
||||
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$NamespaceLister.
|
||||
type $.|public$NamespaceListerExpansion interface {}
|
||||
`
|
371
vendor/k8s.io/code-generator/cmd/lister-gen/generators/lister.go
generated
vendored
Normal file
371
vendor/k8s.io/code-generator/cmd/lister-gen/generators/lister.go
generated
vendored
Normal file
|
@ -0,0 +1,371 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
"k8s.io/code-generator/cmd/client-gen/generators/util"
|
||||
clientgentypes "k8s.io/code-generator/cmd/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),
|
||||
"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"
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
var packageList generator.Packages
|
||||
for _, inputDir := range arguments.InputDirs {
|
||||
p := context.Universe.Package(inputDir)
|
||||
|
||||
objectMeta, internal, 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 internal {
|
||||
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], "/")
|
||||
}
|
||||
groupPackageName := strings.ToLower(gv.Group.NonEmpty())
|
||||
|
||||
// If there's a comment of the form "// +groupName=somegroup" or
|
||||
// "// +groupName=somegroup.foo.bar.io", use the first field (somegroup) as the name of the
|
||||
// group when generating.
|
||||
if override := types.ExtractCommentTags("+", p.Comments)["groupName"]; override != nil {
|
||||
gv.Group = clientgentypes.Group(strings.SplitN(override[0], ".", 2)[0])
|
||||
}
|
||||
|
||||
var typesToGenerate []*types.Type
|
||||
for _, t := range p.Types {
|
||||
tags := util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
if !tags.GenerateClient || !tags.HasVerb("list") || !tags.HasVerb("get") {
|
||||
continue
|
||||
}
|
||||
typesToGenerate = append(typesToGenerate, t)
|
||||
}
|
||||
if len(typesToGenerate) == 0 {
|
||||
continue
|
||||
}
|
||||
orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)}
|
||||
typesToGenerate = orderer.OrderTypes(typesToGenerate)
|
||||
|
||||
packagePath := filepath.Join(arguments.OutputPackagePath, groupPackageName, 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 {
|
||||
tags := util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
return tags.GenerateClient && tags.HasVerb("list") && tags.HasVerb("get")
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return packageList
|
||||
}
|
||||
|
||||
// objectMetaForPackage returns the type of ObjectMeta used by package p.
|
||||
func objectMetaForPackage(p *types.Package) (*types.Type, bool, error) {
|
||||
generatingForPackage := false
|
||||
for _, t := range p.Types {
|
||||
// filter out types which dont have genclient.
|
||||
if !util.MustParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...)).GenerateClient {
|
||||
continue
|
||||
}
|
||||
generatingForPackage = true
|
||||
for _, member := range t.Members {
|
||||
if member.Name == "ObjectMeta" {
|
||||
return member.Type, isInternal(member), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
if generatingForPackage {
|
||||
return nil, false, fmt.Errorf("unable to find ObjectMeta for any types in package %s", p.Path)
|
||||
}
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
// isInternal returns true if the tags for a member do not contain a json tag
|
||||
func isInternal(m types.Member) bool {
|
||||
return !strings.Contains(m.Tags, "json")
|
||||
}
|
||||
|
||||
// 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/apimachinery/pkg/api/errors")
|
||||
imports = append(imports, "k8s.io/apimachinery/pkg/labels")
|
||||
// for Indexer
|
||||
imports = append(imports, "k8s.io/client-go/tools/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: t.Name.Package, Name: "Resource"}),
|
||||
"type": t,
|
||||
"objectMeta": g.objectMeta,
|
||||
}
|
||||
|
||||
tags, err := util.ParseClientGenTags(append(t.SecondClosestCommentLines, t.CommentLines...))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if tags.NonNamespaced {
|
||||
sw.Do(typeListerInterface_NonNamespaced, m)
|
||||
} else {
|
||||
sw.Do(typeListerInterface, m)
|
||||
}
|
||||
|
||||
sw.Do(typeListerStruct, m)
|
||||
sw.Do(typeListerConstructor, m)
|
||||
sw.Do(typeLister_List, m)
|
||||
|
||||
if tags.NonNamespaced {
|
||||
sw.Do(typeLister_NonNamespacedGet, m)
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
sw.Do(typeLister_NamespaceLister, m)
|
||||
sw.Do(namespaceListerInterface, m)
|
||||
sw.Do(namespaceListerStruct, m)
|
||||
sw.Do(namespaceLister_List, m)
|
||||
sw.Do(namespaceLister_Get, 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) {
|
||||
obj, exists, err := s.indexer.GetByKey(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound($.Resource|raw$("$.type|lowercaseSingular$"), name)
|
||||
}
|
||||
return obj.(*$.type|raw$), nil
|
||||
}
|
||||
`
|
||||
|
||||
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
|
||||
}
|
||||
`
|
33
vendor/k8s.io/code-generator/cmd/lister-gen/generators/tags.go
generated
vendored
Normal file
33
vendor/k8s.io/code-generator/cmd/lister-gen/generators/tags.go
generated
vendored
Normal 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.Fatal(err)
|
||||
}
|
||||
return val
|
||||
}
|
59
vendor/k8s.io/code-generator/cmd/lister-gen/main.go
generated
vendored
Normal file
59
vendor/k8s.io/code-generator/cmd/lister-gen/main.go
generated
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
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 (
|
||||
"flag"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/code-generator/cmd/lister-gen/generators"
|
||||
"k8s.io/code-generator/pkg/util"
|
||||
"k8s.io/gengo/args"
|
||||
|
||||
generatorargs "k8s.io/code-generator/cmd/lister-gen/args"
|
||||
)
|
||||
|
||||
func main() {
|
||||
genericArgs, customArgs := generatorargs.NewDefaults()
|
||||
|
||||
// Override defaults.
|
||||
// TODO: move this out of lister-gen
|
||||
genericArgs.GoHeaderFilePath = filepath.Join(args.DefaultSourceTree(), util.BoilerplatePath())
|
||||
genericArgs.OutputPackagePath = "k8s.io/kubernetes/pkg/client/listers"
|
||||
|
||||
genericArgs.AddFlags(pflag.CommandLine)
|
||||
customArgs.AddFlags(pflag.CommandLine)
|
||||
flag.Set("logtostderr", "true")
|
||||
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
|
||||
pflag.Parse()
|
||||
|
||||
if err := generatorargs.Validate(genericArgs); err != nil {
|
||||
glog.Fatalf("Error: %v", err)
|
||||
}
|
||||
|
||||
// Run it.
|
||||
if err := genericArgs.Execute(
|
||||
generators.NameSystems(),
|
||||
generators.DefaultNameSystem(),
|
||||
generators.Packages,
|
||||
); err != nil {
|
||||
glog.Fatalf("Error: %v", err)
|
||||
}
|
||||
glog.V(2).Info("Completed successfully.")
|
||||
}
|
13
vendor/k8s.io/code-generator/cmd/openapi-gen/README
generated
vendored
Normal file
13
vendor/k8s.io/code-generator/cmd/openapi-gen/README
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Generate OpenAPI definitions
|
||||
|
||||
- To generate definition for a specific type or package add "+k8s:openapi-gen=true" tag to the type/package comment lines.
|
||||
- To exclude a type or a member from a tagged package/type, add "+k8s:openapi-gen=false" tag to the comment lines.
|
||||
|
||||
# OpenAPI Extensions
|
||||
OpenAPI spec can have extensions on types. To define one or more extensions on a type or its member
|
||||
add "+k8s:openapi-gen=x-kubernetes-$NAME:$VALUE" to the comment lines before type/member. A type/member can
|
||||
have multiple extensions. The rest of the line in the comment will be used as $VALUE so there is no need to
|
||||
escape or quote the value string. Extensions can be use to pass more information to client generators or
|
||||
documentation generators. For example a type my have a friendly name to be displayed in documentation or
|
||||
being used in a client's fluent interface.
|
||||
|
53
vendor/k8s.io/code-generator/cmd/openapi-gen/args/args.go
generated
vendored
Normal file
53
vendor/k8s.io/code-generator/cmd/openapi-gen/args/args.go
generated
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
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 args
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/gengo/args"
|
||||
)
|
||||
|
||||
// CustomArgs is used by the gengo framework to pass args specific to this generator.
|
||||
type CustomArgs struct{}
|
||||
|
||||
// NewDefaults returns default arguments for the generator.
|
||||
func NewDefaults() (*args.GeneratorArgs, *CustomArgs) {
|
||||
genericArgs := args.Default().WithoutDefaultFlagParsing()
|
||||
customArgs := &CustomArgs{}
|
||||
genericArgs.CustomArgs = customArgs
|
||||
genericArgs.OutputFileBaseName = "openapi_generated"
|
||||
return genericArgs, customArgs
|
||||
}
|
||||
|
||||
// AddFlags add the generator flags to the flag set.
|
||||
func (ca *CustomArgs) AddFlags(fs *pflag.FlagSet) {}
|
||||
|
||||
// Validate checks the given arguments.
|
||||
func Validate(genericArgs *args.GeneratorArgs) error {
|
||||
_ = genericArgs.CustomArgs.(*CustomArgs)
|
||||
|
||||
if len(genericArgs.OutputFileBaseName) == 0 {
|
||||
return fmt.Errorf("output file base name cannot be empty")
|
||||
}
|
||||
if len(genericArgs.OutputPackagePath) == 0 {
|
||||
return fmt.Errorf("output package cannot be empty")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
61
vendor/k8s.io/code-generator/cmd/openapi-gen/main.go
generated
vendored
Normal file
61
vendor/k8s.io/code-generator/cmd/openapi-gen/main.go
generated
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
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 generates openAPI definition file to be used in open API spec generation on API servers. To generate
|
||||
// definition for a specific type or package add "+k8s:openapi-gen=true" tag to the type/package comment lines. To
|
||||
// exclude a type from a tagged package, add "+k8s:openapi-gen=false" tag to the type comment lines.
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/gengo/args"
|
||||
"k8s.io/kube-openapi/pkg/generators"
|
||||
|
||||
generatorargs "k8s.io/code-generator/cmd/openapi-gen/args"
|
||||
"k8s.io/code-generator/pkg/util"
|
||||
)
|
||||
|
||||
func main() {
|
||||
genericArgs, customArgs := generatorargs.NewDefaults()
|
||||
|
||||
// Override defaults.
|
||||
// TODO: move this out of openapi-gen
|
||||
genericArgs.GoHeaderFilePath = filepath.Join(args.DefaultSourceTree(), util.BoilerplatePath())
|
||||
|
||||
genericArgs.AddFlags(pflag.CommandLine)
|
||||
customArgs.AddFlags(pflag.CommandLine)
|
||||
flag.Set("logtostderr", "true")
|
||||
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
|
||||
pflag.Parse()
|
||||
|
||||
if err := generatorargs.Validate(genericArgs); err != nil {
|
||||
glog.Fatalf("Error: %v", err)
|
||||
}
|
||||
|
||||
// Run it.
|
||||
if err := genericArgs.Execute(
|
||||
generators.NameSystems(),
|
||||
generators.DefaultNameSystem(),
|
||||
generators.Packages,
|
||||
); err != nil {
|
||||
glog.Fatalf("Error: %v", err)
|
||||
}
|
||||
glog.V(2).Info("Completed successfully.")
|
||||
}
|
1
vendor/k8s.io/code-generator/cmd/set-gen/.gitignore
generated
vendored
Normal file
1
vendor/k8s.io/code-generator/cmd/set-gen/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
set-gen
|
55
vendor/k8s.io/code-generator/cmd/set-gen/main.go
generated
vendored
Normal file
55
vendor/k8s.io/code-generator/cmd/set-gen/main.go
generated
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// set-gen is an example usage of gengo.
|
||||
//
|
||||
// Structs in the input directories with the below line in their comments will
|
||||
// have sets generated for them.
|
||||
// // +genset
|
||||
//
|
||||
// Any builtin type referenced anywhere in the input directories will have a
|
||||
// set generated for it.
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"k8s.io/code-generator/pkg/util"
|
||||
"k8s.io/gengo/args"
|
||||
"k8s.io/gengo/examples/set-gen/generators"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
arguments := args.Default()
|
||||
|
||||
// Override defaults.
|
||||
arguments.GoHeaderFilePath = filepath.Join(args.DefaultSourceTree(), util.BoilerplatePath())
|
||||
arguments.InputDirs = []string{"k8s.io/kubernetes/pkg/util/sets/types"}
|
||||
arguments.OutputPackagePath = "k8s.io/apimachinery/pkg/util/sets"
|
||||
|
||||
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.")
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue