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
imports namer.ImportTracker
typesForInit []conversionType
globalVariables map[string]interface{}
}
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) {
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() {
if g.isOtherPackage(singleImport) {
importLines = append(importLines, singleImport)
@ -473,7 +469,16 @@ func (g *genConversion) Imports(c *generator.Context) (imports []string) {
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{}{
"inType": inType,
"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 {
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.Do("func init() {\n", nil)
if g.targetPackage == apiPackagePath {
sw.Do("if err := Scheme.AddGeneratedConversionFuncs(\n", nil)
} else {
sw.Do("if err := api.Scheme.AddGeneratedConversionFuncs(\n", nil)
}
sw.Do("if err := $.scheme|raw$.AddGeneratedConversionFuncs(\n", map[string]interface{}{
"scheme": scheme,
})
for _, conv := range g.typesForInit {
funcName := g.funcNameTmpl(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) {
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))
} else {
sw.Do(fmt.Sprintf("func auto%s(in *$.inType|raw$, out *$.outType|raw$, s conversion.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)))
// if no defaulter of form SetDefaults_XXX is defined, do not inline a check for defaulting.
if function, ok := g.defaulters[inType]; ok {
sw.Do("$.|raw$(in)\n", function)
}
g.generateFor(inType, outType, sw)
sw.Do("return nil\n", nil)
sw.Do("}\n\n", nil)
// If there is no public preexisting Convert method, generate it.
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) 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("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("}\n\n", nil)
}

View File

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