Merge pull request #45057 from caesarxuchao/fix-conversion-for-pr

Automatic merge from submit-queue (batch tested with PRs 45057, 47259)

Allow conversion-gen to take types that are not in the output path

Part of fixing https://github.com/kubernetes/kubernetes/issues/44065.

Partially address https://github.com/kubernetes/features/issues/282.

The first commit is the changes to the conversion-gen (and vendor).

The second commit moves the api/v1 types to staging, and the third commit shows the resulted changes in the generated conversions.
This commit is contained in:
Kubernetes Submit Queue 2017-06-09 15:16:41 -07:00 committed by GitHub
commit e1efc5465d

View File

@ -46,13 +46,26 @@ type CustomArgs struct {
SkipUnsafe bool
}
// This is the comment tag that carries parameters for conversion generation.
const tagName = "k8s:conversion-gen"
// These are the comment tags that carry parameters for conversion generation.
const (
// e.g., "+k8s:conversion-gen=<peer-pkg>" in doc.go, where <peer-pkg> is the
// import path of the package the peer types are defined in.
// e.g., "+k8s:conversion-gen=false" in a type's comment will let
// conversion-gen skip that type.
tagName = "k8s:conversion-gen"
// e.g., "+k8s:conversion-gen-external-types=<type-pkg>" in doc.go, where
// <type-pkg> is the relative path to the package the types are defined in.
externalTypesTagName = "k8s:conversion-gen-external-types"
)
func extractTag(comments []string) []string {
return types.ExtractCommentTags("+", comments)[tagName]
}
func extractExternalTypesTag(comments []string) []string {
return types.ExtractCommentTags("+", comments)[externalTypesTagName]
}
func isCopyOnly(comments []string) bool {
values := types.ExtractCommentTags("+", comments)["k8s:conversion-fn"]
return len(values) == 1 && values[0] == "copy-only"
@ -198,6 +211,10 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
for i := range inputs {
glog.V(5).Infof("considering pkg %q", i)
pkg := context.Universe[i]
// typesPkg is where the versioned types are defined. Sometimes it is
// different from pkg. For example, kubernetes core/v1 types are defined
// in vendor/k8s.io/api/core/v1, while pkg is at pkg/api/v1.
typesPkg := pkg
if pkg == nil {
// If the input had no Go files, for example.
continue
@ -224,6 +241,24 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
skipUnsafe = customArgs.SkipUnsafe
}
// if the external types are not in the same package where the conversion functions to be generated
externalTypesValues := extractExternalTypesTag(pkg.Comments)
if externalTypesValues != nil {
if len(externalTypesValues) != 1 {
glog.Fatalf(" expect only one value for %q tag, got: %q", externalTypesTagName, externalTypesValues)
}
externalTypes := externalTypesValues[0]
glog.V(5).Infof(" external types tags: %q", externalTypes)
var err error
typesPkg, err = context.AddDirectory(filepath.Join(pkg.Path, externalTypes))
if err != nil {
glog.Fatalf("cannot import package %s", externalTypes)
}
// update context.Order to the latest context.Universe
orderer := namer.Orderer{Namer: namer.NewPublicNamer(1)}
context.Order = orderer.OrderUniverse(context.Universe)
}
// if the source path is within a /vendor/ directory (for example,
// k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/apis/meta/v1), allow
// generation to output to the proper relative path (under vendor).
@ -263,11 +298,11 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
HeaderText: header,
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
return []generator.Generator{
NewGenConversion(arguments.OutputFileBaseName, pkg.Path, manualConversions, peerPkgs, unsafeEquality),
NewGenConversion(arguments.OutputFileBaseName, typesPkg.Path, pkg.Path, manualConversions, peerPkgs, unsafeEquality),
}
},
FilterFunc: func(c *generator.Context, t *types.Type) bool {
return t.Name.Package == pkg.Path
return t.Name.Package == typesPkg.Path
},
})
}
@ -380,7 +415,12 @@ type TypesEqual interface {
// genConversion produces a file with a autogenerated conversions.
type genConversion struct {
generator.DefaultGen
targetPackage string
// the package that contains the types that conversion func are going to be
// generated for
typesPackage string
// the package that the conversion funcs are going to be output to
outputPackage string
// packages that contain the peer of types in typesPacakge
peerPackages []string
manualConversions conversionFuncMap
imports namer.ImportTracker
@ -389,12 +429,13 @@ type genConversion struct {
useUnsafe TypesEqual
}
func NewGenConversion(sanitizedName, targetPackage string, manualConversions conversionFuncMap, peerPkgs []string, useUnsafe TypesEqual) generator.Generator {
func NewGenConversion(sanitizedName, typesPackage, outputPackage string, manualConversions conversionFuncMap, peerPkgs []string, useUnsafe TypesEqual) generator.Generator {
return &genConversion{
DefaultGen: generator.DefaultGen{
OptionalName: sanitizedName,
},
targetPackage: targetPackage,
typesPackage: typesPackage,
outputPackage: outputPackage,
peerPackages: peerPkgs,
manualConversions: manualConversions,
imports: generator.NewImportTracker(),
@ -407,7 +448,7 @@ func NewGenConversion(sanitizedName, targetPackage string, manualConversions con
func (g *genConversion) Namers(c *generator.Context) namer.NameSystems {
// Have the raw namer for this file track what it imports.
return namer.NameSystems{
"raw": namer.NewRawNamer(g.targetPackage, g.imports),
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
"publicIT": &namerPlusImportTracking{
delegate: conversionNamer(),
tracker: g.imports,
@ -428,13 +469,13 @@ func (n *namerPlusImportTracking) Name(t *types.Type) string {
func (g *genConversion) convertibleOnlyWithinPackage(inType, outType *types.Type) bool {
var t *types.Type
var other *types.Type
if inType.Name.Package == g.targetPackage {
if inType.Name.Package == g.typesPackage {
t, other = inType, outType
} else {
t, other = outType, inType
}
if t.Name.Package != g.targetPackage {
if t.Name.Package != g.typesPackage {
return false
}
// If the type has opted out, skip it.
@ -471,10 +512,10 @@ func (g *genConversion) Filter(c *generator.Context, t *types.Type) bool {
}
func (g *genConversion) isOtherPackage(pkg string) bool {
if pkg == g.targetPackage {
if pkg == g.outputPackage {
return false
}
if strings.HasSuffix(pkg, `"`+g.targetPackage+`"`) {
if strings.HasSuffix(pkg, `"`+g.outputPackage+`"`) {
return false
}
return true