diff --git a/pkg/api/serialization_test.go b/pkg/api/serialization_test.go index 3ec93d2896e..4a44937a913 100644 --- a/pkg/api/serialization_test.go +++ b/pkg/api/serialization_test.go @@ -38,8 +38,12 @@ import ( apitesting "k8s.io/kubernetes/pkg/api/testing" "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/v1" + "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" + "k8s.io/kubernetes/pkg/conversion" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime/serializer/streaming" + "k8s.io/kubernetes/pkg/runtime/serializer/versioning" "k8s.io/kubernetes/pkg/util/diff" "k8s.io/kubernetes/pkg/util/sets" "k8s.io/kubernetes/pkg/watch" @@ -144,6 +148,61 @@ func roundTripSame(t *testing.T, group testapi.TestGroup, item runtime.Object, e } } +func Convert_v1beta1_ReplicaSet_to_api_ReplicationController(in *v1beta1.ReplicaSet, out *api.ReplicationController, s conversion.Scope) error { + intermediate1 := &extensions.ReplicaSet{} + if err := v1beta1.Convert_v1beta1_ReplicaSet_To_extensions_ReplicaSet(in, intermediate1, s); err != nil { + return err + } + + intermediate2 := &v1.ReplicationController{} + if err := v1.Convert_extensions_ReplicaSet_to_v1_ReplicationController(intermediate1, intermediate2, s); err != nil { + return err + } + + return v1.Convert_v1_ReplicationController_To_api_ReplicationController(intermediate2, out, s) +} + +func TestSetControllerConversion(t *testing.T) { + if err := api.Scheme.AddConversionFuncs(Convert_v1beta1_ReplicaSet_to_api_ReplicationController); err != nil { + t.Fatal(err) + } + + rs := &extensions.ReplicaSet{} + rc := &api.ReplicationController{} + + extGroup := testapi.Extensions + defaultGroup := testapi.Default + + fuzzInternalObject(t, extGroup.InternalGroupVersion(), rs, rand.Int63()) + + t.Logf("rs._internal.extensions -> rs.v1beta1.extensions") + data, err := runtime.Encode(extGroup.Codec(), rs) + if err != nil { + t.Fatalf("unexpected encoding error: %v", err) + } + + decoder := api.Codecs.UniversalDecoder(*extGroup.GroupVersion(), *defaultGroup.GroupVersion()) + if err := versioning.EnableCrossGroupDecoding(decoder, extGroup.GroupVersion().Group, defaultGroup.GroupVersion().Group); err != nil { + t.Fatalf("unexpected error while enabling cross-group decoding: %v", err) + } + + t.Logf("rs.v1beta1.extensions -> rc._internal") + if err := runtime.DecodeInto(decoder, data, rc); err != nil { + t.Fatalf("unexpected decoding error: %v", err) + } + + t.Logf("rc._internal -> rc.v1") + data, err = runtime.Encode(defaultGroup.Codec(), rc) + if err != nil { + t.Fatalf("unexpected encoding error: %v", err) + } + + t.Logf("rc.v1 -> rs._internal.extensions") + if err := runtime.DecodeInto(decoder, data, rs); err != nil { + t.Fatalf("unexpected decoding error: %v", err) + } +} + // For debugging problems func TestSpecificKind(t *testing.T) { kind := "DaemonSet" diff --git a/pkg/api/v1/conversion.go b/pkg/api/v1/conversion.go index 642b1bc5e58..f180b3348d7 100644 --- a/pkg/api/v1/conversion.go +++ b/pkg/api/v1/conversion.go @@ -19,10 +19,13 @@ package v1 import ( "encoding/json" "fmt" + "reflect" "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/conversion" "k8s.io/kubernetes/pkg/runtime" + "k8s.io/kubernetes/pkg/util/validation/field" ) const ( @@ -31,6 +34,9 @@ const ( // Value used to identify mirror pods from pre-v1.1 kubelet. mirrorAnnotationValue_1_0 = "mirror" + + // annotation key prefix used to identify non-convertible json paths. + NonConvertibleAnnotationPrefix = "kubernetes.io/non-convertible" ) func addConversionFuncs(scheme *runtime.Scheme) { @@ -46,6 +52,12 @@ func addConversionFuncs(scheme *runtime.Scheme) { Convert_v1_Secret_To_api_Secret, Convert_v1_ServiceSpec_To_api_ServiceSpec, Convert_v1_ResourceList_To_api_ResourceList, + Convert_v1_ReplicationController_to_extensions_ReplicaSet, + Convert_v1_ReplicationControllerSpec_to_extensions_ReplicaSetSpec, + Convert_v1_ReplicationControllerStatus_to_extensions_ReplicaSetStatus, + Convert_extensions_ReplicaSet_to_v1_ReplicationController, + Convert_extensions_ReplicaSetSpec_to_v1_ReplicationControllerSpec, + Convert_extensions_ReplicaSetStatus_to_v1_ReplicationControllerStatus, ) if err != nil { // If one of the conversion functions is malformed, detect it immediately. @@ -199,17 +211,107 @@ func addConversionFuncs(scheme *runtime.Scheme) { } } +func Convert_v1_ReplicationController_to_extensions_ReplicaSet(in *ReplicationController, out *extensions.ReplicaSet, s conversion.Scope) error { + if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found { + defaulting.(func(*ReplicationController))(in) + } + if err := api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil { + return err + } + if err := Convert_v1_ObjectMeta_To_api_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, s); err != nil { + return err + } + if err := Convert_v1_ReplicationControllerSpec_to_extensions_ReplicaSetSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1_ReplicationControllerStatus_to_extensions_ReplicaSetStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +func Convert_v1_ReplicationControllerSpec_to_extensions_ReplicaSetSpec(in *ReplicationControllerSpec, out *extensions.ReplicaSetSpec, s conversion.Scope) error { + if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found { + defaulting.(func(*ReplicationControllerSpec))(in) + } + out.Replicas = *in.Replicas + if in.Selector != nil { + api.Convert_map_to_unversioned_LabelSelector(&in.Selector, out.Selector, s) + } + if in.Template != nil { + if err := Convert_v1_PodTemplateSpec_To_api_PodTemplateSpec(in.Template, &out.Template, s); err != nil { + return err + } + } + return nil +} + +func Convert_v1_ReplicationControllerStatus_to_extensions_ReplicaSetStatus(in *ReplicationControllerStatus, out *extensions.ReplicaSetStatus, s conversion.Scope) error { + if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found { + defaulting.(func(*ReplicationControllerStatus))(in) + } + out.Replicas = in.Replicas + out.FullyLabeledReplicas = in.FullyLabeledReplicas + out.ObservedGeneration = in.ObservedGeneration + return nil +} + +func Convert_extensions_ReplicaSet_to_v1_ReplicationController(in *extensions.ReplicaSet, out *ReplicationController, s conversion.Scope) error { + if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found { + defaulting.(func(*extensions.ReplicaSet))(in) + } + if err := api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil { + return err + } + if err := Convert_api_ObjectMeta_To_v1_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, s); err != nil { + return err + } + if err := Convert_extensions_ReplicaSetSpec_to_v1_ReplicationControllerSpec(&in.Spec, &out.Spec, s); err != nil { + fieldErr, ok := err.(*field.Error) + if !ok { + return err + } + if out.Annotations == nil { + out.Annotations = make(map[string]string) + } + out.Annotations[NonConvertibleAnnotationPrefix+"/"+fieldErr.Field] = reflect.ValueOf(fieldErr.BadValue).String() + } + if err := Convert_extensions_ReplicaSetStatus_to_v1_ReplicationControllerStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +func Convert_extensions_ReplicaSetSpec_to_v1_ReplicationControllerSpec(in *extensions.ReplicaSetSpec, out *ReplicationControllerSpec, s conversion.Scope) error { + if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found { + defaulting.(func(*extensions.ReplicaSetSpec))(in) + } + out.Replicas = new(int32) + *out.Replicas = in.Replicas + var invalidErr error + if in.Selector != nil { + invalidErr = api.Convert_unversioned_LabelSelector_to_map(in.Selector, &out.Selector, s) + } + out.Template = new(PodTemplateSpec) + if err := Convert_api_PodTemplateSpec_To_v1_PodTemplateSpec(&in.Template, out.Template, s); err != nil { + return err + } + return invalidErr +} + +func Convert_extensions_ReplicaSetStatus_to_v1_ReplicationControllerStatus(in *extensions.ReplicaSetStatus, out *ReplicationControllerStatus, s conversion.Scope) error { + if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found { + defaulting.(func(*extensions.ReplicaSetStatus))(in) + } + out.Replicas = in.Replicas + out.FullyLabeledReplicas = in.FullyLabeledReplicas + out.ObservedGeneration = in.ObservedGeneration + return nil +} + func Convert_api_ReplicationControllerSpec_To_v1_ReplicationControllerSpec(in *api.ReplicationControllerSpec, out *ReplicationControllerSpec, s conversion.Scope) error { out.Replicas = &in.Replicas out.Selector = in.Selector - //if in.TemplateRef != nil { - // out.TemplateRef = new(ObjectReference) - // if err := Convert_api_ObjectReference_To_v1_ObjectReference(in.TemplateRef, out.TemplateRef, s); err != nil { - // return err - // } - //} else { - // out.TemplateRef = nil - //} if in.Template != nil { out.Template = new(PodTemplateSpec) if err := Convert_api_PodTemplateSpec_To_v1_PodTemplateSpec(in.Template, out.Template, s); err != nil { @@ -224,15 +326,6 @@ func Convert_api_ReplicationControllerSpec_To_v1_ReplicationControllerSpec(in *a func Convert_v1_ReplicationControllerSpec_To_api_ReplicationControllerSpec(in *ReplicationControllerSpec, out *api.ReplicationControllerSpec, s conversion.Scope) error { out.Replicas = *in.Replicas out.Selector = in.Selector - - //if in.TemplateRef != nil { - // out.TemplateRef = new(api.ObjectReference) - // if err := Convert_v1_ObjectReference_To_api_ObjectReference(in.TemplateRef, out.TemplateRef, s); err != nil { - // return err - // } - //} else { - // out.TemplateRef = nil - //} if in.Template != nil { out.Template = new(api.PodTemplateSpec) if err := Convert_v1_PodTemplateSpec_To_api_PodTemplateSpec(in.Template, out.Template, s); err != nil {