mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Handle aliases correctly in deepcopy/conversion
This commit is contained in:
parent
5f9e7a00b8
commit
1c8b928908
@ -367,6 +367,14 @@ func isDirectlyConvertible(in, out *types.Type, preexisting conversions) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unwrapAlias recurses down aliased types to find the bedrock type.
|
||||||
|
func unwrapAlias(in *types.Type) *types.Type {
|
||||||
|
if in.Kind == types.Alias {
|
||||||
|
return unwrapAlias(in.Underlying)
|
||||||
|
}
|
||||||
|
return in
|
||||||
|
}
|
||||||
|
|
||||||
func areTypesAliased(in, out *types.Type) bool {
|
func areTypesAliased(in, out *types.Type) 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 {
|
||||||
@ -685,11 +693,25 @@ func (g *genConversion) doStruct(inType, outType *types.Type, sw *generator.Snip
|
|||||||
// this field has "genconversion=false" comment to ignore it.
|
// this field has "genconversion=false" comment to ignore it.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
t, outT := m.Type, outMember.Type
|
||||||
|
// create a copy of both underlying types but give them the top level alias name (since aliases
|
||||||
|
// are assignable)
|
||||||
|
if underlying := unwrapAlias(t); underlying != t {
|
||||||
|
copied := *underlying
|
||||||
|
copied.Name = t.Name
|
||||||
|
t = &copied
|
||||||
|
}
|
||||||
|
if underlying := unwrapAlias(outT); underlying != outT {
|
||||||
|
copied := *underlying
|
||||||
|
copied.Name = outT.Name
|
||||||
|
outT = &copied
|
||||||
|
}
|
||||||
args := map[string]interface{}{
|
args := map[string]interface{}{
|
||||||
"inType": m.Type,
|
"inType": t,
|
||||||
"outType": outMember.Type,
|
"outType": outT,
|
||||||
"name": m.Name,
|
"name": m.Name,
|
||||||
}
|
}
|
||||||
|
// check based on the top level name, not the underlying names
|
||||||
if function, ok := g.preexists(m.Type, outMember.Type); ok {
|
if function, ok := g.preexists(m.Type, outMember.Type); ok {
|
||||||
args["function"] = function
|
args["function"] = function
|
||||||
sw.Do("if err := $.function|raw$(&in.$.name$, &out.$.name$, s); err != nil {\n", args)
|
sw.Do("if err := $.function|raw$(&in.$.name$, &out.$.name$, s); err != nil {\n", args)
|
||||||
@ -697,32 +719,32 @@ func (g *genConversion) doStruct(inType, outType *types.Type, sw *generator.Snip
|
|||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
switch m.Type.Kind {
|
switch t.Kind {
|
||||||
case types.Builtin:
|
case types.Builtin:
|
||||||
if m.Type == outMember.Type {
|
if t == outT {
|
||||||
sw.Do("out.$.name$ = in.$.name$\n", args)
|
sw.Do("out.$.name$ = in.$.name$\n", args)
|
||||||
} else {
|
} else {
|
||||||
sw.Do("out.$.name$ = $.outType|raw$(in.$.name$)\n", args)
|
sw.Do("out.$.name$ = $.outType|raw$(in.$.name$)\n", args)
|
||||||
}
|
}
|
||||||
case types.Map, types.Slice, types.Pointer:
|
case types.Map, types.Slice, types.Pointer:
|
||||||
if g.isDirectlyAssignable(m.Type, outMember.Type) {
|
if g.isDirectlyAssignable(t, outT) {
|
||||||
sw.Do("out.$.name$ = in.$.name$\n", args)
|
sw.Do("out.$.name$ = in.$.name$\n", args)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
sw.Do("if in.$.name$ != nil {\n", args)
|
sw.Do("if in.$.name$ != nil {\n", args)
|
||||||
sw.Do("in, out := &in.$.name$, &out.$.name$\n", args)
|
sw.Do("in, out := &in.$.name$, &out.$.name$\n", args)
|
||||||
g.generateFor(m.Type, outMember.Type, sw)
|
g.generateFor(t, outT, sw)
|
||||||
sw.Do("} else {\n", nil)
|
sw.Do("} else {\n", nil)
|
||||||
sw.Do("out.$.name$ = nil\n", args)
|
sw.Do("out.$.name$ = nil\n", args)
|
||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
case types.Struct:
|
case types.Struct:
|
||||||
if g.isDirectlyAssignable(m.Type, outMember.Type) {
|
if g.isDirectlyAssignable(t, outT) {
|
||||||
sw.Do("out.$.name$ = in.$.name$\n", args)
|
sw.Do("out.$.name$ = in.$.name$\n", args)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if g.convertibleOnlyWithinPackage(m.Type, outMember.Type) {
|
if g.convertibleOnlyWithinPackage(t, outT) {
|
||||||
funcName := g.funcNameTmpl(m.Type, outMember.Type)
|
funcName := g.funcNameTmpl(t, outT)
|
||||||
sw.Do(fmt.Sprintf("if err := %s(&in.$.name$, &out.$.name$, s); err != nil {\n", funcName), args)
|
sw.Do(fmt.Sprintf("if err := %s(&in.$.name$, &out.$.name$, s); err != nil {\n", funcName), args)
|
||||||
} else {
|
} else {
|
||||||
sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)
|
sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)
|
||||||
@ -731,15 +753,15 @@ func (g *genConversion) doStruct(inType, outType *types.Type, sw *generator.Snip
|
|||||||
sw.Do("return err\n", nil)
|
sw.Do("return err\n", nil)
|
||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
case types.Alias:
|
case types.Alias:
|
||||||
if outMember.Type.IsAssignable() {
|
if outT.IsAssignable() {
|
||||||
if m.Type == outMember.Type {
|
if t == outT {
|
||||||
sw.Do("out.$.name$ = in.$.name$\n", args)
|
sw.Do("out.$.name$ = in.$.name$\n", args)
|
||||||
} else {
|
} else {
|
||||||
sw.Do("out.$.name$ = $.outType|raw$(in.$.name$)\n", args)
|
sw.Do("out.$.name$ = $.outType|raw$(in.$.name$)\n", args)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if g.convertibleOnlyWithinPackage(m.Type, outMember.Type) {
|
if g.convertibleOnlyWithinPackage(t, outT) {
|
||||||
funcName := g.funcNameTmpl(m.Type, outMember.Type)
|
funcName := g.funcNameTmpl(t, outT)
|
||||||
sw.Do(fmt.Sprintf("if err := %s(&in.$.name$, &out.$.name$, s); err != nil {\n", funcName), args)
|
sw.Do(fmt.Sprintf("if err := %s(&in.$.name$, &out.$.name$, s); err != nil {\n", funcName), args)
|
||||||
} else {
|
} else {
|
||||||
sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)
|
sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)
|
||||||
@ -749,8 +771,8 @@ func (g *genConversion) doStruct(inType, outType *types.Type, sw *generator.Snip
|
|||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
if g.convertibleOnlyWithinPackage(m.Type, outMember.Type) {
|
if g.convertibleOnlyWithinPackage(t, outT) {
|
||||||
funcName := g.funcNameTmpl(m.Type, outMember.Type)
|
funcName := g.funcNameTmpl(t, outT)
|
||||||
sw.Do(fmt.Sprintf("if err := %s(&in.$.name$, &out.$.name$, s); err != nil {\n", funcName), args)
|
sw.Do(fmt.Sprintf("if err := %s(&in.$.name$, &out.$.name$, s); err != nil {\n", funcName), args)
|
||||||
} else {
|
} else {
|
||||||
sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)
|
sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)
|
||||||
|
@ -409,23 +409,29 @@ func (g *genDeepCopy) doSlice(t *types.Type, sw *generator.SnippetWriter) {
|
|||||||
|
|
||||||
func (g *genDeepCopy) doStruct(t *types.Type, sw *generator.SnippetWriter) {
|
func (g *genDeepCopy) doStruct(t *types.Type, sw *generator.SnippetWriter) {
|
||||||
for _, m := range t.Members {
|
for _, m := range t.Members {
|
||||||
|
t := m.Type
|
||||||
|
if t.Kind == types.Alias {
|
||||||
|
copied := *t.Underlying
|
||||||
|
copied.Name = t.Name
|
||||||
|
t = &copied
|
||||||
|
}
|
||||||
args := map[string]interface{}{
|
args := map[string]interface{}{
|
||||||
"type": m.Type,
|
"type": t,
|
||||||
"name": m.Name,
|
"name": m.Name,
|
||||||
}
|
}
|
||||||
switch m.Type.Kind {
|
switch t.Kind {
|
||||||
case types.Builtin:
|
case types.Builtin:
|
||||||
sw.Do("out.$.name$ = in.$.name$\n", args)
|
sw.Do("out.$.name$ = in.$.name$\n", args)
|
||||||
case types.Map, types.Slice, types.Pointer:
|
case types.Map, types.Slice, types.Pointer:
|
||||||
sw.Do("if in.$.name$ != nil {\n", args)
|
sw.Do("if in.$.name$ != nil {\n", args)
|
||||||
sw.Do("in, out := in.$.name$, &out.$.name$\n", args)
|
sw.Do("in, out := in.$.name$, &out.$.name$\n", args)
|
||||||
g.generateFor(m.Type, sw)
|
g.generateFor(t, sw)
|
||||||
sw.Do("} else {\n", nil)
|
sw.Do("} else {\n", nil)
|
||||||
sw.Do("out.$.name$ = nil\n", args)
|
sw.Do("out.$.name$ = nil\n", args)
|
||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
case types.Struct:
|
case types.Struct:
|
||||||
if g.canInlineTypeFn(g.context, m.Type) {
|
if g.canInlineTypeFn(g.context, t) {
|
||||||
funcName := g.funcNameTmpl(m.Type)
|
funcName := g.funcNameTmpl(t)
|
||||||
sw.Do(fmt.Sprintf("if err := %s(in.$.name$, &out.$.name$, c); err != nil {\n", funcName), args)
|
sw.Do(fmt.Sprintf("if err := %s(in.$.name$, &out.$.name$, c); err != nil {\n", funcName), args)
|
||||||
sw.Do("return err\n", nil)
|
sw.Do("return err\n", nil)
|
||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
@ -437,17 +443,13 @@ func (g *genDeepCopy) doStruct(t *types.Type, sw *generator.SnippetWriter) {
|
|||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
if m.Type.Kind == types.Alias && m.Type.Underlying.Kind == types.Builtin {
|
sw.Do("if in.$.name$ == nil {\n", args)
|
||||||
sw.Do("out.$.name$ = in.$.name$\n", args)
|
sw.Do("out.$.name$ = nil\n", args)
|
||||||
} else {
|
sw.Do("} else if newVal, err := c.DeepCopy(in.$.name$); err != nil {\n", args)
|
||||||
sw.Do("if in.$.name$ == nil {\n", args)
|
sw.Do("return err\n", nil)
|
||||||
sw.Do("out.$.name$ = nil\n", args)
|
sw.Do("} else {\n", nil)
|
||||||
sw.Do("} else if newVal, err := c.DeepCopy(in.$.name$); err != nil {\n", args)
|
sw.Do("out.$.name$ = newVal.($.type|raw$)\n", args)
|
||||||
sw.Do("return err\n", nil)
|
sw.Do("}\n", nil)
|
||||||
sw.Do("} else {\n", nil)
|
|
||||||
sw.Do("out.$.name$ = newVal.($.type|raw$)\n", args)
|
|
||||||
sw.Do("}\n", nil)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,19 @@ func main() {
|
|||||||
|
|
||||||
// Override defaults. These are Kubernetes specific input locations.
|
// Override defaults. These are Kubernetes specific input locations.
|
||||||
arguments.InputDirs = []string{
|
arguments.InputDirs = []string{
|
||||||
|
// generate all types, but do not register them
|
||||||
|
"+k8s.io/kubernetes/pkg/api/unversioned",
|
||||||
|
|
||||||
|
"-k8s.io/kubernetes/pkg/api/meta",
|
||||||
|
"-k8s.io/kubernetes/pkg/api/meta/metatypes",
|
||||||
|
"-k8s.io/kubernetes/pkg/api/resource",
|
||||||
|
"-k8s.io/kubernetes/pkg/conversion",
|
||||||
|
"-k8s.io/kubernetes/pkg/labels",
|
||||||
|
"-k8s.io/kubernetes/pkg/runtime",
|
||||||
|
"-k8s.io/kubernetes/pkg/runtime/serializer",
|
||||||
|
"-k8s.io/kubernetes/pkg/util/intstr",
|
||||||
|
"-k8s.io/kubernetes/pkg/util/sets",
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api",
|
"k8s.io/kubernetes/pkg/api",
|
||||||
"k8s.io/kubernetes/pkg/api/v1",
|
"k8s.io/kubernetes/pkg/api/v1",
|
||||||
"k8s.io/kubernetes/pkg/apis/authentication.k8s.io",
|
"k8s.io/kubernetes/pkg/apis/authentication.k8s.io",
|
||||||
@ -61,19 +74,6 @@ func main() {
|
|||||||
"k8s.io/kubernetes/pkg/apis/rbac/v1alpha1",
|
"k8s.io/kubernetes/pkg/apis/rbac/v1alpha1",
|
||||||
"k8s.io/kubernetes/federation/apis/federation",
|
"k8s.io/kubernetes/federation/apis/federation",
|
||||||
"k8s.io/kubernetes/federation/apis/federation/v1alpha1",
|
"k8s.io/kubernetes/federation/apis/federation/v1alpha1",
|
||||||
|
|
||||||
// generate all types, but do not register them
|
|
||||||
"+k8s.io/kubernetes/pkg/api/unversioned",
|
|
||||||
|
|
||||||
"-k8s.io/kubernetes/pkg/api/meta",
|
|
||||||
"-k8s.io/kubernetes/pkg/api/meta/metatypes",
|
|
||||||
"-k8s.io/kubernetes/pkg/api/resource",
|
|
||||||
"-k8s.io/kubernetes/pkg/conversion",
|
|
||||||
"-k8s.io/kubernetes/pkg/labels",
|
|
||||||
"-k8s.io/kubernetes/pkg/runtime",
|
|
||||||
"-k8s.io/kubernetes/pkg/runtime/serializer",
|
|
||||||
"-k8s.io/kubernetes/pkg/util/intstr",
|
|
||||||
"-k8s.io/kubernetes/pkg/util/sets",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := arguments.Execute(
|
if err := arguments.Execute(
|
||||||
|
@ -591,9 +591,6 @@ func (b *Builder) walkType(u types.Universe, useName *types.Name, in tc.Type) *t
|
|||||||
// "feature" for users. This flattens those types
|
// "feature" for users. This flattens those types
|
||||||
// together.
|
// together.
|
||||||
name := tcNameToName(t.String())
|
name := tcNameToName(t.String())
|
||||||
if name.Name == "OptionalMap" {
|
|
||||||
fmt.Printf("DEBUG: flattening %T -> %T\n", t, t.Underlying())
|
|
||||||
}
|
|
||||||
if out := u.Type(name); out.Kind != types.Unknown {
|
if out := u.Type(name); out.Kind != types.Unknown {
|
||||||
return out // short circuit if we've already made this.
|
return out // short circuit if we've already made this.
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
resource "k8s.io/kubernetes/pkg/api/resource"
|
resource "k8s.io/kubernetes/pkg/api/resource"
|
||||||
conversion "k8s.io/kubernetes/pkg/conversion"
|
conversion "k8s.io/kubernetes/pkg/conversion"
|
||||||
runtime "k8s.io/kubernetes/pkg/runtime"
|
runtime "k8s.io/kubernetes/pkg/runtime"
|
||||||
|
types "k8s.io/kubernetes/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -3593,7 +3594,7 @@ func autoConvert_v1_ObjectMeta_To_api_ObjectMeta(in *ObjectMeta, out *api.Object
|
|||||||
out.GenerateName = in.GenerateName
|
out.GenerateName = in.GenerateName
|
||||||
out.Namespace = in.Namespace
|
out.Namespace = in.Namespace
|
||||||
out.SelfLink = in.SelfLink
|
out.SelfLink = in.SelfLink
|
||||||
out.UID = in.UID
|
out.UID = types.UID(in.UID)
|
||||||
out.ResourceVersion = in.ResourceVersion
|
out.ResourceVersion = in.ResourceVersion
|
||||||
out.Generation = in.Generation
|
out.Generation = in.Generation
|
||||||
if err := api.Convert_unversioned_Time_To_unversioned_Time(&in.CreationTimestamp, &out.CreationTimestamp, s); err != nil {
|
if err := api.Convert_unversioned_Time_To_unversioned_Time(&in.CreationTimestamp, &out.CreationTimestamp, s); err != nil {
|
||||||
@ -3627,7 +3628,7 @@ func autoConvert_api_ObjectMeta_To_v1_ObjectMeta(in *api.ObjectMeta, out *Object
|
|||||||
out.GenerateName = in.GenerateName
|
out.GenerateName = in.GenerateName
|
||||||
out.Namespace = in.Namespace
|
out.Namespace = in.Namespace
|
||||||
out.SelfLink = in.SelfLink
|
out.SelfLink = in.SelfLink
|
||||||
out.UID = in.UID
|
out.UID = types.UID(in.UID)
|
||||||
out.ResourceVersion = in.ResourceVersion
|
out.ResourceVersion = in.ResourceVersion
|
||||||
out.Generation = in.Generation
|
out.Generation = in.Generation
|
||||||
if err := api.Convert_unversioned_Time_To_unversioned_Time(&in.CreationTimestamp, &out.CreationTimestamp, s); err != nil {
|
if err := api.Convert_unversioned_Time_To_unversioned_Time(&in.CreationTimestamp, &out.CreationTimestamp, s); err != nil {
|
||||||
@ -3660,7 +3661,7 @@ func autoConvert_v1_ObjectReference_To_api_ObjectReference(in *ObjectReference,
|
|||||||
out.Kind = in.Kind
|
out.Kind = in.Kind
|
||||||
out.Namespace = in.Namespace
|
out.Namespace = in.Namespace
|
||||||
out.Name = in.Name
|
out.Name = in.Name
|
||||||
out.UID = in.UID
|
out.UID = types.UID(in.UID)
|
||||||
out.APIVersion = in.APIVersion
|
out.APIVersion = in.APIVersion
|
||||||
out.ResourceVersion = in.ResourceVersion
|
out.ResourceVersion = in.ResourceVersion
|
||||||
out.FieldPath = in.FieldPath
|
out.FieldPath = in.FieldPath
|
||||||
@ -3675,7 +3676,7 @@ func autoConvert_api_ObjectReference_To_v1_ObjectReference(in *api.ObjectReferen
|
|||||||
out.Kind = in.Kind
|
out.Kind = in.Kind
|
||||||
out.Namespace = in.Namespace
|
out.Namespace = in.Namespace
|
||||||
out.Name = in.Name
|
out.Name = in.Name
|
||||||
out.UID = in.UID
|
out.UID = types.UID(in.UID)
|
||||||
out.APIVersion = in.APIVersion
|
out.APIVersion = in.APIVersion
|
||||||
out.ResourceVersion = in.ResourceVersion
|
out.ResourceVersion = in.ResourceVersion
|
||||||
out.FieldPath = in.FieldPath
|
out.FieldPath = in.FieldPath
|
||||||
@ -3690,7 +3691,7 @@ func autoConvert_v1_OwnerReference_To_api_OwnerReference(in *OwnerReference, out
|
|||||||
out.APIVersion = in.APIVersion
|
out.APIVersion = in.APIVersion
|
||||||
out.Kind = in.Kind
|
out.Kind = in.Kind
|
||||||
out.Name = in.Name
|
out.Name = in.Name
|
||||||
out.UID = in.UID
|
out.UID = types.UID(in.UID)
|
||||||
out.Controller = in.Controller
|
out.Controller = in.Controller
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -3703,7 +3704,7 @@ func autoConvert_api_OwnerReference_To_v1_OwnerReference(in *api.OwnerReference,
|
|||||||
out.APIVersion = in.APIVersion
|
out.APIVersion = in.APIVersion
|
||||||
out.Kind = in.Kind
|
out.Kind = in.Kind
|
||||||
out.Name = in.Name
|
out.Name = in.Name
|
||||||
out.UID = in.UID
|
out.UID = types.UID(in.UID)
|
||||||
out.Controller = in.Controller
|
out.Controller = in.Controller
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user