Merge pull request #28579 from thockin/dont-checkin-generated-code-prep-2

Automatic merge from submit-queue

Prep for not checking in generated, part 2/2

This PR is extracted from #25978 and build on #28578 - it is just the conversion related parts. All the Makefile stuff is excluded.

@wojtek-t this is literally branched, a bunch of commits deleted, and a very small number of manual fixups applied. If you think this is easier to review (and if it passes CI) you can feel free to go over it again. I will follow this with a conversion-related PR to build on this.

Or if you prefer, just close this and let the mega-PR ride.

@lavalamp
pull/6/head
k8s-merge-robot 2016-07-08 01:05:00 -07:00 committed by GitHub
commit dbab1a8477
30 changed files with 639 additions and 482 deletions

View File

@ -32,6 +32,19 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
) )
// CustomArgs is used tby the go2idl framework to pass args specific to this
// generator.
type CustomArgs struct {
ExtraPeerDirs []string // Always consider these as last-ditch possibilities for conversions.
}
// This is the comment tag that carries parameters for conversion generation.
const tagName = "k8s:conversion-gen"
func extractTag(comments []string) []string {
return types.ExtractCommentTags("+", comments)[tagName]
}
// TODO: This is created only to reduce number of changes in a single PR. // TODO: This is created only to reduce number of changes in a single PR.
// Remove it and use PublicNamer instead. // Remove it and use PublicNamer instead.
func conversionNamer() *namer.NameStrategy { func conversionNamer() *namer.NameStrategy {
@ -67,139 +80,125 @@ func DefaultNameSystem() string {
return "public" return "public"
} }
var fallbackPackages = []string{ func getPeerTypeFor(context *generator.Context, t *types.Type, potenialPeerPkgs []string) *types.Type {
"k8s.io/kubernetes/pkg/api/unversioned", for _, ppp := range potenialPeerPkgs {
"k8s.io/kubernetes/pkg/apis/extensions", p := context.Universe.Package(ppp)
"k8s.io/kubernetes/pkg/apis/autoscaling", if p == nil {
"k8s.io/kubernetes/pkg/apis/batch", continue
} }
if p.Has(t.Name.Name) {
func getInternalTypeFor(context *generator.Context, t *types.Type) (*types.Type, bool) { return p.Type(t.Name.Name)
internalPackage := filepath.Dir(t.Name.Package)
if !context.Universe.Package(internalPackage).Has(t.Name.Name) {
for _, fallbackPackage := range fallbackPackages {
if fallbackPackage == t.Name.Package || !context.Universe.Package(fallbackPackage).Has(t.Name.Name) {
continue
}
return context.Universe.Package(fallbackPackage).Type(t.Name.Name), true
} }
return nil, false
} }
return context.Universe.Package(internalPackage).Type(t.Name.Name), true return nil
} }
type conversionType struct { type conversionPair struct {
inType *types.Type inType *types.Type
outType *types.Type outType *types.Type
} }
// All of the types in conversions map are of type "DeclarationOf" with // All of the types in conversions map are of type "DeclarationOf" with
// the underlying type being "Func". // the underlying type being "Func".
type conversions map[conversionType]*types.Type type conversionFuncMap map[conversionPair]*types.Type
// Returns all already existing conversion functions that we are able to find. // Returns all manually-defined conversion functions in the package.
func existingConversionFunctions(context *generator.Context) conversions { func getManualConversionFunctions(context *generator.Context, pkg *types.Package, manualMap conversionFuncMap) {
scopeName := types.Name{Package: conversionPackagePath, Name: "Scope"} scopeName := types.Name{Package: conversionPackagePath, Name: "Scope"}
errorName := types.Name{Package: "", Name: "error"} errorName := types.Name{Package: "", Name: "error"}
buffer := &bytes.Buffer{} buffer := &bytes.Buffer{}
sw := generator.NewSnippetWriter(buffer, context, "$", "$") sw := generator.NewSnippetWriter(buffer, context, "$", "$")
preexisting := make(conversions) for _, f := range pkg.Functions {
for _, p := range context.Universe { if f.Underlying == nil || f.Underlying.Kind != types.Func {
for _, f := range p.Functions { glog.Errorf("Malformed function: %#v", f)
if f.Underlying == nil || f.Underlying.Kind != types.Func { continue
glog.Errorf("Malformed function: %#v", f)
continue
}
if f.Underlying.Signature == nil {
glog.Errorf("Function without signature: %#v", f)
continue
}
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 {
continue
}
if len(signature.Parameters) != 3 || signature.Parameters[2].Name != scopeName {
continue
}
if len(signature.Results) != 1 || signature.Results[0].Name != errorName {
continue
}
inType := signature.Parameters[0]
outType := signature.Parameters[1]
if inType.Kind != types.Pointer || outType.Kind != types.Pointer {
continue
}
// Now check if the name satisfies the convention.
args := argsFromType(inType.Elem, outType.Elem)
sw.Do("Convert_$.inType|public$_To_$.outType|public$", args)
if f.Name.Name == buffer.String() {
key := conversionType{inType.Elem, outType.Elem}
if v, ok := preexisting[key]; ok && v != nil {
panic(fmt.Sprintf("duplicate static conversion defined: %#v", key))
}
preexisting[key] = f
}
buffer.Reset()
} }
if f.Underlying.Signature == nil {
glog.Errorf("Function without signature: %#v", f)
continue
}
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 {
continue
}
if len(signature.Parameters) != 3 || signature.Parameters[2].Name != scopeName {
continue
}
if len(signature.Results) != 1 || signature.Results[0].Name != errorName {
continue
}
inType := signature.Parameters[0]
outType := signature.Parameters[1]
if inType.Kind != types.Pointer || outType.Kind != types.Pointer {
continue
}
// Now check if the name satisfies the convention.
args := argsFromType(inType.Elem, outType.Elem)
sw.Do("Convert_$.inType|public$_To_$.outType|public$", args)
if f.Name.Name == buffer.String() {
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: %#v", key))
}
manualMap[key] = f
}
buffer.Reset()
} }
return preexisting
} }
// All of the types in conversions map are of type "DeclarationOf" with // All of the types in conversions map are of type "DeclarationOf" with
// the underlying type being "Func". // the underlying type being "Func".
type defaulters map[*types.Type]*types.Type type defaulterFuncMap map[*types.Type]*types.Type
// Returns all already existing defaulting functions that we are able to find. // Returns all manually-defined defaulting functions in the package.
func existingDefaultingFunctions(context *generator.Context) defaulters { func getManualDefaultingFunctions(context *generator.Context, pkg *types.Package, manualMap defaulterFuncMap) {
buffer := &bytes.Buffer{} buffer := &bytes.Buffer{}
sw := generator.NewSnippetWriter(buffer, context, "$", "$") sw := generator.NewSnippetWriter(buffer, context, "$", "$")
preexisting := make(defaulters) for _, f := range pkg.Functions {
for _, p := range context.Universe { if f.Underlying == nil || f.Underlying.Kind != types.Func {
for _, f := range p.Functions { glog.Errorf("Malformed function: %#v", f)
if f.Underlying == nil || f.Underlying.Kind != types.Func { continue
glog.Errorf("Malformed function: %#v", f)
continue
}
if f.Underlying.Signature == nil {
glog.Errorf("Function without signature: %#v", f)
continue
}
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 {
continue
}
if len(signature.Parameters) != 1 {
continue
}
if len(signature.Results) != 0 {
continue
}
inType := signature.Parameters[0]
if inType.Kind != types.Pointer {
continue
}
// Now check if the name satisfies the convention.
args := defaultingArgsFromType(inType.Elem)
sw.Do("$.inType|defaultfn$", args)
if f.Name.Name == buffer.String() {
key := inType.Elem
if v, ok := preexisting[key]; ok && v != nil {
panic(fmt.Sprintf("duplicate static defaulter defined: %#v", key))
}
preexisting[key] = f
}
buffer.Reset()
} }
if f.Underlying.Signature == nil {
glog.Errorf("Function without signature: %#v", f)
continue
}
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 {
continue
}
if len(signature.Parameters) != 1 {
continue
}
if len(signature.Results) != 0 {
continue
}
inType := signature.Parameters[0]
if inType.Kind != types.Pointer {
continue
}
// Now check if the name satisfies the convention.
args := defaultingArgsFromType(inType.Elem)
sw.Do("$.inType|defaultfn$", args)
if f.Name.Name == buffer.String() {
key := inType.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 defaulter defined: %#v", key))
}
manualMap[key] = f
}
buffer.Reset()
} }
return preexisting
} }
func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages { func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
@ -208,7 +207,7 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
glog.Fatalf("Failed loading boilerplate: %v", err) glog.Fatalf("Failed loading boilerplate: %v", err)
} }
inputs := sets.NewString(arguments.InputDirs...) inputs := sets.NewString(context.Inputs...)
packages := generator.Packages{} packages := generator.Packages{}
header := append([]byte(fmt.Sprintf("// +build !%s\n\n", arguments.GeneratedBuildTag)), boilerplate...) header := append([]byte(fmt.Sprintf("// +build !%s\n\n", arguments.GeneratedBuildTag)), boilerplate...)
header = append(header, []byte( header = append(header, []byte(
@ -217,65 +216,89 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
`)...) `)...)
// Compute all pre-existing conversion functions. // Accumulate pre-existing conversion and default functions.
preexisting := existingConversionFunctions(context) // TODO: This is too ad-hoc. We need a better way.
preexistingDefaults := existingDefaultingFunctions(context) manualConversions := conversionFuncMap{}
manualDefaults := defaulterFuncMap{}
// We are generating conversions only for packages that are explicitly // We are generating conversions only for packages that are explicitly
// passed as InputDir, and only for those that have a corresponding type // passed as InputDir.
// (in the directory one above) and can be automatically converted to. for i := range inputs {
for _, p := range context.Universe { glog.V(5).Infof("considering pkg %q", i)
path := p.Path pkg := context.Universe[i]
if !inputs.Has(path) { if pkg == nil {
continue // If the input had no Go files, for example.
}
// Only generate conversions for package which explicitly requested it
// byt setting "+genversion=true" in their doc.go file.
filtered := false
if extractBoolTagOrDie("genconversion", false, p.DocComments) == true {
filtered = true
}
if !filtered {
continue continue
} }
convertibleType := false // Add conversion and defaulting functions.
for _, t := range p.Types { getManualConversionFunctions(context, pkg, manualConversions)
// Check whether this type can be auto-converted to the internal getManualDefaultingFunctions(context, pkg, manualDefaults)
// version.
internalType, exists := getInternalTypeFor(context, t) // Only generate conversions for packages which explicitly request it
if !exists { // by specifying one or more "+k8s:conversion-gen=<peer-pkg>"
// There is no corresponding type in the internal package. // 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
}
if customArgs, ok := arguments.CustomArgs.(*CustomArgs); ok {
if len(customArgs.ExtraPeerDirs) > 0 {
peerPkgs = append(peerPkgs, customArgs.ExtraPeerDirs...)
}
}
// Make sure our peer-packages are added and fully parsed.
for _, pp := range peerPkgs {
context.AddDir(pp)
getManualConversionFunctions(context, context.Universe[pp], manualConversions)
getManualDefaultingFunctions(context, context.Universe[pp], manualDefaults)
}
pkgNeedsGeneration := false
for _, t := range pkg.Types {
// Check whether this type can be auto-converted to the peer
// package type.
peerType := getPeerTypeFor(context, t, peerPkgs)
if peerType == nil {
// We did not find a corresponding type.
continue continue
} }
// We won't be able to convert to private type. if namer.IsPrivateGoName(peerType.Name.Name) {
if namer.IsPrivateGoName(internalType.Name.Name) { // We won't be able to convert to a private type.
glog.V(5).Infof(" found a peer type %v, but it is a private name", t)
continue continue
} }
// If we can generate conversion in any direction, we should // If we can generate conversion in any direction, we should
// generate this package. // generate this package.
if isConvertible(t, internalType, preexisting) || isConvertible(internalType, t, preexisting) { if isConvertible(t, peerType, manualConversions) || isConvertible(peerType, t, manualConversions) {
convertibleType = true pkgNeedsGeneration = true
break
} }
} }
if !pkgNeedsGeneration {
if convertibleType { glog.V(5).Infof(" no viable conversions, not generating for this package")
packages = append(packages, continue
&generator.DefaultPackage{
PackageName: filepath.Base(path),
PackagePath: path,
HeaderText: header,
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
generators = []generator.Generator{}
generators = append(
generators, NewGenConversion("conversion_generated", path, preexisting, preexistingDefaults))
return generators
},
FilterFunc: func(c *generator.Context, t *types.Type) bool {
return t.Name.Package == path
},
})
} }
packages = append(packages,
&generator.DefaultPackage{
PackageName: filepath.Base(pkg.Path),
PackagePath: pkg.Path,
HeaderText: header,
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
generators = []generator.Generator{}
generators = append(
generators, NewGenConversion(arguments.OutputFileBaseName, pkg.Path, manualConversions, manualDefaults, peerPkgs))
return generators
},
FilterFunc: func(c *generator.Context, t *types.Type) bool {
return t.Name.Package == pkg.Path
},
})
} }
return packages return packages
} }
@ -292,23 +315,26 @@ func findMember(t *types.Type, name string) (types.Member, bool) {
return types.Member{}, false return types.Member{}, false
} }
func isConvertible(in, out *types.Type, preexisting conversions) bool { func isConvertible(in, out *types.Type, manualConversions conversionFuncMap) bool {
// If there is pre-existing conversion function, return true immediately. // If there is pre-existing conversion function, return true immediately.
if _, ok := preexisting[conversionType{in, out}]; ok { if _, ok := manualConversions[conversionPair{in, out}]; ok {
return true return true
} }
return isDirectlyConvertible(in, out, preexisting) return isDirectlyConvertible(in, out, manualConversions)
} }
func isDirectlyConvertible(in, out *types.Type, preexisting conversions) bool { func isDirectlyConvertible(in, out *types.Type, manualConversions conversionFuncMap) bool {
// If one of the types is Alias, resolve it. // If one of the types is Alias, resolve it.
if in.Kind == types.Alias { if in.Kind == types.Alias {
return isConvertible(in.Underlying, out, preexisting) return isConvertible(in.Underlying, out, manualConversions)
} }
if out.Kind == types.Alias { if out.Kind == types.Alias {
return isConvertible(in, out.Underlying, preexisting) return isConvertible(in, out.Underlying, manualConversions)
} }
if in == out {
return true
}
if in.Kind != out.Kind { if in.Kind != out.Kind {
return false return false
} }
@ -318,18 +344,9 @@ func isDirectlyConvertible(in, out *types.Type, preexisting conversions) bool {
// We don't support conversion of other types yet. // We don't support conversion of other types yet.
return false return false
} }
switch out.Kind {
case types.Builtin, types.Struct, types.Map, types.Slice, types.Pointer:
default:
// We don't support conversion of other types yet.
return false
}
switch in.Kind { switch in.Kind {
case types.Builtin: case types.Builtin:
if in == out {
return true
}
// TODO: Support more conversion types. // TODO: Support more conversion types.
return types.IsInteger(in) && types.IsInteger(out) return types.IsInteger(in) && types.IsInteger(out)
case types.Struct: case types.Struct:
@ -338,24 +355,24 @@ func isDirectlyConvertible(in, out *types.Type, preexisting conversions) bool {
// Check if there is an out member with that name. // Check if there is an out member with that name.
outMember, found := findMember(out, inMember.Name) outMember, found := findMember(out, inMember.Name)
if !found { if !found {
// Check if the member doesn't have comment: // Check if the member has opted out with:
// "+ genconversion=false" // "+k8s:conversion-gen=false"
// comment to ignore this field for conversion.
// TODO: Switch to SecondClosestCommentLines. // TODO: Switch to SecondClosestCommentLines.
if extractBoolTagOrDie("genconversion", true, inMember.CommentLines) == false { if tagvals := extractTag(inMember.CommentLines); tagvals != nil && tagvals[0] == "false" {
glog.V(5).Infof("field %v.%s requests no conversion generation, skipping", in, inMember.Name)
continue continue
} }
return false return false
} }
convertible = convertible && isConvertible(inMember.Type, outMember.Type, preexisting) convertible = convertible && isConvertible(inMember.Type, outMember.Type, manualConversions)
} }
return convertible return convertible
case types.Map: case types.Map:
return isConvertible(in.Key, out.Key, preexisting) && isConvertible(in.Elem, out.Elem, preexisting) return isConvertible(in.Key, out.Key, manualConversions) && isConvertible(in.Elem, out.Elem, manualConversions)
case types.Slice: case types.Slice:
return isConvertible(in.Elem, out.Elem, preexisting) return isConvertible(in.Elem, out.Elem, manualConversions)
case types.Pointer: case types.Pointer:
return isConvertible(in.Elem, out.Elem, preexisting) return isConvertible(in.Elem, out.Elem, manualConversions)
} }
glog.Fatalf("All other types should be filtered before") glog.Fatalf("All other types should be filtered before")
return false return false
@ -389,25 +406,27 @@ const (
// genConversion produces a file with a autogenerated conversions. // genConversion produces a file with a autogenerated conversions.
type genConversion struct { type genConversion struct {
generator.DefaultGen generator.DefaultGen
targetPackage string targetPackage string
preexisting conversions peerPackages []string
defaulters defaulters manualConversions conversionFuncMap
imports namer.ImportTracker manualDefaulters defaulterFuncMap
typesForInit []conversionType imports namer.ImportTracker
typesForInit []conversionPair
globalVariables map[string]interface{} globalVariables map[string]interface{}
} }
func NewGenConversion(sanitizedName, targetPackage string, preexisting conversions, defaulters defaulters) generator.Generator { func NewGenConversion(sanitizedName, targetPackage string, manualConversions conversionFuncMap, manualDefaulters defaulterFuncMap, peerPkgs []string) generator.Generator {
return &genConversion{ return &genConversion{
DefaultGen: generator.DefaultGen{ DefaultGen: generator.DefaultGen{
OptionalName: sanitizedName, OptionalName: sanitizedName,
}, },
targetPackage: targetPackage, targetPackage: targetPackage,
preexisting: preexisting, peerPackages: peerPkgs,
defaulters: defaulters, manualConversions: manualConversions,
imports: generator.NewImportTracker(), manualDefaulters: manualDefaulters,
typesForInit: make([]conversionType, 0), imports: generator.NewImportTracker(),
typesForInit: make([]conversionPair, 0),
} }
} }
@ -428,7 +447,13 @@ func (g *genConversion) convertibleOnlyWithinPackage(inType, outType *types.Type
if t.Name.Package != g.targetPackage { if t.Name.Package != g.targetPackage {
return false return false
} }
if extractBoolTagOrDie("genconversion", true, t.CommentLines) == 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 return false
} }
// TODO: Consider generating functions for other kinds too. // TODO: Consider generating functions for other kinds too.
@ -443,22 +468,22 @@ func (g *genConversion) convertibleOnlyWithinPackage(inType, outType *types.Type
} }
func (g *genConversion) Filter(c *generator.Context, t *types.Type) bool { func (g *genConversion) Filter(c *generator.Context, t *types.Type) bool {
internalType, exists := getInternalTypeFor(c, t) peerType := getPeerTypeFor(c, t, g.peerPackages)
if !exists { if peerType == nil {
return false return false
} }
if !g.convertibleOnlyWithinPackage(t, internalType) { if !g.convertibleOnlyWithinPackage(t, peerType) {
return false return false
} }
// We explicitly return true if any conversion is possible - this needs // We explicitly return true if any conversion is possible - this needs
// to be checked again while generating code for that type. // to be checked again while generating code for that type.
convertible := false convertible := false
if isConvertible(t, internalType, g.preexisting) { if isConvertible(t, peerType, g.manualConversions) {
g.typesForInit = append(g.typesForInit, conversionType{t, internalType}) g.typesForInit = append(g.typesForInit, conversionPair{t, peerType})
convertible = true convertible = true
} }
if isConvertible(internalType, t, g.preexisting) { if isConvertible(peerType, t, g.manualConversions) {
g.typesForInit = append(g.typesForInit, conversionType{internalType, t}) g.typesForInit = append(g.typesForInit, conversionPair{peerType, t})
convertible = true convertible = true
} }
return convertible return convertible
@ -513,7 +538,7 @@ func (g *genConversion) funcNameTmpl(inType, outType *types.Type) string {
} }
func (g *genConversion) preexists(inType, outType *types.Type) (*types.Type, bool) { func (g *genConversion) preexists(inType, outType *types.Type) (*types.Type, bool) {
function, ok := g.preexisting[conversionType{inType, outType}] function, ok := g.manualConversions[conversionPair{inType, outType}]
return function, ok return function, ok
} }
@ -545,13 +570,29 @@ func (g *genConversion) Init(c *generator.Context, w io.Writer) error {
} }
func (g *genConversion) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { func (g *genConversion) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
glog.V(5).Infof("generating for type %v", t)
sw := generator.NewSnippetWriter(w, c, "$", "$") sw := generator.NewSnippetWriter(w, c, "$", "$")
internalType, _ := getInternalTypeFor(c, t) peerType := getPeerTypeFor(c, t, g.peerPackages)
if isDirectlyConvertible(t, internalType, g.preexisting) { didForward, didBackward := false, false
g.generateConversion(t, internalType, sw) if isDirectlyConvertible(t, peerType, g.manualConversions) {
didForward = true
g.generateConversion(t, peerType, sw)
} }
if isDirectlyConvertible(internalType, t, g.preexisting) { if isDirectlyConvertible(peerType, t, g.manualConversions) {
g.generateConversion(internalType, t, sw) didBackward = true
g.generateConversion(peerType, t, sw)
}
if didForward != didBackward {
glog.Fatalf("Could only generate one direction of conversion for %v <-> %v", t, peerType)
}
if !didForward && !didBackward {
// TODO: This should be fatal but we have at least 8 types that
// currently fail this. The right thing to do is to figure out why they
// can't be generated and mark those fields as
// +k8s:conversion-gen=false, and ONLY do manual conversions for those
// fields, with the manual Convert_...() calling autoConvert_...()
// first.
glog.Errorf("Warning: could not generate autoConvert functions for %v <-> %v", t, peerType)
} }
return sw.Error() return sw.Error()
} }
@ -561,14 +602,14 @@ func (g *genConversion) generateConversion(inType, outType *types.Type, sw *gene
sw.Do(fmt.Sprintf("func auto%s(in *$.inType|raw$, out *$.outType|raw$, s $.Scope|raw$) error {\n", funcName), g.withGlobals(argsFromType(inType, outType))) sw.Do(fmt.Sprintf("func auto%s(in *$.inType|raw$, out *$.outType|raw$, s $.Scope|raw$) error {\n", funcName), g.withGlobals(argsFromType(inType, outType)))
// if no defaulter of form SetDefaults_XXX is defined, do not inline a check for defaulting. // if no defaulter of form SetDefaults_XXX is defined, do not inline a check for defaulting.
if function, ok := g.defaulters[inType]; ok { if function, ok := g.manualDefaulters[inType]; ok {
sw.Do("$.|raw$(in)\n", function) sw.Do("$.|raw$(in)\n", function)
} }
g.generateFor(inType, outType, sw) g.generateFor(inType, outType, sw)
sw.Do("return nil\n", nil) sw.Do("return nil\n", nil)
sw.Do("}\n\n", nil) sw.Do("}\n\n", nil)
// If there is no public preexisting Convert method, generate it. // If there is no public manual Conversion method, generate it.
if _, ok := g.preexists(inType, outType); !ok { if _, ok := g.preexists(inType, outType); !ok {
sw.Do(fmt.Sprintf("func %s(in *$.inType|raw$, out *$.outType|raw$, s $.Scope|raw$) error {\n", funcName), g.withGlobals(argsFromType(inType, outType))) sw.Do(fmt.Sprintf("func %s(in *$.inType|raw$, out *$.outType|raw$, s $.Scope|raw$) error {\n", funcName), g.withGlobals(argsFromType(inType, outType)))
sw.Do(fmt.Sprintf("return auto%s(in, out, s)\n", funcName), argsFromType(inType, outType)) sw.Do(fmt.Sprintf("return auto%s(in, out, s)\n", funcName), argsFromType(inType, outType))
@ -669,6 +710,11 @@ func (g *genConversion) doSlice(inType, outType *types.Type, sw *generator.Snipp
funcName := g.funcNameTmpl(inType.Elem, outType.Elem) funcName := g.funcNameTmpl(inType.Elem, outType.Elem)
sw.Do(fmt.Sprintf("if err := %s(&(*in)[i], &(*out)[i], s); err != nil {\n", funcName), argsFromType(inType.Elem, outType.Elem)) sw.Do(fmt.Sprintf("if err := %s(&(*in)[i], &(*out)[i], s); err != nil {\n", funcName), argsFromType(inType.Elem, outType.Elem))
} else { } else {
// TODO: This triggers on v1.ObjectMeta <-> api.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("// 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("if err := s.Convert(&(*in)[i], &(*out)[i], 0); err != nil {\n", nil)
} }
@ -684,7 +730,7 @@ func (g *genConversion) doStruct(inType, outType *types.Type, sw *generator.Snip
outMember, isOutMember := findMember(outType, m.Name) outMember, isOutMember := findMember(outType, m.Name)
if !isOutMember { if !isOutMember {
// Since this object wasn't filtered out, this means that // Since this object wasn't filtered out, this means that
// this field has "genconversion=false" comment to ignore it. // this field has "+k8s:conversion-gen=false" comment to ignore it.
continue continue
} }
t, outT := m.Type, outMember.Type t, outT := m.Type, outMember.Type

View File

@ -1,33 +0,0 @@
/*
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/kubernetes/cmd/libs/go2idl/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
// defaultVal.
func extractBoolTagOrDie(key string, defaultVal bool, lines []string) bool {
val, err := types.ExtractSingleBoolCommentTag("+", key, defaultVal, lines)
if err != nil {
glog.Fatalf(err.Error())
}
return val
}

View File

@ -16,9 +16,22 @@ limitations under the License.
// conversion-gen is a tool for auto-generating Conversion functions. // conversion-gen is a tool for auto-generating Conversion functions.
// //
// Structs in the input directories with the below line in their comments // Given a list of input directories, it will scan for "peer" packages and
// will be ignored during generation. // generate functions that efficiently convert between same-name types in each
// // +genconversion=false // 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 package main
import ( import (
@ -26,42 +39,30 @@ import (
"k8s.io/kubernetes/cmd/libs/go2idl/conversion-gen/generators" "k8s.io/kubernetes/cmd/libs/go2idl/conversion-gen/generators"
"github.com/golang/glog" "github.com/golang/glog"
"github.com/spf13/pflag"
) )
func main() { func main() {
arguments := args.Default() arguments := args.Default()
// Override defaults. These are Kubernetes specific input locations. // Override defaults.
arguments.InputDirs = []string{ arguments.OutputFileBaseName = "conversion_generated"
"k8s.io/kubernetes/pkg/api/v1",
"k8s.io/kubernetes/pkg/api",
"k8s.io/kubernetes/pkg/apis/authentication.k8s.io",
"k8s.io/kubernetes/pkg/apis/authentication.k8s.io/v1beta1",
"k8s.io/kubernetes/pkg/apis/authorization",
"k8s.io/kubernetes/pkg/apis/authorization/v1beta1",
"k8s.io/kubernetes/pkg/apis/autoscaling",
"k8s.io/kubernetes/pkg/apis/autoscaling/v1",
"k8s.io/kubernetes/pkg/apis/batch",
"k8s.io/kubernetes/pkg/apis/batch/v1",
"k8s.io/kubernetes/pkg/apis/batch/v2alpha1",
"k8s.io/kubernetes/pkg/apis/apps",
"k8s.io/kubernetes/pkg/apis/apps/v1alpha1",
"k8s.io/kubernetes/pkg/apis/certificates",
"k8s.io/kubernetes/pkg/apis/certificates/v1alpha1",
"k8s.io/kubernetes/pkg/apis/componentconfig",
"k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1",
"k8s.io/kubernetes/pkg/apis/policy",
"k8s.io/kubernetes/pkg/apis/policy/v1alpha1",
"k8s.io/kubernetes/pkg/apis/extensions",
"k8s.io/kubernetes/pkg/apis/extensions/v1beta1",
"k8s.io/kubernetes/pkg/apis/rbac",
"k8s.io/kubernetes/pkg/apis/rbac/v1alpha1",
"k8s.io/kubernetes/federation/apis/federation",
"k8s.io/kubernetes/federation/apis/federation/v1beta1",
"k8s.io/kubernetes/pkg/conversion",
"k8s.io/kubernetes/pkg/runtime",
}
// Custom args.
customArgs := &generators.CustomArgs{
ExtraPeerDirs: []string{
"k8s.io/kubernetes/pkg/api",
"k8s.io/kubernetes/pkg/api/v1",
"k8s.io/kubernetes/pkg/api/unversioned",
"k8s.io/kubernetes/pkg/conversion",
"k8s.io/kubernetes/pkg/runtime",
},
}
pflag.CommandLine.StringSliceVar(&customArgs.ExtraPeerDirs, "extra-peer-dirs", customArgs.ExtraPeerDirs,
"Comma-separated list of import paths which are considered, after tag-specified peers, for conversions.")
arguments.CustomArgs = customArgs
// Run it.
if err := arguments.Execute( if err := arguments.Execute(
generators.NameSystems(), generators.NameSystems(),
generators.DefaultNameSystem(), generators.DefaultNameSystem(),

View File

@ -166,6 +166,9 @@ type Context struct {
// If true, Execute* calls will just verify that the existing output is // If true, Execute* calls will just verify that the existing output is
// correct. (You may set this after calling NewContext.) // correct. (You may set this after calling NewContext.)
Verify bool Verify bool
// Allows generators to add packages at runtime.
builder *parser.Builder
} }
// NewContext generates a context from the given builder, naming systems, and // NewContext generates a context from the given builder, naming systems, and
@ -183,6 +186,7 @@ func NewContext(b *parser.Builder, nameSystems namer.NameSystems, canonicalOrder
FileTypes: map[string]FileType{ FileTypes: map[string]FileType{
GolangFileType: NewGolangFile(), GolangFileType: NewGolangFile(),
}, },
builder: b,
} }
for name, systemNamer := range nameSystems { for name, systemNamer := range nameSystems {
@ -194,3 +198,10 @@ func NewContext(b *parser.Builder, nameSystems namer.NameSystems, canonicalOrder
} }
return c, nil return c, nil
} }
// AddDir adds a Go package to the context. The specified path must be a single
// go package import path. GOPATH, GOROOT, and the location of your go binary
// (`which go`) will all be searched, in the normal Go fashion.
func (ctxt *Context) AddDir(path string) error {
return ctxt.builder.AddDirTo(path, &ctxt.Universe)
}

View File

@ -45,7 +45,7 @@ type Builder struct {
// map of package id to absolute path (to prevent overlap) // map of package id to absolute path (to prevent overlap)
absPaths map[string]string absPaths map[string]string
// Set by makePackages, used by importer() and friends. // Set by makePackage(), used by importer() and friends.
pkgs map[string]*tc.Package pkgs map[string]*tc.Package
// Map of package path to whether the user requested it or it was from // Map of package path to whether the user requested it or it was from
@ -167,6 +167,7 @@ func (b *Builder) addFile(pkg string, path string, src []byte, userRequested boo
} else { } else {
b.absPaths[pkg] = dirPath b.absPaths[pkg] = dirPath
} }
b.parsed[pkg] = append(b.parsed[pkg], parsedFile{path, p}) b.parsed[pkg] = append(b.parsed[pkg], parsedFile{path, p})
b.userRequested[pkg] = userRequested b.userRequested[pkg] = userRequested
for _, c := range p.Comments { for _, c := range p.Comments {
@ -232,6 +233,26 @@ func (b *Builder) AddDirRecursive(dir string) error {
return nil return nil
} }
// AddDirTo adds an entire directory to a given Universe. Unlike AddDir, this
// processes the package immediately, which makes it safe to use from within a
// generator (rather than just at init time. 'dir' must be a single go package.
// GOPATH, GOROOT, and the location of your go binary (`which go`) will all be
// searched if dir doesn't literally resolve.
func (b *Builder) AddDirTo(dir string, u *types.Universe) error {
if _, found := b.parsed[dir]; !found {
// We want all types from this package, as if they were directly added
// by the user. They WERE added by the user, in effect.
if err := b.addDir(dir, true); err != nil {
return err
}
} else {
// We already had this package, but we want it to be considered as if
// the user addid it directly.
b.userRequested[dir] = true
}
return b.findTypesIn(dir, u)
}
// The implementation of AddDir. A flag indicates whether this directory was // The implementation of AddDir. A flag indicates whether this directory was
// user-requested or just from following the import graph. // user-requested or just from following the import graph.
func (b *Builder) addDir(dir string, userRequested bool) error { func (b *Builder) addDir(dir string, userRequested bool) error {
@ -240,8 +261,10 @@ func (b *Builder) addDir(dir string, userRequested bool) error {
return err return err
} }
// Check in case this package was added (maybe dir was not canonical) // Check in case this package was added (maybe dir was not canonical)
if _, alreadyAdded := b.parsed[dir]; alreadyAdded { if wasRequested, wasAdded := b.userRequested[dir]; wasAdded {
return nil if !userRequested || userRequested == wasRequested {
return nil
}
} }
for _, n := range pkg.GoFiles { for _, n := range pkg.GoFiles {
@ -335,23 +358,35 @@ func (b *Builder) typeCheckPackage(id string) (*tc.Package, error) {
return pkg, err return pkg, err
} }
func (b *Builder) makePackages() error { func (b *Builder) makeAllPackages() error {
b.pkgs = map[string]*tc.Package{} // Take a snapshot to iterate, since this will recursively mutate b.parsed.
keys := []string{}
for id := range b.parsed { for id := range b.parsed {
// We have to check here even though we made a new one above, keys = append(keys, id)
// because typeCheckPackage follows the import graph, which may }
// cause a package to be filled before we get to it in this for _, id := range keys {
// loop. if _, err := b.makePackage(id); err != nil {
if _, done := b.pkgs[id]; done {
continue
}
if _, err := b.typeCheckPackage(id); err != nil {
return err return err
} }
} }
return nil return nil
} }
func (b *Builder) makePackage(id string) (*tc.Package, error) {
if b.pkgs == nil {
b.pkgs = map[string]*tc.Package{}
}
// We have to check here even though we made a new one above,
// because typeCheckPackage follows the import graph, which may
// cause a package to be filled before we get to it in this
// loop.
if pkg, done := b.pkgs[id]; done {
return pkg, nil
}
return b.typeCheckPackage(id)
}
// FindPackages fetches a list of the user-imported packages. // FindPackages fetches a list of the user-imported packages.
func (b *Builder) FindPackages() []string { func (b *Builder) FindPackages() []string {
result := []string{} result := []string{}
@ -369,65 +404,78 @@ func (b *Builder) FindPackages() []string {
// FindTypes finalizes the package imports, and searches through all the // FindTypes finalizes the package imports, and searches through all the
// packages for types. // packages for types.
func (b *Builder) FindTypes() (types.Universe, error) { func (b *Builder) FindTypes() (types.Universe, error) {
if err := b.makePackages(); err != nil { if err := b.makeAllPackages(); err != nil {
return nil, err return nil, err
} }
u := types.Universe{} u := types.Universe{}
for pkgPath, pkg := range b.pkgs { for pkgPath := range b.parsed {
if !b.userRequested[pkgPath] { if err := b.findTypesIn(pkgPath, &u); err != nil {
// Since walkType is recursive, all types that the return nil, err
// packages they asked for depend on will be included.
// But we don't need to include all types in all
// *packages* they depend on.
continue
} }
for _, f := range b.parsed[pkgPath] {
if strings.HasSuffix(f.name, "/doc.go") {
tp := u.Package(pkgPath)
for i := range f.file.Comments {
tp.Comments = append(tp.Comments, splitLines(f.file.Comments[i].Text())...)
}
if f.file.Doc != nil {
tp.DocComments = splitLines(f.file.Doc.Text())
}
}
}
s := pkg.Scope()
for _, n := range s.Names() {
obj := s.Lookup(n)
tn, ok := obj.(*tc.TypeName)
if ok {
t := b.walkType(u, nil, tn.Type())
c1 := b.priorCommentLines(obj.Pos(), 1)
t.CommentLines = splitLines(c1.Text())
if c1 == nil {
t.SecondClosestCommentLines = splitLines(b.priorCommentLines(obj.Pos(), 2).Text())
} else {
t.SecondClosestCommentLines = splitLines(b.priorCommentLines(c1.List[0].Slash, 2).Text())
}
}
tf, ok := obj.(*tc.Func)
// We only care about functions, not concrete/abstract methods.
if ok && tf.Type() != nil && tf.Type().(*tc.Signature).Recv() == nil {
b.addFunction(u, nil, tf)
}
tv, ok := obj.(*tc.Var)
if ok && !tv.IsField() {
b.addVariable(u, nil, tv)
}
}
for p := range b.importGraph[pkgPath] {
u.AddImports(pkgPath, p)
}
u.Package(pkgPath).Name = pkg.Name()
} }
return u, nil return u, nil
} }
// findTypesIn finalizes the package import and searches through the package
// for types.
func (b *Builder) findTypesIn(pkgPath string, u *types.Universe) error {
pkg, err := b.makePackage(pkgPath)
if err != nil {
return err
}
if !b.userRequested[pkgPath] {
// Since walkType is recursive, all types that the
// packages they asked for depend on will be included.
// But we don't need to include all types in all
// *packages* they depend on.
return nil
}
for _, f := range b.parsed[pkgPath] {
if strings.HasSuffix(f.name, "/doc.go") {
tp := u.Package(pkgPath)
for i := range f.file.Comments {
tp.Comments = append(tp.Comments, splitLines(f.file.Comments[i].Text())...)
}
if f.file.Doc != nil {
tp.DocComments = splitLines(f.file.Doc.Text())
}
}
}
s := pkg.Scope()
for _, n := range s.Names() {
obj := s.Lookup(n)
tn, ok := obj.(*tc.TypeName)
if ok {
t := b.walkType(*u, nil, tn.Type())
c1 := b.priorCommentLines(obj.Pos(), 1)
t.CommentLines = splitLines(c1.Text())
if c1 == nil {
t.SecondClosestCommentLines = splitLines(b.priorCommentLines(obj.Pos(), 2).Text())
} else {
t.SecondClosestCommentLines = splitLines(b.priorCommentLines(c1.List[0].Slash, 2).Text())
}
}
tf, ok := obj.(*tc.Func)
// We only care about functions, not concrete/abstract methods.
if ok && tf.Type() != nil && tf.Type().(*tc.Signature).Recv() == nil {
b.addFunction(*u, nil, tf)
}
tv, ok := obj.(*tc.Var)
if ok && !tv.IsField() {
b.addVariable(*u, nil, tv)
}
}
for p := range b.importGraph[pkgPath] {
u.AddImports(pkgPath, p)
}
u.Package(pkgPath).Name = pkg.Name()
return nil
}
// if there's a comment on the line `lines` before pos, return its text, otherwise "". // if there's a comment on the line `lines` before pos, return its text, otherwise "".
func (b *Builder) priorCommentLines(pos token.Pos, lines int) *ast.CommentGroup { func (b *Builder) priorCommentLines(pos token.Pos, lines int) *ast.CommentGroup {
position := b.fset.Position(pos) position := b.fset.Position(pos)

View File

@ -118,7 +118,9 @@ func (p *Package) Has(name string) bool {
return has return has
} }
// Get (or add) the given type // Type gets the given Type in this Package. If the Type is not already
// defined, this will add it and return the new Type value. The caller is
// expected to finish initialization.
func (p *Package) Type(typeName string) *Type { func (p *Package) Type(typeName string) *Type {
if t, ok := p.Types[typeName]; ok { if t, ok := p.Types[typeName]; ok {
return t return t
@ -135,9 +137,10 @@ func (p *Package) Type(typeName string) *Type {
return t return t
} }
// Get (or add) the given function. If a function is added, it's the caller's // Function gets the given function Type in this Package. If the function is
// responsibility to finish construction of the function by setting Underlying // not already defined, this will add it. If a function is added, it's the
// to the correct type. // caller's responsibility to finish construction of the function by setting
// Underlying to the correct type.
func (p *Package) Function(funcName string) *Type { func (p *Package) Function(funcName string) *Type {
if t, ok := p.Functions[funcName]; ok { if t, ok := p.Functions[funcName]; ok {
return t return t
@ -148,7 +151,8 @@ func (p *Package) Function(funcName string) *Type {
return t return t
} }
// Get (or add) the given varaible. If a variable is added, it's the caller's // Variable gets the given varaible Type in this Package. If the variable is
// not already defined, this will add it. If a variable is added, it's the caller's
// responsibility to finish construction of the variable by setting Underlying // responsibility to finish construction of the variable by setting Underlying
// to the correct type. // to the correct type.
func (p *Package) Variable(varName string) *Type { func (p *Package) Variable(varName string) *Type {
@ -169,19 +173,20 @@ func (p *Package) HasImport(packageName string) bool {
} }
// Universe is a map of all packages. The key is the package name, but you // Universe is a map of all packages. The key is the package name, but you
// should use Get() or Package() instead of direct access. // should use Package(), Type(), Function(), or Variable() instead of direct
// access.
type Universe map[string]*Package type Universe map[string]*Package
// Get returns the canonical type for the given fully-qualified name. Builtin // Type returns the canonical type for the given fully-qualified name. Builtin
// types will always be found, even if they haven't been explicitly added to // types will always be found, even if they haven't been explicitly added to
// the map. If a non-existing type is requested, u will create (a marker for) // the map. If a non-existing type is requested, this will create (a marker for)
// it. // it.
func (u Universe) Type(n Name) *Type { func (u Universe) Type(n Name) *Type {
return u.Package(n.Package).Type(n.Name) return u.Package(n.Package).Type(n.Name)
} }
// Function returns the canonical function for the given fully-qualified name. // Function returns the canonical function for the given fully-qualified name.
// If a non-existing function is requested, u will create (a marker for) it. // If a non-existing function is requested, this will create (a marker for) it.
// If a marker is created, it's the caller's responsibility to finish // If a marker is created, it's the caller's responsibility to finish
// construction of the function by setting Underlying to the correct type. // construction of the function by setting Underlying to the correct type.
func (u Universe) Function(n Name) *Type { func (u Universe) Function(n Name) *Type {
@ -189,7 +194,7 @@ func (u Universe) Function(n Name) *Type {
} }
// Variable returns the canonical variable for the given fully-qualified name. // Variable returns the canonical variable for the given fully-qualified name.
// If a non-existing variable is requested, u will create (a marker for) it. // If a non-existing variable is requested, this will create (a marker for) it.
// If a marker is created, it's the caller's responsibility to finish // If a marker is created, it's the caller's responsibility to finish
// construction of the variable by setting Underlying to the correct type. // construction of the variable by setting Underlying to the correct type.
func (u Universe) Variable(n Name) *Type { func (u Universe) Variable(n Name) *Type {
@ -205,7 +210,10 @@ func (u Universe) AddImports(packagePath string, importPaths ...string) {
} }
} }
// Get (create if needed) the package. // Package returns the Package for the given path.
// If a non-existing package is requested, this will create (a marker for) it.
// If a marker is created, it's the caller's responsibility to finish
// construction of the package.
func (u Universe) Package(packagePath string) *Package { func (u Universe) Package(packagePath string) *Package {
if p, ok := u[packagePath]; ok { if p, ok := u[packagePath]; ok {
return p return p

View File

@ -79,9 +79,10 @@ cmd/libs/go2idl/ tool.
2. Make sure your pkg/apis/`<group>`/`<version>` directory has a doc.go file 2. Make sure your pkg/apis/`<group>`/`<version>` directory has a doc.go file
with the comment `// +k8s:deepcopy-gen=package,register`, to catch the with the comment `// +k8s:deepcopy-gen=package,register`, to catch the
attention of our generation tools. attention of our generation tools.
3. Make sure your pkg/apis/`<group>`/`<version>` directory has a doc.go file 3. Make sure your `pkg/apis/<group>/<version>` directory has a doc.go file
with the comment `// +genconversion=true`, to catch the attention of our with the comment `// +k8s:conversion-gen=<internal-pkg>`, to catch the
gen-conversion script. attention of our generation tools. For most APIs the only target you
need is `k8s.io/kubernetes/pkg/apis/<group>` (your internal API).
4. Run hack/update-all.sh. 4. Run hack/update-all.sh.
2. Generate files for Ugorji codec: 2. Generate files for Ugorji codec:

View File

@ -522,9 +522,8 @@ At the moment, you'll have to make a new directory under `pkg/apis/`; copy the
directory structure from `pkg/apis/extensions`. Add the new group/version to all directory structure from `pkg/apis/extensions`. Add the new group/version to all
of the `hack/{verify,update}-generated-{deep-copy,conversions,swagger}.sh` files of the `hack/{verify,update}-generated-{deep-copy,conversions,swagger}.sh` files
in the appropriate places--it should just require adding your new group/version in the appropriate places--it should just require adding your new group/version
to a bash array. You will also need to make sure your new types are imported by to a bash array. See [docs on adding an API group](adding-an-APIGroup.md) for
the generation commands (`cmd/gendeepcopy/` & `cmd/genconversion`). These more.
instructions may not be complete and will be updated as we gain experience.
Adding API groups outside of the `pkg/apis/` directory is not currently Adding API groups outside of the `pkg/apis/` directory is not currently
supported, but is clearly desirable. The deep copy & conversion generators need supported, but is clearly desirable. The deep copy & conversion generators need

View File

@ -15,6 +15,6 @@ limitations under the License.
*/ */
// +k8s:deepcopy-gen=package,register // +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=k8s.io/kubernetes/federation/apis/federation
// +genconversion=true
package v1beta1 package v1beta1

View File

@ -47,7 +47,6 @@ ${clientgen} --clientset-name="release_1_4" --input="api/v1,extensions/v1beta1,a
# Clientgen for federation clientset. # Clientgen for federation clientset.
${clientgen} --clientset-name=federation_internalclientset --clientset-path=k8s.io/kubernetes/federation/client/clientset_generated --input="../../federation/apis/federation/","api/" --included-types-overrides="api/Service" "$@" ${clientgen} --clientset-name=federation_internalclientset --clientset-path=k8s.io/kubernetes/federation/client/clientset_generated --input="../../federation/apis/federation/","api/" --included-types-overrides="api/Service" "$@"
${clientgen} --clientset-name=federation_release_1_4 --clientset-path=k8s.io/kubernetes/federation/client/clientset_generated --input="../../federation/apis/federation/v1beta1","api/v1" --included-types-overrides="api/v1/Service" "$@" ${clientgen} --clientset-name=federation_release_1_4 --clientset-path=k8s.io/kubernetes/federation/client/clientset_generated --input="../../federation/apis/federation/v1beta1","api/v1" --included-types-overrides="api/v1/Service" "$@"
${conversiongen} "$@"
${setgen} "$@" ${setgen} "$@"
# You may add additional calls of code generators like set-gen above. # You may add additional calls of code generators like set-gen above.
@ -73,9 +72,22 @@ DEEP_COPY_DIRS=$(
| xargs dirname \ | xargs dirname \
| sort -u | sort -u
) )
INPUTS=$( DEEPCOPY_INPUTS=$(
for d in ${DEEP_COPY_DIRS}; do for d in ${DEEP_COPY_DIRS}; do
echo k8s.io/kubernetes/$d echo k8s.io/kubernetes/$d
done | paste -sd, done | paste -sd,
) )
${deepcopygen} -i ${INPUTS} ${deepcopygen} -i ${DEEPCOPY_INPUTS}
CONVERSION_DIRS=$(
grep '^// *+k8s:conversion-gen=' ${ALL_K8S_TAG_FILES} \
| cut -f1 -d: \
| xargs dirname \
| sort -u \
)
CONVERSION_INPUTS=$(
for d in ${CONVERSION_DIRS}; do
echo k8s.io/kubernetes/$d
done | paste -sd,
)
${conversiongen} -i ${CONVERSION_INPUTS}

View File

@ -150,13 +150,14 @@ executor-bindall
executor-logv executor-logv
executor-path executor-path
executor-suicide-timeout executor-suicide-timeout
exit-on-lock-contention
experimental-flannel-overlay experimental-flannel-overlay
experimental-keystone-url experimental-keystone-url
experimental-nvidia-gpus experimental-nvidia-gpus
experimental-prefix experimental-prefix
external-hostname external-hostname
external-ip external-ip
exit-on-lock-contention extra-peer-dirs
failover-timeout failover-timeout
failure-domains failure-domains
fake-clientset fake-clientset

View File

@ -100,15 +100,12 @@ func Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(in, out *unversioned.T
} }
func Convert_unversioned_ListMeta_To_unversioned_ListMeta(in, out *unversioned.ListMeta, s conversion.Scope) error { func Convert_unversioned_ListMeta_To_unversioned_ListMeta(in, out *unversioned.ListMeta, s conversion.Scope) error {
out.ResourceVersion = in.ResourceVersion *out = *in
out.SelfLink = in.SelfLink
return nil return nil
} }
func Convert_intstr_IntOrString_To_intstr_IntOrString(in, out *intstr.IntOrString, s conversion.Scope) error { func Convert_intstr_IntOrString_To_intstr_IntOrString(in, out *intstr.IntOrString, s conversion.Scope) error {
out.Type = in.Type *out = *in
out.IntVal = in.IntVal
out.StrVal = in.StrVal
return nil return nil
} }

View File

@ -1479,12 +1479,15 @@ type PodSecurityContext struct {
// Use the host's network namespace. If this option is set, the ports that will be // Use the host's network namespace. If this option is set, the ports that will be
// used must be specified. // used must be specified.
// Optional: Default to false // Optional: Default to false
// +k8s:conversion-gen=false
HostNetwork bool `json:"hostNetwork,omitempty"` HostNetwork bool `json:"hostNetwork,omitempty"`
// Use the host's pid namespace. // Use the host's pid namespace.
// Optional: Default to false. // Optional: Default to false.
// +k8s:conversion-gen=false
HostPID bool `json:"hostPID,omitempty"` HostPID bool `json:"hostPID,omitempty"`
// Use the host's ipc namespace. // Use the host's ipc namespace.
// Optional: Default to false. // Optional: Default to false.
// +k8s:conversion-gen=false
HostIPC bool `json:"hostIPC,omitempty"` HostIPC bool `json:"hostIPC,omitempty"`
// The SELinux context to be applied to all containers. // The SELinux context to be applied to all containers.
// If unspecified, the container runtime will allocate a random SELinux context for each // If unspecified, the container runtime will allocate a random SELinux context for each

View File

@ -360,124 +360,34 @@ func Convert_v1_PodTemplateSpec_To_api_PodTemplateSpec(in *PodTemplateSpec, out
// The following two PodSpec conversions are done here to support ServiceAccount // The following two PodSpec conversions are done here to support ServiceAccount
// as an alias for ServiceAccountName. // as an alias for ServiceAccountName.
func Convert_api_PodSpec_To_v1_PodSpec(in *api.PodSpec, out *PodSpec, s conversion.Scope) error { func Convert_api_PodSpec_To_v1_PodSpec(in *api.PodSpec, out *PodSpec, s conversion.Scope) error {
if in.Volumes != nil { if err := autoConvert_api_PodSpec_To_v1_PodSpec(in, out, s); err != nil {
out.Volumes = make([]Volume, len(in.Volumes)) return err
for i := range in.Volumes {
if err := Convert_api_Volume_To_v1_Volume(&in.Volumes[i], &out.Volumes[i], s); err != nil {
return err
}
}
} else {
out.Volumes = nil
}
if in.InitContainers != nil {
out.InitContainers = make([]Container, len(in.InitContainers))
for i := range in.InitContainers {
if err := Convert_api_Container_To_v1_Container(&in.InitContainers[i], &out.InitContainers[i], s); err != nil {
return err
}
}
} else {
out.InitContainers = nil
}
if in.Containers != nil {
out.Containers = make([]Container, len(in.Containers))
for i := range in.Containers {
if err := Convert_api_Container_To_v1_Container(&in.Containers[i], &out.Containers[i], s); err != nil {
return err
}
}
} else {
out.Containers = nil
} }
out.RestartPolicy = RestartPolicy(in.RestartPolicy)
out.TerminationGracePeriodSeconds = in.TerminationGracePeriodSeconds
out.ActiveDeadlineSeconds = in.ActiveDeadlineSeconds
out.DNSPolicy = DNSPolicy(in.DNSPolicy)
out.NodeSelector = in.NodeSelector
out.ServiceAccountName = in.ServiceAccountName
// DeprecatedServiceAccount is an alias for ServiceAccountName. // DeprecatedServiceAccount is an alias for ServiceAccountName.
out.DeprecatedServiceAccount = in.ServiceAccountName out.DeprecatedServiceAccount = in.ServiceAccountName
out.NodeName = in.NodeName
if in.SecurityContext != nil {
out.SecurityContext = new(PodSecurityContext)
if err := Convert_api_PodSecurityContext_To_v1_PodSecurityContext(in.SecurityContext, out.SecurityContext, s); err != nil {
return err
}
if in.SecurityContext != nil {
// the host namespace fields have to be handled here for backward compatibility // the host namespace fields have to be handled here for backward compatibility
// with v1.0.0 // with v1.0.0
out.HostPID = in.SecurityContext.HostPID out.HostPID = in.SecurityContext.HostPID
out.HostNetwork = in.SecurityContext.HostNetwork out.HostNetwork = in.SecurityContext.HostNetwork
out.HostIPC = in.SecurityContext.HostIPC out.HostIPC = in.SecurityContext.HostIPC
} }
if in.ImagePullSecrets != nil {
out.ImagePullSecrets = make([]LocalObjectReference, len(in.ImagePullSecrets))
for i := range in.ImagePullSecrets {
if err := Convert_api_LocalObjectReference_To_v1_LocalObjectReference(&in.ImagePullSecrets[i], &out.ImagePullSecrets[i], s); err != nil {
return err
}
}
} else {
out.ImagePullSecrets = nil
}
out.Hostname = in.Hostname
out.Subdomain = in.Subdomain
return nil return nil
} }
func Convert_v1_PodSpec_To_api_PodSpec(in *PodSpec, out *api.PodSpec, s conversion.Scope) error { func Convert_v1_PodSpec_To_api_PodSpec(in *PodSpec, out *api.PodSpec, s conversion.Scope) error {
SetDefaults_PodSpec(in) if err := autoConvert_v1_PodSpec_To_api_PodSpec(in, out, s); err != nil {
if in.Volumes != nil { return err
out.Volumes = make([]api.Volume, len(in.Volumes))
for i := range in.Volumes {
if err := Convert_v1_Volume_To_api_Volume(&in.Volumes[i], &out.Volumes[i], s); err != nil {
return err
}
}
} else {
out.Volumes = nil
} }
if in.InitContainers != nil {
out.InitContainers = make([]api.Container, len(in.InitContainers))
for i := range in.InitContainers {
if err := Convert_v1_Container_To_api_Container(&in.InitContainers[i], &out.InitContainers[i], s); err != nil {
return err
}
}
} else {
out.InitContainers = nil
}
if in.Containers != nil {
out.Containers = make([]api.Container, len(in.Containers))
for i := range in.Containers {
if err := Convert_v1_Container_To_api_Container(&in.Containers[i], &out.Containers[i], s); err != nil {
return err
}
}
} else {
out.Containers = nil
}
out.RestartPolicy = api.RestartPolicy(in.RestartPolicy)
out.TerminationGracePeriodSeconds = in.TerminationGracePeriodSeconds
out.ActiveDeadlineSeconds = in.ActiveDeadlineSeconds
out.DNSPolicy = api.DNSPolicy(in.DNSPolicy)
out.NodeSelector = in.NodeSelector
// We support DeprecatedServiceAccount as an alias for ServiceAccountName. // We support DeprecatedServiceAccount as an alias for ServiceAccountName.
// If both are specified, ServiceAccountName (the new field) wins. // If both are specified, ServiceAccountName (the new field) wins.
out.ServiceAccountName = in.ServiceAccountName
if in.ServiceAccountName == "" { if in.ServiceAccountName == "" {
out.ServiceAccountName = in.DeprecatedServiceAccount out.ServiceAccountName = in.DeprecatedServiceAccount
} }
out.NodeName = in.NodeName
if in.SecurityContext != nil {
out.SecurityContext = new(api.PodSecurityContext)
if err := Convert_v1_PodSecurityContext_To_api_PodSecurityContext(in.SecurityContext, out.SecurityContext, s); err != nil {
return err
}
}
// the host namespace fields have to be handled specially for backward compatibility // the host namespace fields have to be handled specially for backward compatibility
// with v1.0.0 // with v1.0.0
@ -487,18 +397,7 @@ func Convert_v1_PodSpec_To_api_PodSpec(in *PodSpec, out *api.PodSpec, s conversi
out.SecurityContext.HostNetwork = in.HostNetwork out.SecurityContext.HostNetwork = in.HostNetwork
out.SecurityContext.HostPID = in.HostPID out.SecurityContext.HostPID = in.HostPID
out.SecurityContext.HostIPC = in.HostIPC out.SecurityContext.HostIPC = in.HostIPC
if in.ImagePullSecrets != nil {
out.ImagePullSecrets = make([]api.LocalObjectReference, len(in.ImagePullSecrets))
for i := range in.ImagePullSecrets {
if err := Convert_v1_LocalObjectReference_To_api_LocalObjectReference(&in.ImagePullSecrets[i], &out.ImagePullSecrets[i], s); err != nil {
return err
}
}
} else {
out.ImagePullSecrets = nil
}
out.Hostname = in.Hostname
out.Subdomain = in.Subdomain
return nil return nil
} }

View File

@ -4785,6 +4785,90 @@ func autoConvert_v1_PodSecurityContext_To_api_PodSecurityContext(in *PodSecurity
return nil return nil
} }
func autoConvert_api_PodSecurityContext_To_v1_PodSecurityContext(in *api.PodSecurityContext, out *PodSecurityContext, s conversion.Scope) error {
if in.SELinuxOptions != nil {
in, out := &in.SELinuxOptions, &out.SELinuxOptions
*out = new(SELinuxOptions)
if err := Convert_api_SELinuxOptions_To_v1_SELinuxOptions(*in, *out, s); err != nil {
return err
}
} else {
out.SELinuxOptions = nil
}
out.RunAsUser = in.RunAsUser
out.RunAsNonRoot = in.RunAsNonRoot
out.SupplementalGroups = in.SupplementalGroups
out.FSGroup = in.FSGroup
return nil
}
func autoConvert_v1_PodSpec_To_api_PodSpec(in *PodSpec, out *api.PodSpec, s conversion.Scope) error {
SetDefaults_PodSpec(in)
if in.Volumes != nil {
in, out := &in.Volumes, &out.Volumes
*out = make([]api.Volume, len(*in))
for i := range *in {
if err := Convert_v1_Volume_To_api_Volume(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Volumes = nil
}
if in.InitContainers != nil {
in, out := &in.InitContainers, &out.InitContainers
*out = make([]api.Container, len(*in))
for i := range *in {
if err := Convert_v1_Container_To_api_Container(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.InitContainers = nil
}
if in.Containers != nil {
in, out := &in.Containers, &out.Containers
*out = make([]api.Container, len(*in))
for i := range *in {
if err := Convert_v1_Container_To_api_Container(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Containers = nil
}
out.RestartPolicy = api.RestartPolicy(in.RestartPolicy)
out.TerminationGracePeriodSeconds = in.TerminationGracePeriodSeconds
out.ActiveDeadlineSeconds = in.ActiveDeadlineSeconds
out.DNSPolicy = api.DNSPolicy(in.DNSPolicy)
out.NodeSelector = in.NodeSelector
out.ServiceAccountName = in.ServiceAccountName
out.NodeName = in.NodeName
if in.SecurityContext != nil {
in, out := &in.SecurityContext, &out.SecurityContext
*out = new(api.PodSecurityContext)
if err := Convert_v1_PodSecurityContext_To_api_PodSecurityContext(*in, *out, s); err != nil {
return err
}
} else {
out.SecurityContext = nil
}
if in.ImagePullSecrets != nil {
in, out := &in.ImagePullSecrets, &out.ImagePullSecrets
*out = make([]api.LocalObjectReference, len(*in))
for i := range *in {
if err := Convert_v1_LocalObjectReference_To_api_LocalObjectReference(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.ImagePullSecrets = nil
}
out.Hostname = in.Hostname
out.Subdomain = in.Subdomain
return nil
}
func autoConvert_api_PodSpec_To_v1_PodSpec(in *api.PodSpec, out *PodSpec, s conversion.Scope) error { func autoConvert_api_PodSpec_To_v1_PodSpec(in *api.PodSpec, out *PodSpec, s conversion.Scope) error {
if in.Volumes != nil { if in.Volumes != nil {
in, out := &in.Volumes, &out.Volumes in, out := &in.Volumes, &out.Volumes

View File

@ -15,7 +15,7 @@ limitations under the License.
*/ */
// +k8s:deepcopy-gen=package,register // +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/api
// Package v1 is the v1 version of the API. // Package v1 is the v1 version of the API.
// +genconversion=true
package v1 package v1

View File

@ -2089,6 +2089,7 @@ message PodSpec {
// DeprecatedServiceAccount is a depreciated alias for ServiceAccountName. // DeprecatedServiceAccount is a depreciated alias for ServiceAccountName.
// Deprecated: Use serviceAccountName instead. // Deprecated: Use serviceAccountName instead.
// +k8s:conversion-gen=false
optional string serviceAccount = 9; optional string serviceAccount = 9;
// NodeName is a request to schedule this pod onto a specific node. If it is non-empty, // NodeName is a request to schedule this pod onto a specific node. If it is non-empty,
@ -2099,14 +2100,17 @@ message PodSpec {
// Host networking requested for this pod. Use the host's network namespace. // Host networking requested for this pod. Use the host's network namespace.
// If this option is set, the ports that will be used must be specified. // If this option is set, the ports that will be used must be specified.
// Default to false. // Default to false.
// +k8s:conversion-gen=false
optional bool hostNetwork = 11; optional bool hostNetwork = 11;
// Use the host's pid namespace. // Use the host's pid namespace.
// Optional: Default to false. // Optional: Default to false.
// +k8s:conversion-gen=false
optional bool hostPID = 12; optional bool hostPID = 12;
// Use the host's ipc namespace. // Use the host's ipc namespace.
// Optional: Default to false. // Optional: Default to false.
// +k8s:conversion-gen=false
optional bool hostIPC = 13; optional bool hostIPC = 13;
// SecurityContext holds pod-level security attributes and common container settings. // SecurityContext holds pod-level security attributes and common container settings.
@ -2481,7 +2485,7 @@ message Secret {
// It is provided as a write-only convenience method. // It is provided as a write-only convenience method.
// All keys and values are merged into the data field on write, overwriting any existing values. // All keys and values are merged into the data field on write, overwriting any existing values.
// It is never output when reading from the API. // It is never output when reading from the API.
// +genconversion=false // +k8s:conversion-gen=false
map<string, string> stringData = 4; map<string, string> stringData = 4;
// Used to facilitate programmatic handling of secret data. // Used to facilitate programmatic handling of secret data.
@ -2715,7 +2719,7 @@ message ServiceSpec {
// API for compatibility until at least 8/20/2016. It will be removed from // API for compatibility until at least 8/20/2016. It will be removed from
// any new API revisions. If both deprecatedPublicIPs *and* externalIPs are // any new API revisions. If both deprecatedPublicIPs *and* externalIPs are
// set, deprecatedPublicIPs is used. // set, deprecatedPublicIPs is used.
// +genconversion=false // +k8s:conversion-gen=false
repeated string deprecatedPublicIPs = 6; repeated string deprecatedPublicIPs = 6;
// Supports "ClientIP" and "None". Used to maintain session affinity. // Supports "ClientIP" and "None". Used to maintain session affinity.

View File

@ -1719,6 +1719,7 @@ type PodSpec struct {
ServiceAccountName string `json:"serviceAccountName,omitempty" protobuf:"bytes,8,opt,name=serviceAccountName"` ServiceAccountName string `json:"serviceAccountName,omitempty" protobuf:"bytes,8,opt,name=serviceAccountName"`
// DeprecatedServiceAccount is a depreciated alias for ServiceAccountName. // DeprecatedServiceAccount is a depreciated alias for ServiceAccountName.
// Deprecated: Use serviceAccountName instead. // Deprecated: Use serviceAccountName instead.
// +k8s:conversion-gen=false
DeprecatedServiceAccount string `json:"serviceAccount,omitempty" protobuf:"bytes,9,opt,name=serviceAccount"` DeprecatedServiceAccount string `json:"serviceAccount,omitempty" protobuf:"bytes,9,opt,name=serviceAccount"`
// NodeName is a request to schedule this pod onto a specific node. If it is non-empty, // NodeName is a request to schedule this pod onto a specific node. If it is non-empty,
@ -1728,12 +1729,15 @@ type PodSpec struct {
// Host networking requested for this pod. Use the host's network namespace. // Host networking requested for this pod. Use the host's network namespace.
// If this option is set, the ports that will be used must be specified. // If this option is set, the ports that will be used must be specified.
// Default to false. // Default to false.
// +k8s:conversion-gen=false
HostNetwork bool `json:"hostNetwork,omitempty" protobuf:"varint,11,opt,name=hostNetwork"` HostNetwork bool `json:"hostNetwork,omitempty" protobuf:"varint,11,opt,name=hostNetwork"`
// Use the host's pid namespace. // Use the host's pid namespace.
// Optional: Default to false. // Optional: Default to false.
// +k8s:conversion-gen=false
HostPID bool `json:"hostPID,omitempty" protobuf:"varint,12,opt,name=hostPID"` HostPID bool `json:"hostPID,omitempty" protobuf:"varint,12,opt,name=hostPID"`
// Use the host's ipc namespace. // Use the host's ipc namespace.
// Optional: Default to false. // Optional: Default to false.
// +k8s:conversion-gen=false
HostIPC bool `json:"hostIPC,omitempty" protobuf:"varint,13,opt,name=hostIPC"` HostIPC bool `json:"hostIPC,omitempty" protobuf:"varint,13,opt,name=hostIPC"`
// SecurityContext holds pod-level security attributes and common container settings. // SecurityContext holds pod-level security attributes and common container settings.
// Optional: Defaults to empty. See type description for default values of each field. // Optional: Defaults to empty. See type description for default values of each field.
@ -2081,7 +2085,7 @@ type ServiceSpec struct {
// API for compatibility until at least 8/20/2016. It will be removed from // API for compatibility until at least 8/20/2016. It will be removed from
// any new API revisions. If both deprecatedPublicIPs *and* externalIPs are // any new API revisions. If both deprecatedPublicIPs *and* externalIPs are
// set, deprecatedPublicIPs is used. // set, deprecatedPublicIPs is used.
// +genconversion=false // +k8s:conversion-gen=false
DeprecatedPublicIPs []string `json:"deprecatedPublicIPs,omitempty" protobuf:"bytes,6,rep,name=deprecatedPublicIPs"` DeprecatedPublicIPs []string `json:"deprecatedPublicIPs,omitempty" protobuf:"bytes,6,rep,name=deprecatedPublicIPs"`
// Supports "ClientIP" and "None". Used to maintain session affinity. // Supports "ClientIP" and "None". Used to maintain session affinity.
@ -3096,7 +3100,7 @@ type Secret struct {
// It is provided as a write-only convenience method. // It is provided as a write-only convenience method.
// All keys and values are merged into the data field on write, overwriting any existing values. // All keys and values are merged into the data field on write, overwriting any existing values.
// It is never output when reading from the API. // It is never output when reading from the API.
// +genconversion=false // +k8s:conversion-gen=false
StringData map[string]string `json:"stringData,omitempty" protobuf:"bytes,4,rep,name=stringData"` StringData map[string]string `json:"stringData,omitempty" protobuf:"bytes,4,rep,name=stringData"`
// Used to facilitate programmatic handling of secret data. // Used to facilitate programmatic handling of secret data.

View File

@ -15,6 +15,6 @@ limitations under the License.
*/ */
// +k8s:deepcopy-gen=package,register // +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/apps
// +genconversion=true
package v1alpha1 package v1alpha1

View File

@ -15,6 +15,6 @@ limitations under the License.
*/ */
// +k8s:deepcopy-gen=package,register // +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/authentication.k8s.io
// +genconversion=true
package v1beta1 package v1beta1

View File

@ -15,6 +15,6 @@ limitations under the License.
*/ */
// +k8s:deepcopy-gen=package,register // +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/authorization
// +genconversion=true
package v1beta1 package v1beta1

View File

@ -15,6 +15,6 @@ limitations under the License.
*/ */
// +k8s:deepcopy-gen=package,register // +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/autoscaling
// +genconversion=true
package v1 package v1

View File

@ -15,6 +15,6 @@ limitations under the License.
*/ */
// +k8s:deepcopy-gen=package,register // +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/batch
// +genconversion=true
package v1 package v1

View File

@ -15,6 +15,6 @@ limitations under the License.
*/ */
// +k8s:deepcopy-gen=package,register // +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/batch
// +genconversion=true
package v2alpha1 package v2alpha1

View File

@ -15,6 +15,6 @@ limitations under the License.
*/ */
// +k8s:deepcopy-gen=package,register // +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/certificates
// +genconversion=true
package v1alpha1 package v1alpha1

View File

@ -15,6 +15,6 @@ limitations under the License.
*/ */
// +k8s:deepcopy-gen=package,register // +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/componentconfig
// +genconversion=true
package v1alpha1 package v1alpha1

View File

@ -62,6 +62,8 @@ func init() {
Convert_extensions_DeploymentStatus_To_v1beta1_DeploymentStatus, Convert_extensions_DeploymentStatus_To_v1beta1_DeploymentStatus,
Convert_v1beta1_DeploymentStrategy_To_extensions_DeploymentStrategy, Convert_v1beta1_DeploymentStrategy_To_extensions_DeploymentStrategy,
Convert_extensions_DeploymentStrategy_To_v1beta1_DeploymentStrategy, Convert_extensions_DeploymentStrategy_To_v1beta1_DeploymentStrategy,
Convert_v1beta1_ExportOptions_To_api_ExportOptions,
Convert_api_ExportOptions_To_v1beta1_ExportOptions,
Convert_v1beta1_FSGroupStrategyOptions_To_extensions_FSGroupStrategyOptions, Convert_v1beta1_FSGroupStrategyOptions_To_extensions_FSGroupStrategyOptions,
Convert_extensions_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions, Convert_extensions_FSGroupStrategyOptions_To_v1beta1_FSGroupStrategyOptions,
Convert_v1beta1_HTTPIngressPath_To_extensions_HTTPIngressPath, Convert_v1beta1_HTTPIngressPath_To_extensions_HTTPIngressPath,
@ -110,6 +112,8 @@ func init() {
Convert_unversioned_LabelSelector_To_v1beta1_LabelSelector, Convert_unversioned_LabelSelector_To_v1beta1_LabelSelector,
Convert_v1beta1_LabelSelectorRequirement_To_unversioned_LabelSelectorRequirement, Convert_v1beta1_LabelSelectorRequirement_To_unversioned_LabelSelectorRequirement,
Convert_unversioned_LabelSelectorRequirement_To_v1beta1_LabelSelectorRequirement, Convert_unversioned_LabelSelectorRequirement_To_v1beta1_LabelSelectorRequirement,
Convert_v1beta1_ListOptions_To_api_ListOptions,
Convert_api_ListOptions_To_v1beta1_ListOptions,
Convert_v1beta1_NetworkPolicy_To_extensions_NetworkPolicy, Convert_v1beta1_NetworkPolicy_To_extensions_NetworkPolicy,
Convert_extensions_NetworkPolicy_To_v1beta1_NetworkPolicy, Convert_extensions_NetworkPolicy_To_v1beta1_NetworkPolicy,
Convert_v1beta1_NetworkPolicyIngressRule_To_extensions_NetworkPolicyIngressRule, Convert_v1beta1_NetworkPolicyIngressRule_To_extensions_NetworkPolicyIngressRule,
@ -644,6 +648,32 @@ func autoConvert_extensions_DeploymentStrategy_To_v1beta1_DeploymentStrategy(in
return nil return nil
} }
func autoConvert_v1beta1_ExportOptions_To_api_ExportOptions(in *ExportOptions, out *api.ExportOptions, s conversion.Scope) error {
if err := api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
return err
}
out.Export = in.Export
out.Exact = in.Exact
return nil
}
func Convert_v1beta1_ExportOptions_To_api_ExportOptions(in *ExportOptions, out *api.ExportOptions, s conversion.Scope) error {
return autoConvert_v1beta1_ExportOptions_To_api_ExportOptions(in, out, s)
}
func autoConvert_api_ExportOptions_To_v1beta1_ExportOptions(in *api.ExportOptions, out *ExportOptions, s conversion.Scope) error {
if err := api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
return err
}
out.Export = in.Export
out.Exact = in.Exact
return nil
}
func Convert_api_ExportOptions_To_v1beta1_ExportOptions(in *api.ExportOptions, out *ExportOptions, s conversion.Scope) error {
return autoConvert_api_ExportOptions_To_v1beta1_ExportOptions(in, out, s)
}
func autoConvert_v1beta1_FSGroupStrategyOptions_To_extensions_FSGroupStrategyOptions(in *FSGroupStrategyOptions, out *extensions.FSGroupStrategyOptions, s conversion.Scope) error { func autoConvert_v1beta1_FSGroupStrategyOptions_To_extensions_FSGroupStrategyOptions(in *FSGroupStrategyOptions, out *extensions.FSGroupStrategyOptions, s conversion.Scope) error {
out.Rule = extensions.FSGroupStrategyType(in.Rule) out.Rule = extensions.FSGroupStrategyType(in.Rule)
if in.Ranges != nil { if in.Ranges != nil {
@ -1440,6 +1470,46 @@ func Convert_unversioned_LabelSelectorRequirement_To_v1beta1_LabelSelectorRequir
return autoConvert_unversioned_LabelSelectorRequirement_To_v1beta1_LabelSelectorRequirement(in, out, s) return autoConvert_unversioned_LabelSelectorRequirement_To_v1beta1_LabelSelectorRequirement(in, out, s)
} }
func autoConvert_v1beta1_ListOptions_To_api_ListOptions(in *ListOptions, out *api.ListOptions, s conversion.Scope) error {
if err := api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
return err
}
if err := api.Convert_string_To_labels_Selector(&in.LabelSelector, &out.LabelSelector, s); err != nil {
return err
}
if err := api.Convert_string_To_fields_Selector(&in.FieldSelector, &out.FieldSelector, s); err != nil {
return err
}
out.Watch = in.Watch
out.ResourceVersion = in.ResourceVersion
out.TimeoutSeconds = in.TimeoutSeconds
return nil
}
func Convert_v1beta1_ListOptions_To_api_ListOptions(in *ListOptions, out *api.ListOptions, s conversion.Scope) error {
return autoConvert_v1beta1_ListOptions_To_api_ListOptions(in, out, s)
}
func autoConvert_api_ListOptions_To_v1beta1_ListOptions(in *api.ListOptions, out *ListOptions, s conversion.Scope) error {
if err := api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
return err
}
if err := api.Convert_labels_Selector_To_string(&in.LabelSelector, &out.LabelSelector, s); err != nil {
return err
}
if err := api.Convert_fields_Selector_To_string(&in.FieldSelector, &out.FieldSelector, s); err != nil {
return err
}
out.Watch = in.Watch
out.ResourceVersion = in.ResourceVersion
out.TimeoutSeconds = in.TimeoutSeconds
return nil
}
func Convert_api_ListOptions_To_v1beta1_ListOptions(in *api.ListOptions, out *ListOptions, s conversion.Scope) error {
return autoConvert_api_ListOptions_To_v1beta1_ListOptions(in, out, s)
}
func autoConvert_v1beta1_NetworkPolicy_To_extensions_NetworkPolicy(in *NetworkPolicy, out *extensions.NetworkPolicy, s conversion.Scope) error { func autoConvert_v1beta1_NetworkPolicy_To_extensions_NetworkPolicy(in *NetworkPolicy, out *extensions.NetworkPolicy, s conversion.Scope) error {
SetDefaults_NetworkPolicy(in) SetDefaults_NetworkPolicy(in)
if err := api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil { if err := api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {

View File

@ -15,6 +15,8 @@ limitations under the License.
*/ */
// +k8s:deepcopy-gen=package,register // +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/extensions
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/autoscaling
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/batch
// +genconversion=true
package v1beta1 package v1beta1

View File

@ -15,9 +15,9 @@ limitations under the License.
*/ */
// +k8s:deepcopy-gen=package,register // +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/policy
// Package policy is for any kind of policy object. Suitable examples, even if // Package policy is for any kind of policy object. Suitable examples, even if
// they aren't all here, are PodDisruptionBudget, PodSecurityPolicy, // they aren't all here, are PodDisruptionBudget, PodSecurityPolicy,
// NetworkPolicy, etc. // NetworkPolicy, etc.
// +genconversion=true
package v1alpha1 package v1alpha1

View File

@ -16,6 +16,6 @@ limitations under the License.
// +groupName=rbac.authorization.k8s.io // +groupName=rbac.authorization.k8s.io
// +k8s:deepcopy-gen=package,register // +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/rbac
// +genconversion=true
package v1alpha1 package v1alpha1