mirror of https://github.com/k3s-io/k3s
Make api use converter package.
parent
a73e4f4623
commit
5c0f5e85e2
|
@ -1,195 +0,0 @@
|
|||
/*
|
||||
Copyright 2014 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type typePair struct {
|
||||
source reflect.Type
|
||||
dest reflect.Type
|
||||
}
|
||||
|
||||
type debugLogger interface {
|
||||
Logf(format string, args ...interface{})
|
||||
}
|
||||
|
||||
// Converter knows how to convert one type to another.
|
||||
type Converter struct {
|
||||
// Map from the conversion pair to a function which can
|
||||
// do the conversion.
|
||||
funcs map[typePair]reflect.Value
|
||||
|
||||
// If true, print helpful debugging info. Quite verbose.
|
||||
debug debugLogger
|
||||
}
|
||||
|
||||
// NewConverter makes a new Converter object.
|
||||
func NewConverter() *Converter {
|
||||
return &Converter{
|
||||
funcs: map[typePair]reflect.Value{},
|
||||
}
|
||||
}
|
||||
|
||||
// Register registers a conversion func with the Converter. conversionFunc must take
|
||||
// two parameters, the input and output type. It must take a pointer to each. It must
|
||||
// return an error.
|
||||
//
|
||||
// Example:
|
||||
// c.Register(func(in *Pod, out *v1beta1.Pod) error { ... return nil })
|
||||
func (c *Converter) Register(conversionFunc interface{}) error {
|
||||
fv := reflect.ValueOf(conversionFunc)
|
||||
ft := fv.Type()
|
||||
if ft.Kind() != reflect.Func {
|
||||
return fmt.Errorf("expected func, got: %v", ft)
|
||||
}
|
||||
if ft.NumIn() != 2 {
|
||||
return fmt.Errorf("expected two in params, got: %v", ft)
|
||||
}
|
||||
if ft.NumOut() != 1 {
|
||||
return fmt.Errorf("expected one out param, got: %v", ft)
|
||||
}
|
||||
if ft.In(0).Kind() != reflect.Ptr {
|
||||
return fmt.Errorf("expected pointer arg for in param 0, got: %v", ft)
|
||||
}
|
||||
if ft.In(1).Kind() != reflect.Ptr {
|
||||
return fmt.Errorf("expected pointer arg for in param 1, got: %v", ft)
|
||||
}
|
||||
var forErrorType error
|
||||
// This convolution is necessary, otherwise TypeOf picks up on the fact
|
||||
// that forErrorType is nil.
|
||||
errorType := reflect.TypeOf(&forErrorType).Elem()
|
||||
if ft.Out(0) != errorType {
|
||||
return fmt.Errorf("expected error return, got: %v", ft)
|
||||
}
|
||||
c.funcs[typePair{ft.In(0).Elem(), ft.In(1).Elem()}] = fv
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert will translate src to dest if it knows how. Both must be pointers.
|
||||
// If no conversion func is registered and the default copying mechanism
|
||||
// doesn't work on this type pair, an error will be returned.
|
||||
// Not safe for objects with cyclic references!
|
||||
func (c *Converter) Convert(src, dest interface{}) error {
|
||||
dv, sv := reflect.ValueOf(dest), reflect.ValueOf(src)
|
||||
if dv.Kind() != reflect.Ptr {
|
||||
return fmt.Errorf("Need pointer, but got %#v", dest)
|
||||
}
|
||||
if sv.Kind() != reflect.Ptr {
|
||||
return fmt.Errorf("Need pointer, but got %#v", src)
|
||||
}
|
||||
dv = dv.Elem()
|
||||
sv = sv.Elem()
|
||||
if !dv.CanAddr() {
|
||||
return fmt.Errorf("Can't write to dest")
|
||||
}
|
||||
return c.convert(sv, dv)
|
||||
}
|
||||
|
||||
// convert recursively copies sv into dv, calling an appropriate conversion function if
|
||||
// one is registered.
|
||||
func (c *Converter) convert(sv, dv reflect.Value) error {
|
||||
dt, st := dv.Type(), sv.Type()
|
||||
if fv, ok := c.funcs[typePair{st, dt}]; ok {
|
||||
if c.debug != nil {
|
||||
c.debug.Logf("Calling custom conversion of '%v' to '%v'", st, dt)
|
||||
}
|
||||
ret := fv.Call([]reflect.Value{sv.Addr(), dv.Addr()})[0].Interface()
|
||||
// This convolution is necssary because nil interfaces won't convert
|
||||
// to errors.
|
||||
if ret == nil {
|
||||
return nil
|
||||
}
|
||||
return ret.(error)
|
||||
}
|
||||
|
||||
if dt.Name() != st.Name() {
|
||||
return fmt.Errorf("Type names don't match: %v, %v", dt.Name(), st.Name())
|
||||
}
|
||||
|
||||
// This should handle all simple types.
|
||||
if st.AssignableTo(dt) {
|
||||
dv.Set(sv)
|
||||
return nil
|
||||
}
|
||||
if st.ConvertibleTo(dt) {
|
||||
dv.Set(sv.Convert(dt))
|
||||
return nil
|
||||
}
|
||||
|
||||
if c.debug != nil {
|
||||
c.debug.Logf("Trying to convert '%v' to '%v'", st, dt)
|
||||
}
|
||||
|
||||
switch dv.Kind() {
|
||||
case reflect.Struct:
|
||||
for i := 0; i < dt.NumField(); i++ {
|
||||
f := dv.Type().Field(i)
|
||||
sf := sv.FieldByName(f.Name)
|
||||
if !sf.IsValid() {
|
||||
return fmt.Errorf("%v not present in source %v for dest %v", f.Name, sv.Type(), dv.Type())
|
||||
}
|
||||
df := dv.Field(i)
|
||||
if err := c.convert(sf, df); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case reflect.Slice:
|
||||
if sv.IsNil() {
|
||||
// Don't make a zero-length slice.
|
||||
dv.Set(reflect.Zero(dt))
|
||||
return nil
|
||||
}
|
||||
dv.Set(reflect.MakeSlice(dt, sv.Len(), sv.Cap()))
|
||||
for i := 0; i < sv.Len(); i++ {
|
||||
if err := c.convert(sv.Index(i), dv.Index(i)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case reflect.Ptr:
|
||||
if sv.IsNil() {
|
||||
// Don't copy a nil ptr!
|
||||
dv.Set(reflect.Zero(dt))
|
||||
return nil
|
||||
}
|
||||
dv.Set(reflect.New(dt.Elem()))
|
||||
return c.convert(sv.Elem(), dv.Elem())
|
||||
case reflect.Map:
|
||||
if sv.IsNil() {
|
||||
// Don't copy a nil ptr!
|
||||
dv.Set(reflect.Zero(dt))
|
||||
return nil
|
||||
}
|
||||
dv.Set(reflect.MakeMap(dt))
|
||||
for _, sk := range sv.MapKeys() {
|
||||
dk := reflect.New(dt.Key()).Elem()
|
||||
if err := c.convert(sk, dk); err != nil {
|
||||
return err
|
||||
}
|
||||
dkv := reflect.New(dt.Elem()).Elem()
|
||||
if err := c.convert(sv.MapIndex(sk), dkv); err != nil {
|
||||
return err
|
||||
}
|
||||
dv.SetMapIndex(dk, dkv)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("Couldn't copy '%v' into '%v'", st, dt)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
/*
|
||||
Copyright 2014 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestConverter(t *testing.T) {
|
||||
type A struct {
|
||||
Foo string
|
||||
}
|
||||
type B struct {
|
||||
Bar string
|
||||
}
|
||||
type C struct{}
|
||||
c := NewConverter()
|
||||
err := c.Register(func(in *A, out *B) error {
|
||||
out.Bar = in.Foo
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
err = c.Register(func(in *B, out *A) error {
|
||||
out.Foo = in.Bar
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
x := A{"hello, intrepid test reader!"}
|
||||
y := B{}
|
||||
|
||||
err = c.Convert(&x, &y)
|
||||
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)
|
||||
}
|
||||
|
||||
z := B{"all your test are belong to us"}
|
||||
w := A{}
|
||||
|
||||
err = c.Convert(&z, &w)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
if e, a := z.Bar, w.Foo; e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
err = c.Register(func(in *A, out *C) error {
|
||||
return fmt.Errorf("C can't store an A, silly")
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
err = c.Convert(&A{}, &C{})
|
||||
if err == nil {
|
||||
t.Errorf("unexpected non-error")
|
||||
}
|
||||
}
|
||||
|
||||
func anonymousEmptyTypeNamedA() interface{} {
|
||||
type A struct{}
|
||||
return &A{}
|
||||
}
|
||||
|
||||
func TestCopyConvertor(t *testing.T) {
|
||||
type A struct {
|
||||
Bar string
|
||||
}
|
||||
type B struct {
|
||||
Bar string
|
||||
}
|
||||
c := NewConverter()
|
||||
err := c.Convert(anonymousEmptyTypeNamedA(), &A{})
|
||||
if err == nil {
|
||||
t.Errorf("unexpected non-error")
|
||||
}
|
||||
|
||||
err = c.Convert(&A{}, anonymousEmptyTypeNamedA())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
err = c.Convert(&B{}, &A{})
|
||||
if err == nil {
|
||||
t.Errorf("unexpected non-error")
|
||||
}
|
||||
}
|
|
@ -17,28 +17,20 @@ limitations under the License.
|
|||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
|
||||
"gopkg.in/v1/yaml"
|
||||
)
|
||||
|
||||
// versionMap allows one to figure out the go type of an object with
|
||||
// the given version and name.
|
||||
var versionMap = map[string]map[string]reflect.Type{}
|
||||
|
||||
// typeToVersion allows one to figure out the version for a given go object.
|
||||
// The reflect.Type we index by should *not* be a pointer. If the same type
|
||||
// is registered for multiple versions, the last one wins.
|
||||
var typeToVersion = map[reflect.Type]string{}
|
||||
|
||||
// theConverter stores all registered conversion functions. It also has
|
||||
// default coverting behavior.
|
||||
var theConverter = NewConverter()
|
||||
var conversionScheme *conversion.Scheme
|
||||
|
||||
func init() {
|
||||
conversionScheme = conversion.NewScheme()
|
||||
conversionScheme.InternalVersion = ""
|
||||
conversionScheme.ExternalVersion = "v1beta1"
|
||||
AddKnownTypes("",
|
||||
PodList{},
|
||||
Pod{},
|
||||
|
@ -98,31 +90,13 @@ func init() {
|
|||
// AddKnownTypes registers the types of the arguments to the marshaller of the package api.
|
||||
// Encode() refuses the object unless its type is registered with AddKnownTypes.
|
||||
func AddKnownTypes(version string, types ...interface{}) {
|
||||
knownTypes, found := versionMap[version]
|
||||
if !found {
|
||||
knownTypes = map[string]reflect.Type{}
|
||||
versionMap[version] = knownTypes
|
||||
}
|
||||
for _, obj := range types {
|
||||
t := reflect.TypeOf(obj)
|
||||
if t.Kind() != reflect.Struct {
|
||||
panic("All types must be structs.")
|
||||
}
|
||||
knownTypes[t.Name()] = t
|
||||
typeToVersion[t] = version
|
||||
}
|
||||
conversionScheme.AddKnownTypes(version, types...)
|
||||
}
|
||||
|
||||
// New returns a new API object of the given version ("" for internal
|
||||
// representation) and name, or an error if it hasn't been registered.
|
||||
func New(versionName, typeName string) (interface{}, error) {
|
||||
if types, ok := versionMap[versionName]; ok {
|
||||
if t, ok := types[typeName]; ok {
|
||||
return reflect.New(t).Interface(), nil
|
||||
}
|
||||
return nil, fmt.Errorf("No type '%v' for version '%v'", typeName, versionName)
|
||||
}
|
||||
return nil, fmt.Errorf("No version '%v'", versionName)
|
||||
return conversionScheme.NewObject(versionName, typeName)
|
||||
}
|
||||
|
||||
// AddConversionFuncs adds a function to the list of conversion functions. The given
|
||||
|
@ -138,20 +112,14 @@ func New(versionName, typeName string) (interface{}, error) {
|
|||
// extra fields, but it must not remove any. So you only need to add a conversion
|
||||
// function for things with changed/removed fields.
|
||||
func AddConversionFuncs(conversionFuncs ...interface{}) error {
|
||||
for _, f := range conversionFuncs {
|
||||
err := theConverter.Register(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return conversionScheme.AddConversionFuncs(conversionFuncs...)
|
||||
}
|
||||
|
||||
// Convert will attempt to convert in into out. Both must be pointers to API objects.
|
||||
// For easy testing of conversion functions. Returns an error if the conversion isn't
|
||||
// possible.
|
||||
func Convert(in, out interface{}) error {
|
||||
return theConverter.Convert(in, out)
|
||||
return conversionScheme.Convert(in, out)
|
||||
}
|
||||
|
||||
// FindJSONBase takes an arbitary api type, returns pointer to its JSONBase field.
|
||||
|
@ -196,11 +164,7 @@ func FindJSONBaseRO(obj interface{}) (JSONBase, error) {
|
|||
|
||||
// EncodeOrDie is a version of Encode which will panic instead of returning an error. For tests.
|
||||
func EncodeOrDie(obj interface{}) string {
|
||||
bytes, err := Encode(obj)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(bytes)
|
||||
return conversionScheme.EncodeOrDie(obj)
|
||||
}
|
||||
|
||||
// Encode turns the given api object into an appropriate JSON string.
|
||||
|
@ -238,93 +202,7 @@ func EncodeOrDie(obj interface{}) string {
|
|||
// upgraded.
|
||||
//
|
||||
func Encode(obj interface{}) (data []byte, err error) {
|
||||
obj = maybeCopy(obj)
|
||||
obj, err = maybeExternalize(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
jsonBase, err := prepareEncode(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err = json.MarshalIndent(obj, "", " ")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Leave these blank in memory.
|
||||
jsonBase.SetKind("")
|
||||
jsonBase.SetAPIVersion("")
|
||||
return data, err
|
||||
}
|
||||
|
||||
// Returns the API version of the go object, or an error if it's not a
|
||||
// pointer or is unregistered.
|
||||
func objAPIVersionAndName(obj interface{}) (apiVersion, name string, err error) {
|
||||
v, err := enforcePtr(obj)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
t := v.Type()
|
||||
if version, ok := typeToVersion[t]; !ok {
|
||||
return "", "", fmt.Errorf("Unregistered type: %v", t)
|
||||
} else {
|
||||
return version, t.Name(), nil
|
||||
}
|
||||
}
|
||||
|
||||
// maybeExternalize converts obj to an external object if it isn't one already.
|
||||
// obj must be a pointer.
|
||||
func maybeExternalize(obj interface{}) (interface{}, error) {
|
||||
version, _, err := objAPIVersionAndName(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if version != "" {
|
||||
// Object is already of an external versioned type.
|
||||
return obj, nil
|
||||
}
|
||||
return externalize(obj)
|
||||
}
|
||||
|
||||
// maybeCopy copies obj if it is not a pointer, to get a settable/addressable
|
||||
// object. Guaranteed to return a pointer.
|
||||
func maybeCopy(obj interface{}) interface{} {
|
||||
v := reflect.ValueOf(obj)
|
||||
if v.Kind() == reflect.Ptr {
|
||||
return obj
|
||||
}
|
||||
v2 := reflect.New(v.Type())
|
||||
v2.Elem().Set(v)
|
||||
return v2.Interface()
|
||||
}
|
||||
|
||||
// prepareEncode sets the APIVersion and Kind fields to match the go type in obj.
|
||||
// Returns an error if the (version, name) pair isn't registered for the type or
|
||||
// if the type is an internal, non-versioned object.
|
||||
func prepareEncode(obj interface{}) (JSONBaseInterface, error) {
|
||||
version, name, err := objAPIVersionAndName(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if version == "" {
|
||||
return nil, fmt.Errorf("No version for '%v' (%#v); extremely inadvisable to write it in wire format.", name, obj)
|
||||
}
|
||||
jsonBase, err := FindJSONBase(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
knownTypes, found := versionMap[version]
|
||||
if !found {
|
||||
return nil, fmt.Errorf("struct %s, %s won't be unmarshalable because it's not in known versions", version, name)
|
||||
}
|
||||
if _, contains := knownTypes[name]; !contains {
|
||||
return nil, fmt.Errorf("struct %s, %s won't be unmarshalable because it's not in knownTypes", version, name)
|
||||
}
|
||||
jsonBase.SetAPIVersion(version)
|
||||
jsonBase.SetKind(name)
|
||||
return jsonBase, nil
|
||||
return conversionScheme.Encode(obj)
|
||||
}
|
||||
|
||||
// Ensures that obj is a pointer of some sort. Returns a reflect.Value of the
|
||||
|
@ -359,35 +237,7 @@ func VersionAndKind(data []byte) (version, kind string, err error) {
|
|||
// by Encode. Only versioned objects (APIVersion != "") are accepted. The object
|
||||
// will be converted into the in-memory unversioned type before being returned.
|
||||
func Decode(data []byte) (interface{}, error) {
|
||||
version, kind, err := VersionAndKind(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if version == "" {
|
||||
return nil, fmt.Errorf("API Version not set in '%s'", string(data))
|
||||
}
|
||||
obj, err := New(version, kind)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Unable to create new object of type ('%s', '%s')", version, kind)
|
||||
}
|
||||
// yaml is a superset of json, so we use it to decode here. That way,
|
||||
// we understand both.
|
||||
err = yaml.Unmarshal(data, obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
obj, err = internalize(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
jsonBase, err := FindJSONBase(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Don't leave these set. Type and version info is deducible from go's type.
|
||||
jsonBase.SetKind("")
|
||||
jsonBase.SetAPIVersion("")
|
||||
return obj, nil
|
||||
return conversionScheme.Decode(data)
|
||||
}
|
||||
|
||||
// DecodeInto parses a YAML or JSON string and stores it in obj. Returns an error
|
||||
|
@ -396,102 +246,5 @@ func Decode(data []byte) (interface{}, error) {
|
|||
// If obj's APIVersion doesn't match that in data, an attempt will be made to convert
|
||||
// data into obj's version.
|
||||
func DecodeInto(data []byte, obj interface{}) error {
|
||||
dataVersion, dataKind, err := VersionAndKind(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
objVersion, objKind, err := objAPIVersionAndName(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if dataKind == "" {
|
||||
// Assume objects with unset Kind fields are being unmarshalled into the
|
||||
// correct type.
|
||||
dataKind = objKind
|
||||
}
|
||||
if dataKind != objKind {
|
||||
return fmt.Errorf("data of kind '%v', obj of type '%v'", dataKind, objKind)
|
||||
}
|
||||
if dataVersion == "" {
|
||||
// Assume objects with unset Version fields are being unmarshalled into the
|
||||
// correct type.
|
||||
dataVersion = objVersion
|
||||
}
|
||||
|
||||
if objVersion == dataVersion {
|
||||
// Easy case!
|
||||
err = yaml.Unmarshal(data, obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// TODO: look up in our map to see if we can do this dataVersion -> objVersion
|
||||
// conversion.
|
||||
if objVersion != "" || dataVersion != "v1beta1" {
|
||||
return fmt.Errorf("Can't convert from '%v' to '%v' for type '%v'", dataVersion, objVersion, dataKind)
|
||||
}
|
||||
|
||||
external, err := New(dataVersion, dataKind)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to create new object of type ('%s', '%s')", dataVersion, dataKind)
|
||||
}
|
||||
// yaml is a superset of json, so we use it to decode here. That way,
|
||||
// we understand both.
|
||||
err = yaml.Unmarshal(data, external)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
internal, err := internalize(external)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Copy to the provided object.
|
||||
vObj := reflect.ValueOf(obj)
|
||||
vInternal := reflect.ValueOf(internal)
|
||||
if !vInternal.Type().AssignableTo(vObj.Type()) {
|
||||
return fmt.Errorf("%s is not assignable to %s", vInternal.Type(), vObj.Type())
|
||||
}
|
||||
vObj.Elem().Set(vInternal.Elem())
|
||||
}
|
||||
|
||||
jsonBase, err := FindJSONBase(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Don't leave these set. Type and version info is deducible from go's type.
|
||||
jsonBase.SetKind("")
|
||||
jsonBase.SetAPIVersion("")
|
||||
return nil
|
||||
}
|
||||
|
||||
func internalize(obj interface{}) (interface{}, error) {
|
||||
_, objKind, err := objAPIVersionAndName(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
objOut, err := New("", objKind)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = theConverter.Convert(obj, objOut)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return objOut, nil
|
||||
}
|
||||
|
||||
func externalize(obj interface{}) (interface{}, error) {
|
||||
_, objKind, err := objAPIVersionAndName(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
objOut, err := New("v1beta1", objKind)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = theConverter.Convert(obj, objOut)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return objOut, nil
|
||||
return conversionScheme.DecodeInto(data, obj)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue