Conversions have kube-isms and are not portable for downstream

Some minor fixes to enable generators for OpenShift and others who need
to generate conversions on Kube API groups outside the core.
This commit is contained in:
Clayton Coleman 2016-05-01 23:05:13 -04:00
parent 7e7465e2d4
commit 4554889ae9
No known key found for this signature in database
GPG Key ID: 3D16906B4F1C5CB3
2 changed files with 53 additions and 44 deletions

View File

@ -379,6 +379,8 @@ type genConversion struct {
defaulters defaulters defaulters defaulters
imports namer.ImportTracker imports namer.ImportTracker
typesForInit []conversionType typesForInit []conversionType
globalVariables map[string]interface{}
} }
func NewGenConversion(sanitizedName, targetPackage string, preexisting conversions, defaulters defaulters) generator.Generator { func NewGenConversion(sanitizedName, targetPackage string, preexisting conversions, defaulters defaulters) generator.Generator {
@ -459,12 +461,6 @@ func (g *genConversion) isOtherPackage(pkg string) bool {
func (g *genConversion) Imports(c *generator.Context) (imports []string) { func (g *genConversion) Imports(c *generator.Context) (imports []string) {
var importLines []string var importLines []string
if g.isOtherPackage(apiPackagePath) {
importLines = append(importLines, "api \""+apiPackagePath+"\"")
}
if g.isOtherPackage(conversionPackagePath) {
importLines = append(importLines, "conversion \""+conversionPackagePath+"\"")
}
for _, singleImport := range g.imports.ImportLines() { for _, singleImport := range g.imports.ImportLines() {
if g.isOtherPackage(singleImport) { if g.isOtherPackage(singleImport) {
importLines = append(importLines, singleImport) importLines = append(importLines, singleImport)
@ -473,7 +469,16 @@ func (g *genConversion) Imports(c *generator.Context) (imports []string) {
return importLines return importLines
} }
func argsFromType(inType, outType *types.Type) interface{} { func (g *genConversion) withGlobals(args map[string]interface{}) map[string]interface{} {
for k, v := range g.globalVariables {
if _, ok := args[k]; !ok {
args[k] = v
}
}
return args
}
func argsFromType(inType, outType *types.Type) map[string]interface{} {
return map[string]interface{}{ return map[string]interface{}{
"inType": inType, "inType": inType,
"outType": outType, "outType": outType,
@ -498,13 +503,20 @@ func (g *genConversion) preexists(inType, outType *types.Type) (*types.Type, boo
} }
func (g *genConversion) Init(c *generator.Context, w io.Writer) error { func (g *genConversion) Init(c *generator.Context, w io.Writer) error {
scheme := c.Universe.Variable(types.Name{Package: apiPackagePath, Name: "Scheme"})
g.imports.AddType(scheme)
scope := c.Universe.Type(types.Name{Package: conversionPackagePath, Name: "Scope"})
g.imports.AddType(scope)
g.globalVariables = map[string]interface{}{
"scheme": scheme,
"Scope": scope,
}
sw := generator.NewSnippetWriter(w, c, "$", "$") sw := generator.NewSnippetWriter(w, c, "$", "$")
sw.Do("func init() {\n", nil) sw.Do("func init() {\n", nil)
if g.targetPackage == apiPackagePath { sw.Do("if err := $.scheme|raw$.AddGeneratedConversionFuncs(\n", map[string]interface{}{
sw.Do("if err := Scheme.AddGeneratedConversionFuncs(\n", nil) "scheme": scheme,
} else { })
sw.Do("if err := api.Scheme.AddGeneratedConversionFuncs(\n", nil)
}
for _, conv := range g.typesForInit { for _, conv := range g.typesForInit {
funcName := g.funcNameTmpl(conv.inType, conv.outType) funcName := g.funcNameTmpl(conv.inType, conv.outType)
sw.Do(fmt.Sprintf("%s,\n", funcName), argsFromType(conv.inType, conv.outType)) sw.Do(fmt.Sprintf("%s,\n", funcName), argsFromType(conv.inType, conv.outType))
@ -531,27 +543,19 @@ func (g *genConversion) GenerateType(c *generator.Context, t *types.Type, w io.W
func (g *genConversion) generateConversion(inType, outType *types.Type, sw *generator.SnippetWriter) { func (g *genConversion) generateConversion(inType, outType *types.Type, sw *generator.SnippetWriter) {
funcName := g.funcNameTmpl(inType, outType) funcName := g.funcNameTmpl(inType, outType)
if g.targetPackage == conversionPackagePath {
sw.Do(fmt.Sprintf("func auto%s(in *$.inType|raw$, out *$.outType|raw$, s Scope) error {\n", funcName), 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)))
} else {
sw.Do(fmt.Sprintf("func auto%s(in *$.inType|raw$, out *$.outType|raw$, s conversion.Scope) error {\n", funcName), 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.defaulters[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 preexisting Convert method, generate it.
if _, ok := g.preexists(inType, outType); !ok { if _, ok := g.preexists(inType, outType); !ok {
if g.targetPackage == conversionPackagePath { 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) error {\n", funcName), argsFromType(inType, outType))
} else {
sw.Do(fmt.Sprintf("func %s(in *$.inType|raw$, out *$.outType|raw$, s conversion.Scope) error {\n", funcName), 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))
sw.Do("}\n\n", nil) sw.Do("}\n\n", nil)
} }

View File

@ -76,7 +76,7 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
for _, p := range context.Universe { for _, p := range context.Universe {
copyableType := false copyableType := false
for _, t := range p.Types { for _, t := range p.Types {
if copyableWithinPackage(t) { if copyableWithinPackage(t) && inputs.Has(t.Name.Package) {
copyableType = true copyableType = true
} }
} }
@ -114,6 +114,8 @@ type genDeepCopy struct {
imports namer.ImportTracker imports namer.ImportTracker
typesForInit []*types.Type typesForInit []*types.Type
generateInitFunc bool generateInitFunc bool
globalVariables map[string]interface{}
} }
func NewGenDeepCopy(sanitizedName, targetPackage string, generateInitFunc bool) generator.Generator { func NewGenDeepCopy(sanitizedName, targetPackage string, generateInitFunc bool) generator.Generator {
@ -143,9 +145,6 @@ func (g *genDeepCopy) Filter(c *generator.Context, t *types.Type) bool {
} }
func copyableWithinPackage(t *types.Type) bool { func copyableWithinPackage(t *types.Type) bool {
if !strings.HasPrefix(t.Name.Package, "k8s.io/kubernetes/") {
return false
}
if types.ExtractCommentTags("+", t.CommentLines)["gencopy"] == "false" { if types.ExtractCommentTags("+", t.CommentLines)["gencopy"] == "false" {
return false return false
} }
@ -172,12 +171,6 @@ func (g *genDeepCopy) isOtherPackage(pkg string) bool {
func (g *genDeepCopy) Imports(c *generator.Context) (imports []string) { func (g *genDeepCopy) Imports(c *generator.Context) (imports []string) {
importLines := []string{} importLines := []string{}
if g.isOtherPackage(apiPackagePath) && g.generateInitFunc {
importLines = append(importLines, "api \""+apiPackagePath+"\"")
}
if g.isOtherPackage(conversionPackagePath) {
importLines = append(importLines, "conversion \""+conversionPackagePath+"\"")
}
for _, singleImport := range g.imports.ImportLines() { for _, singleImport := range g.imports.ImportLines() {
if g.isOtherPackage(singleImport) { if g.isOtherPackage(singleImport) {
importLines = append(importLines, singleImport) importLines = append(importLines, singleImport)
@ -186,7 +179,16 @@ func (g *genDeepCopy) Imports(c *generator.Context) (imports []string) {
return importLines return importLines
} }
func argsFromType(t *types.Type) interface{} { func (g *genDeepCopy) withGlobals(args map[string]interface{}) map[string]interface{} {
for k, v := range g.globalVariables {
if _, ok := args[k]; !ok {
args[k] = v
}
}
return args
}
func argsFromType(t *types.Type) map[string]interface{} {
return map[string]interface{}{ return map[string]interface{}{
"type": t, "type": t,
} }
@ -202,19 +204,26 @@ func (g *genDeepCopy) funcNameTmpl(t *types.Type) string {
} }
func (g *genDeepCopy) Init(c *generator.Context, w io.Writer) error { func (g *genDeepCopy) Init(c *generator.Context, w io.Writer) error {
cloner := c.Universe.Type(types.Name{Package: conversionPackagePath, Name: "Cloner"})
g.imports.AddType(cloner)
g.globalVariables = map[string]interface{}{
"Cloner": cloner,
}
if !g.generateInitFunc { if !g.generateInitFunc {
// TODO: We should come up with a solution to register all generated // TODO: We should come up with a solution to register all generated
// deep-copy functions. However, for now, to avoid import cycles // deep-copy functions. However, for now, to avoid import cycles
// we register only those explicitly requested. // we register only those explicitly requested.
return nil return nil
} }
scheme := c.Universe.Variable(types.Name{Package: apiPackagePath, Name: "Scheme"})
g.imports.AddType(scheme)
g.globalVariables["scheme"] = scheme
sw := generator.NewSnippetWriter(w, c, "$", "$") sw := generator.NewSnippetWriter(w, c, "$", "$")
sw.Do("func init() {\n", nil) sw.Do("func init() {\n", nil)
if g.targetPackage == apiPackagePath { sw.Do("if err := $.scheme|raw$.AddGeneratedDeepCopyFuncs(\n", map[string]interface{}{
sw.Do("if err := Scheme.AddGeneratedDeepCopyFuncs(\n", nil) "scheme": scheme,
} else { })
sw.Do("if err := api.Scheme.AddGeneratedDeepCopyFuncs(\n", nil)
}
for _, t := range g.typesForInit { for _, t := range g.typesForInit {
sw.Do(fmt.Sprintf("%s,\n", g.funcNameTmpl(t)), argsFromType(t)) sw.Do(fmt.Sprintf("%s,\n", g.funcNameTmpl(t)), argsFromType(t))
} }
@ -229,11 +238,7 @@ func (g *genDeepCopy) Init(c *generator.Context, w io.Writer) error {
func (g *genDeepCopy) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { func (g *genDeepCopy) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
sw := generator.NewSnippetWriter(w, c, "$", "$") sw := generator.NewSnippetWriter(w, c, "$", "$")
funcName := g.funcNameTmpl(t) funcName := g.funcNameTmpl(t)
if g.targetPackage == conversionPackagePath { sw.Do(fmt.Sprintf("func %s(in $.type|raw$, out *$.type|raw$, c *$.Cloner|raw$) error {\n", funcName), g.withGlobals(argsFromType(t)))
sw.Do(fmt.Sprintf("func %s(in $.type|raw$, out *$.type|raw$, c *Cloner) error {\n", funcName), argsFromType(t))
} else {
sw.Do(fmt.Sprintf("func %s(in $.type|raw$, out *$.type|raw$, c *conversion.Cloner) error {\n", funcName), argsFromType(t))
}
g.generateFor(t, sw) g.generateFor(t, sw)
sw.Do("return nil\n", nil) sw.Do("return nil\n", nil)
sw.Do("}\n\n", nil) sw.Do("}\n\n", nil)