@@ -17,20 +17,27 @@ limitations under the License.
1717package v1_test
1818
1919import (
20+ "encoding/json"
21+ "math/rand"
2022 "net/url"
2123 "reflect"
2224 "testing"
2325 "time"
2426
2527 "k8s.io/api/core/v1"
28+ extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
2629 apiequality "k8s.io/apimachinery/pkg/api/equality"
2730 "k8s.io/apimachinery/pkg/api/resource"
31+ "k8s.io/apimachinery/pkg/api/testing/fuzzer"
2832 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2933 "k8s.io/apimachinery/pkg/runtime"
3034 "k8s.io/apimachinery/pkg/util/diff"
3135 "k8s.io/kubernetes/pkg/api"
3236 "k8s.io/kubernetes/pkg/api/legacyscheme"
37+ kapitesting "k8s.io/kubernetes/pkg/api/testing"
3338 k8s_api_v1 "k8s.io/kubernetes/pkg/api/v1"
39+ "k8s.io/kubernetes/pkg/apis/extensions"
40+ utilpointer "k8s.io/kubernetes/pkg/util/pointer"
3441
3542 // enforce that all types are installed
3643 _ "k8s.io/kubernetes/pkg/api/testapi"
@@ -226,3 +233,115 @@ func TestResourceListConversion(t *testing.T) {
226233 }
227234 }
228235}
236+
237+ func TestReplicationControllerConversion (t * testing.T ) {
238+ // If we start with a RC, we should always have round-trip fidelity.
239+ inputs := []* v1.ReplicationController {
240+ {
241+ ObjectMeta : metav1.ObjectMeta {
242+ Name : "name" ,
243+ Namespace : "namespace" ,
244+ },
245+ Spec : v1.ReplicationControllerSpec {
246+ Replicas : utilpointer .Int32Ptr (1 ),
247+ MinReadySeconds : 32 ,
248+ Selector : map [string ]string {"foo" : "bar" , "bar" : "foo" },
249+ Template : & v1.PodTemplateSpec {
250+ ObjectMeta : metav1.ObjectMeta {
251+ Labels : map [string ]string {"foo" : "bar" , "bar" : "foo" },
252+ },
253+ Spec : v1.PodSpec {
254+ Containers : []v1.Container {
255+ {
256+ Name : "container" ,
257+ Image : "image" ,
258+ },
259+ },
260+ },
261+ },
262+ },
263+ Status : v1.ReplicationControllerStatus {
264+ Replicas : 1 ,
265+ FullyLabeledReplicas : 2 ,
266+ ReadyReplicas : 3 ,
267+ AvailableReplicas : 4 ,
268+ ObservedGeneration : 5 ,
269+ Conditions : []v1.ReplicationControllerCondition {
270+ {
271+ Type : v1 .ReplicationControllerReplicaFailure ,
272+ Status : v1 .ConditionTrue ,
273+ LastTransitionTime : metav1 .NewTime (time .Unix (123456789 , 0 )),
274+ Reason : "Reason" ,
275+ Message : "Message" ,
276+ },
277+ },
278+ },
279+ },
280+ }
281+
282+ // Add some fuzzed RCs.
283+ apiObjectFuzzer := fuzzer .FuzzerFor (kapitesting .FuzzerFuncs , rand .NewSource (152 ), legacyscheme .Codecs )
284+ for i := 0 ; i < 100 ; i ++ {
285+ rc := & v1.ReplicationController {}
286+ apiObjectFuzzer .Fuzz (rc )
287+ // Sometimes the fuzzer decides to leave Spec.Template nil.
288+ // We can't support that because Spec.Template is not a pointer in RS,
289+ // so it will round-trip as non-nil but empty.
290+ if rc .Spec .Template == nil {
291+ rc .Spec .Template = & v1.PodTemplateSpec {}
292+ }
293+ // Sometimes the fuzzer decides to insert an empty label key.
294+ // This doesn't round-trip properly because it's invalid.
295+ if rc .Spec .Selector != nil {
296+ delete (rc .Spec .Selector , "" )
297+ }
298+ inputs = append (inputs , rc )
299+ }
300+
301+ // Round-trip the input RCs before converting to RS.
302+ for i := range inputs {
303+ inputs [i ] = roundTrip (t , inputs [i ]).(* v1.ReplicationController )
304+ }
305+
306+ for _ , in := range inputs {
307+ rs := & extensions.ReplicaSet {}
308+ // Use in.DeepCopy() to avoid sharing pointers with `in`.
309+ if err := k8s_api_v1 .Convert_v1_ReplicationController_to_extensions_ReplicaSet (in .DeepCopy (), rs , nil ); err != nil {
310+ t .Errorf ("can't convert RC to RS: %v" , err )
311+ continue
312+ }
313+ // Round-trip RS before converting back to RC.
314+ rs = roundTripRS (t , rs )
315+ out := & v1.ReplicationController {}
316+ if err := k8s_api_v1 .Convert_extensions_ReplicaSet_to_v1_ReplicationController (rs , out , nil ); err != nil {
317+ t .Errorf ("can't convert RS to RC: %v" , err )
318+ continue
319+ }
320+ if ! apiequality .Semantic .DeepEqual (in , out ) {
321+ instr , _ := json .MarshalIndent (in , "" , " " )
322+ outstr , _ := json .MarshalIndent (out , "" , " " )
323+ t .Errorf ("RC-RS conversion round-trip failed:\n in:\n %s\n out:\n %s" , instr , outstr )
324+ }
325+ }
326+ }
327+
328+ func roundTripRS (t * testing.T , rs * extensions.ReplicaSet ) * extensions.ReplicaSet {
329+ codec := legacyscheme .Codecs .LegacyCodec (extensionsv1beta1 .SchemeGroupVersion )
330+ data , err := runtime .Encode (codec , rs )
331+ if err != nil {
332+ t .Errorf ("%v\n %#v" , err , rs )
333+ return nil
334+ }
335+ obj2 , err := runtime .Decode (codec , data )
336+ if err != nil {
337+ t .Errorf ("%v\n Data: %s\n Source: %#v" , err , string (data ), rs )
338+ return nil
339+ }
340+ obj3 := & extensions.ReplicaSet {}
341+ err = legacyscheme .Scheme .Convert (obj2 , obj3 , nil )
342+ if err != nil {
343+ t .Errorf ("%v\n Source: %#v" , err , obj2 )
344+ return nil
345+ }
346+ return obj3
347+ }
0 commit comments