@@ -18,9 +18,11 @@ package sync
18
18
19
19
import (
20
20
"context"
21
+ "fmt"
21
22
"reflect"
22
23
"sort"
23
24
"testing"
25
+ "time"
24
26
25
27
appspub "github.com/openkruise/kruise/apis/apps/pub"
26
28
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
@@ -32,12 +34,29 @@ import (
32
34
v1 "k8s.io/api/core/v1"
33
35
"k8s.io/apimachinery/pkg/api/resource"
34
36
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
37
+ "k8s.io/apimachinery/pkg/runtime"
38
+ "k8s.io/apimachinery/pkg/util/intstr"
39
+ utilruntime "k8s.io/apimachinery/pkg/util/runtime"
35
40
"k8s.io/apimachinery/pkg/util/sets"
41
+ "k8s.io/client-go/kubernetes/scheme"
36
42
"k8s.io/client-go/tools/record"
43
+ corev1 "k8s.io/kubernetes/pkg/apis/core/v1"
44
+ kubecontroller "k8s.io/kubernetes/pkg/controller"
45
+ utilpointer "k8s.io/utils/pointer"
37
46
"sigs.k8s.io/controller-runtime/pkg/client"
38
47
"sigs.k8s.io/controller-runtime/pkg/client/fake"
39
48
)
40
49
50
+ var (
51
+ kscheme * runtime.Scheme
52
+ )
53
+
54
+ func init () {
55
+ kscheme = runtime .NewScheme ()
56
+ utilruntime .Must (appsv1alpha1 .AddToScheme (scheme .Scheme ))
57
+ utilruntime .Must (corev1 .AddToScheme (kscheme ))
58
+ }
59
+
41
60
func newFakeControl () * realControl {
42
61
return & realControl {
43
62
Client : fake .NewClientBuilder ().Build (),
@@ -527,3 +546,119 @@ func TestGetOrGenAvailableIDs(t *testing.T) {
527
546
t .Fatalf ("expected got random id, but actually %v" , id )
528
547
}
529
548
}
549
+
550
+ func TestScale (t * testing.T ) {
551
+ cases := []struct {
552
+ name string
553
+ getCloneSets func () [2 ]* appsv1alpha1.CloneSet
554
+ getRevisions func () [2 ]string
555
+ getPods func () []* v1.Pod
556
+ expectedPodsLen int
557
+ expectedModified bool
558
+ }{
559
+ {
560
+ name : "cloneSet(replicas=3,maxUnavailable=20%,partition=nil,maxSurge=nil,minReadySeconds=9999), pods=5, and scale replicas 5 -> 3" ,
561
+ getCloneSets : func () [2 ]* appsv1alpha1.CloneSet {
562
+ obj := & appsv1alpha1.CloneSet {
563
+ ObjectMeta : metav1.ObjectMeta {
564
+ Name : "sample" ,
565
+ },
566
+ Spec : appsv1alpha1.CloneSetSpec {
567
+ Replicas : utilpointer .Int32 (3 ),
568
+ MinReadySeconds : 9999 ,
569
+ UpdateStrategy : appsv1alpha1.CloneSetUpdateStrategy {
570
+ MaxUnavailable : & intstr.IntOrString {
571
+ Type : intstr .String ,
572
+ StrVal : "20%" ,
573
+ },
574
+ },
575
+ },
576
+ }
577
+ return [2 ]* appsv1alpha1.CloneSet {obj .DeepCopy (), obj .DeepCopy ()}
578
+ },
579
+ getRevisions : func () [2 ]string {
580
+ return [2 ]string {"sample-b976d4544" , "sample-b976d4544" }
581
+ },
582
+ getPods : func () []* v1.Pod {
583
+ t := time .Now ().Add (- time .Second * 10 )
584
+ obj := & v1.Pod {
585
+ ObjectMeta : metav1.ObjectMeta {
586
+ Name : "sample" ,
587
+ Labels : map [string ]string {
588
+ apps .ControllerRevisionHashLabelKey : "sample-b976d4544" ,
589
+ },
590
+ },
591
+ Spec : v1.PodSpec {
592
+ Containers : []v1.Container {
593
+ {
594
+ Name : "main" ,
595
+ Image : "sample:v1" ,
596
+ },
597
+ },
598
+ },
599
+ Status : v1.PodStatus {
600
+ Phase : v1 .PodRunning ,
601
+ Conditions : []v1.PodCondition {
602
+ {
603
+ Type : v1 .PodReady ,
604
+ Status : v1 .ConditionTrue ,
605
+ LastTransitionTime : metav1.Time {Time : t },
606
+ },
607
+ },
608
+ },
609
+ }
610
+ return generatePods (obj , 5 )
611
+ },
612
+ expectedPodsLen : 3 ,
613
+ expectedModified : true ,
614
+ },
615
+ }
616
+
617
+ for _ , cs := range cases {
618
+ t .Run (cs .name , func (t * testing.T ) {
619
+ fClient := fake .NewClientBuilder ().WithScheme (kscheme ).Build ()
620
+ pods := cs .getPods ()
621
+ for _ , pod := range pods {
622
+ err := fClient .Create (context .TODO (), pod )
623
+ if err != nil {
624
+ t .Fatalf (err .Error ())
625
+ }
626
+ }
627
+ rControl := & realControl {
628
+ Client : fClient ,
629
+ recorder : record .NewFakeRecorder (10 ),
630
+ }
631
+ modified , err := rControl .Scale (cs .getCloneSets ()[0 ], cs .getCloneSets ()[1 ], cs .getRevisions ()[0 ], cs .getRevisions ()[1 ], pods , nil )
632
+ if err != nil {
633
+ t .Fatalf (err .Error ())
634
+ }
635
+ if cs .expectedModified != modified {
636
+ t .Fatalf ("expect(%v), but get(%v)" , cs .expectedModified , modified )
637
+ }
638
+ podList := & v1.PodList {}
639
+ err = fClient .List (context .TODO (), podList , & client.ListOptions {})
640
+ if err != nil {
641
+ t .Fatalf (err .Error ())
642
+ }
643
+ actives := 0
644
+ for _ , pod := range podList .Items {
645
+ if kubecontroller .IsPodActive (& pod ) {
646
+ actives ++
647
+ }
648
+ }
649
+ if actives != cs .expectedPodsLen {
650
+ t .Fatalf ("expect(%v), but get(%v)" , cs .expectedPodsLen , actives )
651
+ }
652
+ })
653
+ }
654
+ }
655
+
656
+ func generatePods (base * v1.Pod , replicas int ) []* v1.Pod {
657
+ objs := make ([]* v1.Pod , 0 , replicas )
658
+ for i := 0 ; i < replicas ; i ++ {
659
+ obj := base .DeepCopy ()
660
+ obj .Name = fmt .Sprintf ("%s-%d" , base .Name , i )
661
+ objs = append (objs , obj )
662
+ }
663
+ return objs
664
+ }
0 commit comments