mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-30 15:05:27 +00:00
Cleanup old-style conversions
This commit is contained in:
parent
ab6cbd2e8d
commit
7ab3e436f7
@ -93,7 +93,12 @@ func NewConverter(nameFn NameFunc) *Converter {
|
||||
inputFieldMappingFuncs: make(map[reflect.Type]FieldMappingFunc),
|
||||
inputDefaultFlags: make(map[reflect.Type]FieldMatchingFlags),
|
||||
}
|
||||
c.RegisterConversionFunc(Convert_Slice_byte_To_Slice_byte)
|
||||
c.RegisterUntypedConversionFunc(
|
||||
(*[]byte)(nil), (*[]byte)(nil),
|
||||
func(a, b interface{}, s Scope) error {
|
||||
return Convert_Slice_byte_To_Slice_byte(a.(*[]byte), b.(*[]byte), s)
|
||||
},
|
||||
)
|
||||
return c
|
||||
}
|
||||
|
||||
@ -159,25 +164,11 @@ func NewConversionFuncs() ConversionFuncs {
|
||||
}
|
||||
|
||||
type ConversionFuncs struct {
|
||||
// FIXME: Remove.
|
||||
fns map[typePair]reflect.Value
|
||||
untyped map[typePair]ConversionFunc
|
||||
}
|
||||
|
||||
// Add adds the provided conversion functions to the lookup table - they must have the signature
|
||||
// `func(type1, type2, Scope) error`. Functions are added in the order passed and will override
|
||||
// previously registered pairs.
|
||||
func (c ConversionFuncs) Add(fns ...interface{}) error {
|
||||
for _, fn := range fns {
|
||||
fv := reflect.ValueOf(fn)
|
||||
ft := fv.Type()
|
||||
if err := verifyConversionFunctionSignature(ft); err != nil {
|
||||
return err
|
||||
}
|
||||
c.fns[typePair{ft.In(0).Elem(), ft.In(1).Elem()}] = fv
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddUntyped adds the provided conversion function to the lookup table for the types that are
|
||||
// supplied as a and b. a and b must be pointers or an error is returned. This method overwrites
|
||||
// previously defined functions.
|
||||
@ -360,29 +351,6 @@ func verifyConversionFunctionSignature(ft reflect.Type) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterConversionFunc registers a conversion func with the
|
||||
// Converter. conversionFunc must take three parameters: a pointer to the input
|
||||
// type, a pointer to the output type, and a conversion.Scope (which should be
|
||||
// used if recursive conversion calls are desired). It must return an error.
|
||||
//
|
||||
// Example:
|
||||
// c.RegisterConversionFunc(
|
||||
// func(in *Pod, out *v1.Pod, s Scope) error {
|
||||
// // conversion logic...
|
||||
// return nil
|
||||
// })
|
||||
// DEPRECATED: Will be removed in favor of RegisterUntypedConversionFunc
|
||||
func (c *Converter) RegisterConversionFunc(conversionFunc interface{}) error {
|
||||
return c.conversionFuncs.Add(conversionFunc)
|
||||
}
|
||||
|
||||
// Similar to RegisterConversionFunc, but registers conversion function that were
|
||||
// automatically generated.
|
||||
// DEPRECATED: Will be removed in favor of RegisterGeneratedUntypedConversionFunc
|
||||
func (c *Converter) RegisterGeneratedConversionFunc(conversionFunc interface{}) error {
|
||||
return c.generatedConversionFuncs.Add(conversionFunc)
|
||||
}
|
||||
|
||||
// RegisterUntypedConversionFunc registers a function that converts between a and b by passing objects of those
|
||||
// types to the provided function. The function *must* accept objects of a and b - this machinery will not enforce
|
||||
// any other guarantee.
|
||||
|
@ -111,24 +111,26 @@ func TestConverter_byteSlice(t *testing.T) {
|
||||
func TestConverter_MismatchedTypes(t *testing.T) {
|
||||
c := NewConverter(DefaultNameFunc)
|
||||
|
||||
err := c.RegisterConversionFunc(
|
||||
func(in *[]string, out *int, s Scope) error {
|
||||
if str, err := strconv.Atoi((*in)[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
*out = str
|
||||
return nil
|
||||
}
|
||||
convertFn := func(in *[]string, out *int, s Scope) error {
|
||||
if str, err := strconv.Atoi((*in)[0]); err != nil {
|
||||
return err
|
||||
} else {
|
||||
*out = str
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if err := c.RegisterUntypedConversionFunc(
|
||||
(*[]string)(nil), (*int)(nil),
|
||||
func(a, b interface{}, s Scope) error {
|
||||
return convertFn(a.(*[]string), b.(*int), s)
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
); err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
src := []string{"5"}
|
||||
var dest *int
|
||||
err = c.Convert(&src, &dest, 0, nil)
|
||||
if err != nil {
|
||||
if err := c.Convert(&src, &dest, 0, nil); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if e, a := 5, *dest; e != a {
|
||||
@ -136,47 +138,6 @@ func TestConverter_MismatchedTypes(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestConverter_DefaultConvert(t *testing.T) {
|
||||
type A struct {
|
||||
Foo string
|
||||
Baz int
|
||||
}
|
||||
type B struct {
|
||||
Bar string
|
||||
Baz int
|
||||
}
|
||||
c := NewConverter(DefaultNameFunc)
|
||||
c.Debug = testLogger(t)
|
||||
c.nameFunc = func(t reflect.Type) string { return "MyType" }
|
||||
|
||||
// Ensure conversion funcs can call DefaultConvert to get default behavior,
|
||||
// then fixup remaining fields manually
|
||||
err := c.RegisterConversionFunc(func(in *A, out *B, s Scope) error {
|
||||
if err := s.DefaultConvert(in, out, IgnoreMissingFields); err != nil {
|
||||
return err
|
||||
}
|
||||
out.Bar = in.Foo
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
x := A{"hello, intrepid test reader!", 3}
|
||||
y := B{}
|
||||
|
||||
err = c.Convert(&x, &y, 0, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
if e, a := x.Foo, y.Bar; e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := x.Baz, y.Baz; e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConverter_DeepCopy(t *testing.T) {
|
||||
type A struct {
|
||||
Foo *string
|
||||
@ -229,26 +190,35 @@ func TestConverter_CallsRegisteredFunctions(t *testing.T) {
|
||||
type C struct{}
|
||||
c := NewConverter(DefaultNameFunc)
|
||||
c.Debug = testLogger(t)
|
||||
err := c.RegisterConversionFunc(func(in *A, out *B, s Scope) error {
|
||||
convertFn1 := func(in *A, out *B, s Scope) error {
|
||||
out.Bar = in.Foo
|
||||
return s.Convert(&in.Baz, &out.Baz, 0)
|
||||
})
|
||||
if err != nil {
|
||||
}
|
||||
if err := c.RegisterUntypedConversionFunc(
|
||||
(*A)(nil), (*B)(nil),
|
||||
func(a, b interface{}, s Scope) error {
|
||||
return convertFn1(a.(*A), b.(*B), s)
|
||||
},
|
||||
); err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
err = c.RegisterConversionFunc(func(in *B, out *A, s Scope) error {
|
||||
convertFn2 := func(in *B, out *A, s Scope) error {
|
||||
out.Foo = in.Bar
|
||||
return s.Convert(&in.Baz, &out.Baz, 0)
|
||||
})
|
||||
if err != nil {
|
||||
}
|
||||
if err := c.RegisterUntypedConversionFunc(
|
||||
(*B)(nil), (*A)(nil),
|
||||
func(a, b interface{}, s Scope) error {
|
||||
return convertFn2(a.(*B), b.(*A), s)
|
||||
},
|
||||
); err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
x := A{"hello, intrepid test reader!", 3}
|
||||
y := B{}
|
||||
|
||||
err = c.Convert(&x, &y, 0, nil)
|
||||
if err != nil {
|
||||
if err := c.Convert(&x, &y, 0, nil); err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
if e, a := x.Foo, y.Bar; e != a {
|
||||
@ -261,8 +231,7 @@ func TestConverter_CallsRegisteredFunctions(t *testing.T) {
|
||||
z := B{"all your test are belong to us", 42}
|
||||
w := A{}
|
||||
|
||||
err = c.Convert(&z, &w, 0, nil)
|
||||
if err != nil {
|
||||
if err := c.Convert(&z, &w, 0, nil); err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
if e, a := z.Bar, w.Foo; e != a {
|
||||
@ -272,14 +241,18 @@ func TestConverter_CallsRegisteredFunctions(t *testing.T) {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
err = c.RegisterConversionFunc(func(in *A, out *C, s Scope) error {
|
||||
convertFn3 := func(in *A, out *C, s Scope) error {
|
||||
return fmt.Errorf("C can't store an A, silly")
|
||||
})
|
||||
if err != nil {
|
||||
}
|
||||
if err := c.RegisterUntypedConversionFunc(
|
||||
(*A)(nil), (*C)(nil),
|
||||
func(a, b interface{}, s Scope) error {
|
||||
return convertFn3(a.(*A), b.(*C), s)
|
||||
},
|
||||
); err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
err = c.Convert(&A{}, &C{}, 0, nil)
|
||||
if err == nil {
|
||||
if err := c.Convert(&A{}, &C{}, 0, nil); err == nil {
|
||||
t.Errorf("unexpected non-error")
|
||||
}
|
||||
}
|
||||
@ -290,10 +263,16 @@ func TestConverter_IgnoredConversion(t *testing.T) {
|
||||
|
||||
count := 0
|
||||
c := NewConverter(DefaultNameFunc)
|
||||
if err := c.RegisterConversionFunc(func(in *A, out *B, s Scope) error {
|
||||
convertFn := func(in *A, out *B, s Scope) error {
|
||||
count++
|
||||
return nil
|
||||
}); err != nil {
|
||||
}
|
||||
if err := c.RegisterUntypedConversionFunc(
|
||||
(*A)(nil), (*B)(nil),
|
||||
func(a, b interface{}, s Scope) error {
|
||||
return convertFn(a.(*A), b.(*B), s)
|
||||
},
|
||||
); err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
if err := c.RegisterIgnoredConversion(&A{}, &B{}); err != nil {
|
||||
@ -337,14 +316,26 @@ func TestConverter_GeneratedConversionOverridden(t *testing.T) {
|
||||
type A struct{}
|
||||
type B struct{}
|
||||
c := NewConverter(DefaultNameFunc)
|
||||
if err := c.RegisterConversionFunc(func(in *A, out *B, s Scope) error {
|
||||
convertFn1 := func(in *A, out *B, s Scope) error {
|
||||
return nil
|
||||
}); err != nil {
|
||||
}
|
||||
if err := c.RegisterUntypedConversionFunc(
|
||||
(*A)(nil), (*B)(nil),
|
||||
func(a, b interface{}, s Scope) error {
|
||||
return convertFn1(a.(*A), b.(*B), s)
|
||||
},
|
||||
); err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
if err := c.RegisterGeneratedConversionFunc(func(in *A, out *B, s Scope) error {
|
||||
convertFn2 := func(in *A, out *B, s Scope) error {
|
||||
return fmt.Errorf("generated function should be overridden")
|
||||
}); err != nil {
|
||||
}
|
||||
if err := c.RegisterGeneratedUntypedConversionFunc(
|
||||
(*A)(nil), (*B)(nil),
|
||||
func(a, b interface{}, s Scope) error {
|
||||
return convertFn2(a.(*A), b.(*B), s)
|
||||
},
|
||||
); err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
@ -359,21 +350,36 @@ func TestConverter_WithConversionOverridden(t *testing.T) {
|
||||
type A struct{}
|
||||
type B struct{}
|
||||
c := NewConverter(DefaultNameFunc)
|
||||
if err := c.RegisterConversionFunc(func(in *A, out *B, s Scope) error {
|
||||
convertFn1 := func(in *A, out *B, s Scope) error {
|
||||
return fmt.Errorf("conversion function should be overridden")
|
||||
}); err != nil {
|
||||
}
|
||||
if err := c.RegisterUntypedConversionFunc(
|
||||
(*A)(nil), (*B)(nil),
|
||||
func(a, b interface{}, s Scope) error {
|
||||
return convertFn1(a.(*A), b.(*B), s)
|
||||
},
|
||||
); err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
if err := c.RegisterGeneratedConversionFunc(func(in *A, out *B, s Scope) error {
|
||||
convertFn2 := func(in *A, out *B, s Scope) error {
|
||||
return fmt.Errorf("generated function should be overridden")
|
||||
}); err != nil {
|
||||
}
|
||||
if err := c.RegisterGeneratedUntypedConversionFunc(
|
||||
(*A)(nil), (*B)(nil),
|
||||
func(a, b interface{}, s Scope) error {
|
||||
return convertFn2(a.(*A), b.(*B), s)
|
||||
},
|
||||
); err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
ext := NewConversionFuncs()
|
||||
ext.Add(func(in *A, out *B, s Scope) error {
|
||||
return nil
|
||||
})
|
||||
ext.AddUntyped(
|
||||
(*A)(nil), (*B)(nil),
|
||||
func(a, b interface{}, s Scope) error {
|
||||
return nil
|
||||
},
|
||||
)
|
||||
newc := c.WithConversions(ext)
|
||||
|
||||
a := A{}
|
||||
@ -394,13 +400,19 @@ func TestConverter_MapsStringArrays(t *testing.T) {
|
||||
}
|
||||
c := NewConverter(DefaultNameFunc)
|
||||
c.Debug = testLogger(t)
|
||||
if err := c.RegisterConversionFunc(func(input *[]string, out *string, s Scope) error {
|
||||
convertFn1 := func(input *[]string, out *string, s Scope) error {
|
||||
if len(*input) == 0 {
|
||||
*out = ""
|
||||
}
|
||||
*out = (*input)[0]
|
||||
return nil
|
||||
}); err != nil {
|
||||
}
|
||||
if err := c.RegisterUntypedConversionFunc(
|
||||
(*[]string)(nil), (*string)(nil),
|
||||
func(a, b interface{}, s Scope) error {
|
||||
return convertFn1(a.(*[]string), b.(*string), s)
|
||||
},
|
||||
); err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
@ -416,7 +428,7 @@ func TestConverter_MapsStringArrays(t *testing.T) {
|
||||
t.Error("unexpected non-error")
|
||||
}
|
||||
|
||||
if err := c.RegisterConversionFunc(func(input *[]string, out *int, s Scope) error {
|
||||
convertFn2 := func(input *[]string, out *int, s Scope) error {
|
||||
if len(*input) == 0 {
|
||||
*out = 0
|
||||
}
|
||||
@ -427,7 +439,13 @@ func TestConverter_MapsStringArrays(t *testing.T) {
|
||||
}
|
||||
*out = i
|
||||
return nil
|
||||
}); err != nil {
|
||||
}
|
||||
if err := c.RegisterUntypedConversionFunc(
|
||||
(*[]string)(nil), (*int)(nil),
|
||||
func(a, b interface{}, s Scope) error {
|
||||
return convertFn2(a.(*[]string), b.(*int), s)
|
||||
},
|
||||
); err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
@ -447,13 +465,19 @@ func TestConverter_MapsStringArraysWithMappingKey(t *testing.T) {
|
||||
}
|
||||
c := NewConverter(DefaultNameFunc)
|
||||
c.Debug = testLogger(t)
|
||||
if err := c.RegisterConversionFunc(func(input *[]string, out *string, s Scope) error {
|
||||
convertFn := func(input *[]string, out *string, s Scope) error {
|
||||
if len(*input) == 0 {
|
||||
*out = ""
|
||||
}
|
||||
*out = (*input)[0]
|
||||
return nil
|
||||
}); err != nil {
|
||||
}
|
||||
if err := c.RegisterUntypedConversionFunc(
|
||||
(*[]string)(nil), (*string)(nil),
|
||||
func(a, b interface{}, s Scope) error {
|
||||
return convertFn(a.(*[]string), b.(*string), s)
|
||||
},
|
||||
); err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
@ -536,39 +560,43 @@ func TestConverter_MapElemAddr(t *testing.T) {
|
||||
}
|
||||
c := NewConverter(DefaultNameFunc)
|
||||
c.Debug = testLogger(t)
|
||||
err := c.RegisterConversionFunc(
|
||||
func(in *int, out *string, s Scope) error {
|
||||
*out = fmt.Sprintf("%v", *in)
|
||||
return nil
|
||||
convertFn1 := func(in *int, out *string, s Scope) error {
|
||||
*out = fmt.Sprintf("%v", *in)
|
||||
return nil
|
||||
}
|
||||
if err := c.RegisterUntypedConversionFunc(
|
||||
(*int)(nil), (*string)(nil),
|
||||
func(a, b interface{}, s Scope) error {
|
||||
return convertFn1(a.(*int), b.(*string), s)
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
); err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
err = c.RegisterConversionFunc(
|
||||
func(in *string, out *int, s Scope) error {
|
||||
if str, err := strconv.Atoi(*in); err != nil {
|
||||
return err
|
||||
} else {
|
||||
*out = str
|
||||
return nil
|
||||
}
|
||||
convertFn2 := func(in *string, out *int, s Scope) error {
|
||||
if str, err := strconv.Atoi(*in); err != nil {
|
||||
return err
|
||||
} else {
|
||||
*out = str
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if err := c.RegisterUntypedConversionFunc(
|
||||
(*string)(nil), (*int)(nil),
|
||||
func(a, b interface{}, s Scope) error {
|
||||
return convertFn2(a.(*string), b.(*int), s)
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
); err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
f := fuzz.New().NilChance(0).NumElements(3, 3)
|
||||
first := Foo{}
|
||||
second := Bar{}
|
||||
f.Fuzz(&first)
|
||||
err = c.Convert(&first, &second, AllowDifferentFieldTypeNames, nil)
|
||||
if err != nil {
|
||||
if err := c.Convert(&first, &second, AllowDifferentFieldTypeNames, nil); err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
third := Foo{}
|
||||
err = c.Convert(&second, &third, AllowDifferentFieldTypeNames, nil)
|
||||
if err != nil {
|
||||
if err := c.Convert(&second, &third, AllowDifferentFieldTypeNames, nil); err != nil {
|
||||
t.Fatalf("error on Convert: %v", err)
|
||||
}
|
||||
if e, a := first, third; !reflect.DeepEqual(e, a) {
|
||||
@ -585,22 +613,24 @@ func TestConverter_tags(t *testing.T) {
|
||||
}
|
||||
c := NewConverter(DefaultNameFunc)
|
||||
c.Debug = testLogger(t)
|
||||
err := c.RegisterConversionFunc(
|
||||
func(in *string, out *string, s Scope) error {
|
||||
if e, a := "foo", s.SrcTag().Get("test"); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := "bar", s.DestTag().Get("test"); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
return nil
|
||||
convertFn := func(in *string, out *string, s Scope) error {
|
||||
if e, a := "foo", s.SrcTag().Get("test"); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := "bar", s.DestTag().Get("test"); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if err := c.RegisterUntypedConversionFunc(
|
||||
(*string)(nil), (*string)(nil),
|
||||
func(a, b interface{}, s Scope) error {
|
||||
return convertFn(a.(*string), b.(*string), s)
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
); err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
err = c.Convert(&Foo{}, &Bar{}, AllowDifferentFieldTypeNames, nil)
|
||||
if err != nil {
|
||||
if err := c.Convert(&Foo{}, &Bar{}, AllowDifferentFieldTypeNames, nil); err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
@ -611,33 +641,38 @@ func TestConverter_meta(t *testing.T) {
|
||||
c := NewConverter(DefaultNameFunc)
|
||||
c.Debug = testLogger(t)
|
||||
checks := 0
|
||||
err := c.RegisterConversionFunc(
|
||||
func(in *Foo, out *Bar, s Scope) error {
|
||||
if s.Meta() == nil {
|
||||
t.Errorf("Meta did not get passed!")
|
||||
}
|
||||
checks++
|
||||
s.Convert(&in.A, &out.A, 0)
|
||||
return nil
|
||||
convertFn1 := func(in *Foo, out *Bar, s Scope) error {
|
||||
if s.Meta() == nil {
|
||||
t.Errorf("Meta did not get passed!")
|
||||
}
|
||||
checks++
|
||||
s.Convert(&in.A, &out.A, 0)
|
||||
return nil
|
||||
}
|
||||
if err := c.RegisterUntypedConversionFunc(
|
||||
(*Foo)(nil), (*Bar)(nil),
|
||||
func(a, b interface{}, s Scope) error {
|
||||
return convertFn1(a.(*Foo), b.(*Bar), s)
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
); err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
err = c.RegisterConversionFunc(
|
||||
func(in *string, out *string, s Scope) error {
|
||||
if s.Meta() == nil {
|
||||
t.Errorf("Meta did not get passed a second time!")
|
||||
}
|
||||
checks++
|
||||
return nil
|
||||
convertFn2 := func(in *string, out *string, s Scope) error {
|
||||
if s.Meta() == nil {
|
||||
t.Errorf("Meta did not get passed a second time!")
|
||||
}
|
||||
checks++
|
||||
return nil
|
||||
}
|
||||
if err := c.RegisterUntypedConversionFunc(
|
||||
(*string)(nil), (*string)(nil),
|
||||
func(a, b interface{}, s Scope) error {
|
||||
return convertFn2(a.(*string), b.(*string), s)
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
); err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
err = c.Convert(&Foo{}, &Bar{}, 0, &Meta{})
|
||||
if err != nil {
|
||||
if err := c.Convert(&Foo{}, &Bar{}, 0, &Meta{}); err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
if checks != 2 {
|
||||
|
@ -308,45 +308,6 @@ func (s *Scheme) AddIgnoredConversionType(from, to interface{}) error {
|
||||
return s.converter.RegisterIgnoredConversion(from, to)
|
||||
}
|
||||
|
||||
// AddConversionFuncs adds functions to the list of conversion functions. The given
|
||||
// functions should know how to convert between two of your API objects, or their
|
||||
// sub-objects. We deduce how to call these functions from the types of their two
|
||||
// parameters; see the comment for Converter.Register.
|
||||
//
|
||||
// Note that, if you need to copy sub-objects that didn't change, you can use the
|
||||
// conversion.Scope object that will be passed to your conversion function.
|
||||
// Additionally, all conversions started by Scheme will set the SrcVersion and
|
||||
// DestVersion fields on the Meta object. Example:
|
||||
//
|
||||
// s.AddConversionFuncs(
|
||||
// func(in *InternalObject, out *ExternalObject, scope conversion.Scope) error {
|
||||
// // You can depend on Meta() being non-nil, and this being set to
|
||||
// // the source version, e.g., ""
|
||||
// s.Meta().SrcVersion
|
||||
// // You can depend on this being set to the destination version,
|
||||
// // e.g., "v1".
|
||||
// s.Meta().DestVersion
|
||||
// // Call scope.Convert to copy sub-fields.
|
||||
// s.Convert(&in.SubFieldThatMoved, &out.NewLocation.NewName, 0)
|
||||
// return nil
|
||||
// },
|
||||
// )
|
||||
//
|
||||
// (For more detail about conversion functions, see Converter.Register's comment.)
|
||||
//
|
||||
// Also note that the default behavior, if you don't add a conversion function, is to
|
||||
// sanely copy fields that have the same names and same type names. It's OK if the
|
||||
// destination type has extra fields, but it must not remove any. So you only need to
|
||||
// add conversion functions for things with changed/removed fields.
|
||||
func (s *Scheme) AddConversionFuncs(conversionFuncs ...interface{}) error {
|
||||
for _, f := range conversionFuncs {
|
||||
if err := s.converter.RegisterConversionFunc(f); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddConversionFunc registers a function that converts between a and b by passing objects of those
|
||||
// types to the provided function. The function *must* accept objects of a and b - this machinery will not enforce
|
||||
// any other guarantee.
|
||||
|
@ -31,6 +31,47 @@ import (
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
)
|
||||
|
||||
type testConversions struct {
|
||||
internalToExternalCalls int
|
||||
externalToInternalCalls int
|
||||
}
|
||||
|
||||
func (c *testConversions) internalToExternalSimple(in *runtimetesting.InternalSimple, out *runtimetesting.ExternalSimple, scope conversion.Scope) error {
|
||||
if err := scope.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := scope.Convert(&in.TestString, &out.TestString, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
c.internalToExternalCalls++
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *testConversions) externalToInternalSimple(in *runtimetesting.ExternalSimple, out *runtimetesting.InternalSimple, scope conversion.Scope) error {
|
||||
if err := scope.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := scope.Convert(&in.TestString, &out.TestString, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
c.externalToInternalCalls++
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *testConversions) registerConversions(s *runtime.Scheme) error {
|
||||
if err := s.AddConversionFunc((*runtimetesting.InternalSimple)(nil), (*runtimetesting.ExternalSimple)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return c.internalToExternalSimple(a.(*runtimetesting.InternalSimple), b.(*runtimetesting.ExternalSimple), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*runtimetesting.ExternalSimple)(nil), (*runtimetesting.InternalSimple)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return c.externalToInternalSimple(a.(*runtimetesting.ExternalSimple), b.(*runtimetesting.InternalSimple), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestScheme(t *testing.T) {
|
||||
internalGV := schema.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal}
|
||||
internalGVK := internalGV.WithKind("Simple")
|
||||
@ -47,37 +88,13 @@ func TestScheme(t *testing.T) {
|
||||
// test that scheme is an ObjectTyper
|
||||
var _ runtime.ObjectTyper = scheme
|
||||
|
||||
internalToExternalCalls := 0
|
||||
externalToInternalCalls := 0
|
||||
conversions := &testConversions{
|
||||
internalToExternalCalls: 0,
|
||||
externalToInternalCalls: 0,
|
||||
}
|
||||
|
||||
// Register functions to verify that scope.Meta() gets set correctly.
|
||||
err := scheme.AddConversionFuncs(
|
||||
func(in *runtimetesting.InternalSimple, out *runtimetesting.ExternalSimple, scope conversion.Scope) error {
|
||||
err := scope.Convert(&in.TypeMeta, &out.TypeMeta, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = scope.Convert(&in.TestString, &out.TestString, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
internalToExternalCalls++
|
||||
return nil
|
||||
},
|
||||
func(in *runtimetesting.ExternalSimple, out *runtimetesting.InternalSimple, scope conversion.Scope) error {
|
||||
err := scope.Convert(&in.TypeMeta, &out.TypeMeta, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = scope.Convert(&in.TestString, &out.TestString, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
externalToInternalCalls++
|
||||
return nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
if err := conversions.registerConversions(scheme); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
@ -133,8 +150,7 @@ func TestScheme(t *testing.T) {
|
||||
}
|
||||
|
||||
external := &runtimetesting.ExternalSimple{}
|
||||
err = scheme.Convert(simple, external, nil)
|
||||
if err != nil {
|
||||
if err := scheme.Convert(simple, external, nil); err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
if e, a := simple.TestString, external.TestString; e != a {
|
||||
@ -147,12 +163,11 @@ func TestScheme(t *testing.T) {
|
||||
}
|
||||
|
||||
unstructuredObj := &runtimetesting.Unstructured{}
|
||||
err = scheme.Convert(simple, unstructuredObj, nil)
|
||||
err := scheme.Convert(simple, unstructuredObj, nil)
|
||||
if err == nil || !strings.Contains(err.Error(), "to Unstructured without providing a preferred version to convert to") {
|
||||
t.Fatalf("Unexpected non-error: %v", err)
|
||||
}
|
||||
err = scheme.Convert(simple, unstructuredObj, externalGV)
|
||||
if err != nil {
|
||||
if err := scheme.Convert(simple, unstructuredObj, externalGV); err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
if e, a := simple.TestString, unstructuredObj.Object["testString"].(string); e != a {
|
||||
@ -171,8 +186,7 @@ func TestScheme(t *testing.T) {
|
||||
TestString: "foo",
|
||||
}
|
||||
|
||||
err = scheme.Convert(external, unstructuredObj, nil)
|
||||
if err != nil {
|
||||
if err := scheme.Convert(external, unstructuredObj, nil); err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
if e, a := external.TestString, unstructuredObj.Object["testString"].(string); e != a {
|
||||
@ -187,8 +201,7 @@ func TestScheme(t *testing.T) {
|
||||
"test": []interface{}{"other", "test"},
|
||||
}}
|
||||
uOut := &runtimetesting.Unstructured{}
|
||||
err = scheme.Convert(uIn, uOut, nil)
|
||||
if err != nil {
|
||||
if err := scheme.Convert(uIn, uOut, nil); err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(uIn.Object, uOut.Object) {
|
||||
@ -203,8 +216,7 @@ func TestScheme(t *testing.T) {
|
||||
}
|
||||
unstructuredObj.SetGroupVersionKind(externalGV.WithKind("Simple"))
|
||||
externalOut := &runtimetesting.ExternalSimple{}
|
||||
err = scheme.Convert(unstructuredObj, externalOut, nil)
|
||||
if err != nil {
|
||||
if err := scheme.Convert(unstructuredObj, externalOut, nil); err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
if externalOut.TestString != "bla" {
|
||||
@ -212,12 +224,12 @@ func TestScheme(t *testing.T) {
|
||||
}
|
||||
})
|
||||
t.Run("Encode and Convert should each have caused an increment", func(t *testing.T) {
|
||||
if e, a := 3, internalToExternalCalls; e != a {
|
||||
if e, a := 3, conversions.internalToExternalCalls; e != a {
|
||||
t.Errorf("Expected %v, got %v", e, a)
|
||||
}
|
||||
})
|
||||
t.Run("DecodeInto and Decode should each have caused an increment because of a conversion", func(t *testing.T) {
|
||||
if e, a := 2, externalToInternalCalls; e != a {
|
||||
if e, a := 2, conversions.externalToInternalCalls; e != a {
|
||||
t.Errorf("Expected %v, got %v", e, a)
|
||||
}
|
||||
})
|
||||
@ -481,9 +493,12 @@ func GetTestScheme() *runtime.Scheme {
|
||||
s.AddKnownTypeWithName(differentExternalGV.WithKind("TestType1"), &runtimetesting.ExternalTestType1{})
|
||||
s.AddUnversionedTypes(externalGV, &runtimetesting.UnversionedType{})
|
||||
|
||||
utilruntime.Must(s.AddConversionFuncs(func(in *runtimetesting.TestType1, out *runtimetesting.ExternalTestType1, s conversion.Scope) error {
|
||||
convertTestType := func(in *runtimetesting.TestType1, out *runtimetesting.ExternalTestType1, s conversion.Scope) error {
|
||||
out.A = in.A
|
||||
return nil
|
||||
}
|
||||
utilruntime.Must(s.AddConversionFunc((*runtimetesting.TestType1)(nil), (*runtimetesting.ExternalTestType1)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return convertTestType(a.(*runtimetesting.TestType1), b.(*runtimetesting.ExternalTestType1), scope)
|
||||
}))
|
||||
return s
|
||||
}
|
||||
@ -931,25 +946,13 @@ func TestMetaValues(t *testing.T) {
|
||||
s.AddKnownTypeWithName(internalGV.WithKind("Simple"), &runtimetesting.InternalSimple{})
|
||||
s.AddKnownTypeWithName(externalGV.WithKind("Simple"), &runtimetesting.ExternalSimple{})
|
||||
|
||||
internalToExternalCalls := 0
|
||||
externalToInternalCalls := 0
|
||||
conversions := &testConversions{
|
||||
internalToExternalCalls: 0,
|
||||
externalToInternalCalls: 0,
|
||||
}
|
||||
|
||||
// Register functions to verify that scope.Meta() gets set correctly.
|
||||
err := s.AddConversionFuncs(
|
||||
func(in *runtimetesting.InternalSimple, out *runtimetesting.ExternalSimple, scope conversion.Scope) error {
|
||||
t.Logf("internal -> external")
|
||||
scope.Convert(&in.TestString, &out.TestString, 0)
|
||||
internalToExternalCalls++
|
||||
return nil
|
||||
},
|
||||
func(in *runtimetesting.ExternalSimple, out *runtimetesting.InternalSimple, scope conversion.Scope) error {
|
||||
t.Logf("external -> internal")
|
||||
scope.Convert(&in.TestString, &out.TestString, 0)
|
||||
externalToInternalCalls++
|
||||
return nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
if err := conversions.registerConversions(s); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
simple := &runtimetesting.InternalSimple{
|
||||
@ -972,10 +975,10 @@ func TestMetaValues(t *testing.T) {
|
||||
t.Errorf("Expected:\n %#v,\n Got:\n %#v", e, a)
|
||||
}
|
||||
|
||||
if e, a := 1, internalToExternalCalls; e != a {
|
||||
if e, a := 1, conversions.internalToExternalCalls; e != a {
|
||||
t.Errorf("Expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := 1, externalToInternalCalls; e != a {
|
||||
if e, a := 1, conversions.externalToInternalCalls; e != a {
|
||||
t.Errorf("Expected %v, got %v", e, a)
|
||||
}
|
||||
}
|
||||
@ -997,21 +1000,20 @@ func TestMetaValuesUnregisteredConvert(t *testing.T) {
|
||||
internalToExternalCalls := 0
|
||||
|
||||
// Register functions to verify that scope.Meta() gets set correctly.
|
||||
err := s.AddConversionFuncs(
|
||||
func(in *InternalSimple, out *ExternalSimple, scope conversion.Scope) error {
|
||||
scope.Convert(&in.TestString, &out.TestString, 0)
|
||||
internalToExternalCalls++
|
||||
return nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
convertSimple := func(in *InternalSimple, out *ExternalSimple, scope conversion.Scope) error {
|
||||
scope.Convert(&in.TestString, &out.TestString, 0)
|
||||
internalToExternalCalls++
|
||||
return nil
|
||||
}
|
||||
if err := s.AddConversionFunc((*InternalSimple)(nil), (*ExternalSimple)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return convertSimple(a.(*InternalSimple), b.(*ExternalSimple), scope)
|
||||
}); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
simple := &InternalSimple{TestString: "foo"}
|
||||
external := &ExternalSimple{}
|
||||
err = s.Convert(simple, external, nil)
|
||||
if err != nil {
|
||||
if err := s.Convert(simple, external, nil); err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
if e, a := simple.TestString, external.TestString; e != a {
|
||||
|
Loading…
Reference in New Issue
Block a user