@@ -21,6 +21,7 @@ import (
2121 "k8s.io/apimachinery/pkg/runtime"
2222 "k8s.io/apimachinery/pkg/types"
2323 "k8s.io/client-go/rest"
24+ k8stesting "k8s.io/client-go/testing"
2425 "k8s.io/client-go/tools/record"
2526 controllerruntime "sigs.k8s.io/controller-runtime"
2627 "sigs.k8s.io/controller-runtime/pkg/cache"
@@ -44,6 +45,27 @@ import (
4445 "sigs.k8s.io/controller-runtime/pkg/client/fake"
4546)
4647
48+ func fetchTestingFake (obj interface { RESTClient () rest.Interface }) * k8stesting.Fake {
49+ // https://stackoverflow.com/questions/69740891/mocking-errors-with-client-go-fake-client
50+ return reflect .Indirect (reflect .ValueOf (obj )).FieldByName ("Fake" ).Interface ().(* k8stesting.Fake )
51+ }
52+
53+ func removeReactorFromTestingTake (obj interface { RESTClient () rest.Interface }, verb , resource string ) {
54+ if fakeObj := fetchTestingFake (obj ); fakeObj != nil {
55+ newReactionChain := make ([]k8stesting.Reactor , 0 )
56+ fakeObj .Lock ()
57+ defer fakeObj .Unlock ()
58+ for i := range fakeObj .ReactionChain {
59+ reaction := fakeObj .ReactionChain [i ]
60+ if simpleReaction , ok := reaction .(* k8stesting.SimpleReactor ); ok && simpleReaction .Verb == verb && simpleReaction .Resource == resource {
61+ continue // ignore
62+ }
63+ newReactionChain = append (newReactionChain , reaction )
64+ }
65+ fakeObj .ReactionChain = newReactionChain
66+ }
67+ }
68+
4769func TestCompareClusterCondition (t * testing.T ) {
4870 tests := []struct {
4971 name string
@@ -329,11 +351,39 @@ func Test_CleanExcessClusterOps(t *testing.T) {
329351 }
330352 controller .KubeanClusterOpsSet .KubeanV1alpha1 ().ClusterOperations ().Create (context .Background (), clusterOperation , metav1.CreateOptions {})
331353 }
354+ clusterOperationRunning := & clusteroperationv1alpha1.ClusterOperation {
355+ TypeMeta : metav1.TypeMeta {
356+ Kind : "ClusterOperation" ,
357+ APIVersion : "kubean.io/v1alpha1" ,
358+ },
359+ ObjectMeta : metav1.ObjectMeta {
360+ Name : "my_kubean_ops_cluster_2_" + "running" ,
361+ Labels : map [string ]string {constants .KubeanClusterLabelKey : "cluster1" },
362+ CreationTimestamp : metav1 .Unix (int64 (10 ), 0 ),
363+ },
364+ }
365+ clusterOperationRunning , _ = controller .KubeanClusterOpsSet .KubeanV1alpha1 ().ClusterOperations ().Create (context .Background (), clusterOperationRunning , metav1.CreateOptions {})
366+ clusterOperationRunning .Status = clusteroperationv1alpha1.Status {
367+ Status : clusteroperationv1alpha1 .RunningStatus ,
368+ }
369+ controller .KubeanClusterOpsSet .KubeanV1alpha1 ().ClusterOperations ().UpdateStatus (context .Background (), clusterOperationRunning , metav1.UpdateOptions {})
332370 result , _ := controller .CleanExcessClusterOps (exampleCluster , OpsBackupNum )
333371 return result
334372 },
335373 want : true ,
336374 },
375+ {
376+ name : "get error" ,
377+ args : func () bool {
378+ fetchTestingFake (controller .KubeanClusterOpsSet .KubeanV1alpha1 ()).PrependReactor ("list" , "clusteroperations" , func (action k8stesting.Action ) (handled bool , ret runtime.Object , err error ) {
379+ return true , nil , fmt .Errorf ("this is error" )
380+ })
381+ _ , err := controller .CleanExcessClusterOps (exampleCluster , 5 )
382+ removeReactorFromTestingTake (controller .KubeanClusterOpsSet .KubeanV1alpha1 (), "list" , "clusteroperations" )
383+ return err != nil && err .Error () == "this is error"
384+ },
385+ want : true ,
386+ },
337387 }
338388 for _ , test := range tests {
339389 t .Run (test .name , func (t * testing.T ) {
@@ -410,6 +460,31 @@ func Test_UpdateStatus(t *testing.T) {
410460 },
411461 want : true ,
412462 },
463+ {
464+ name : "get one error" ,
465+ args : func () bool {
466+ exampleCluster := & clusterv1alpha1.Cluster {
467+ TypeMeta : metav1.TypeMeta {
468+ Kind : "Cluster" ,
469+ APIVersion : "kubean.io/v1alpha1" ,
470+ },
471+ ObjectMeta : metav1.ObjectMeta {
472+ Name : "cluster1" ,
473+ },
474+ Spec : clusterv1alpha1.Spec {
475+ HostsConfRef : & apis.ConfigMapRef {NameSpace : "kubean-system" , Name : "hosts-a" },
476+ VarsConfRef : & apis.ConfigMapRef {NameSpace : "kubean-system" , Name : "vars-a" },
477+ },
478+ }
479+ fetchTestingFake (controller .KubeanClusterOpsSet .KubeanV1alpha1 ()).PrependReactor ("list" , "clusteroperations" , func (action k8stesting.Action ) (handled bool , ret runtime.Object , err error ) {
480+ return true , nil , fmt .Errorf ("this is error" )
481+ })
482+ err := controller .UpdateStatus (exampleCluster )
483+ removeReactorFromTestingTake (controller .KubeanClusterOpsSet .KubeanV1alpha1 (), "list" , "clusteroperations" )
484+ return err != nil && err .Error () == "this is error"
485+ },
486+ want : true ,
487+ },
413488 }
414489 for _ , test := range tests {
415490 t .Run (test .name , func (t * testing.T ) {
@@ -491,6 +566,96 @@ func TestReconcile(t *testing.T) {
491566 },
492567 needRequeue : true ,
493568 },
569+ {
570+ name : "CleanExcessClusterOps with error" ,
571+ args : func () bool {
572+ controller := genController ()
573+ exampleCluster := & clusterv1alpha1.Cluster {
574+ TypeMeta : metav1.TypeMeta {
575+ Kind : "Cluster" ,
576+ APIVersion : "kubean.io/v1alpha1" ,
577+ },
578+ ObjectMeta : metav1.ObjectMeta {
579+ Name : "cluster1" ,
580+ },
581+ Spec : clusterv1alpha1.Spec {
582+ HostsConfRef : & apis.ConfigMapRef {NameSpace : "kubean-system" , Name : "hosts-a" },
583+ VarsConfRef : & apis.ConfigMapRef {NameSpace : "kubean-system" , Name : "vars-a" },
584+ },
585+ }
586+ clusterOps := & clusteroperationv1alpha1.ClusterOperation {
587+ TypeMeta : metav1.TypeMeta {
588+ Kind : "ClusterOperation" ,
589+ APIVersion : "kubean.io/v1alpha1" ,
590+ },
591+ ObjectMeta : metav1.ObjectMeta {
592+ Name : "cluster1-ops" ,
593+ Labels : map [string ]string {constants .KubeanClusterLabelKey : exampleCluster .Name },
594+ },
595+ }
596+ controller .Client .Create (context .Background (), clusterOps )
597+ controller .Client .Create (context .Background (), exampleCluster )
598+ controller .KubeanClusterSet .KubeanV1alpha1 ().Clusters ().Create (context .Background (), exampleCluster , metav1.CreateOptions {})
599+ controller .KubeanClusterOpsSet .KubeanV1alpha1 ().ClusterOperations ().Create (context .Background (), clusterOps , metav1.CreateOptions {})
600+ fetchTestingFake (controller .KubeanClusterOpsSet .KubeanV1alpha1 ()).PrependReactor ("list" , "clusteroperations" , func (action k8stesting.Action ) (handled bool , ret runtime.Object , err error ) {
601+ return true , nil , fmt .Errorf ("this is error" )
602+ })
603+ result , _ := controller .Reconcile (context .Background (), controllerruntime.Request {NamespacedName : types.NamespacedName {Name : "cluster1" }})
604+ removeReactorFromTestingTake (controller .KubeanClusterOpsSet .KubeanV1alpha1 (), "list" , "clusteroperations" )
605+ return result .RequeueAfter > 0
606+ },
607+ needRequeue : true ,
608+ },
609+ {
610+ name : "CleanExcessClusterOps with true" ,
611+ args : func () bool {
612+ controller := genController ()
613+ exampleCluster := & clusterv1alpha1.Cluster {
614+ TypeMeta : metav1.TypeMeta {
615+ Kind : "Cluster" ,
616+ APIVersion : "kubean.io/v1alpha1" ,
617+ },
618+ ObjectMeta : metav1.ObjectMeta {
619+ Name : "cluster1" ,
620+ },
621+ Spec : clusterv1alpha1.Spec {
622+ HostsConfRef : & apis.ConfigMapRef {NameSpace : "kubean-system" , Name : "hosts-a" },
623+ VarsConfRef : & apis.ConfigMapRef {NameSpace : "kubean-system" , Name : "vars-a" },
624+ },
625+ }
626+ clusterOps := & clusteroperationv1alpha1.ClusterOperation {
627+ TypeMeta : metav1.TypeMeta {
628+ Kind : "ClusterOperation" ,
629+ APIVersion : "kubean.io/v1alpha1" ,
630+ },
631+ ObjectMeta : metav1.ObjectMeta {
632+ Name : "cluster1-ops" ,
633+ Labels : map [string ]string {constants .KubeanClusterLabelKey : exampleCluster .Name },
634+ },
635+ }
636+ controller .Client .Create (context .Background (), clusterOps )
637+ controller .Client .Create (context .Background (), exampleCluster )
638+ controller .KubeanClusterSet .KubeanV1alpha1 ().Clusters ().Create (context .Background (), exampleCluster , metav1.CreateOptions {})
639+ controller .KubeanClusterOpsSet .KubeanV1alpha1 ().ClusterOperations ().Create (context .Background (), clusterOps , metav1.CreateOptions {})
640+ for i := 0 ; i < 100 ; i ++ {
641+ clusterOperation := & clusteroperationv1alpha1.ClusterOperation {
642+ TypeMeta : metav1.TypeMeta {
643+ Kind : "ClusterOperation" ,
644+ APIVersion : "kubean.io/v1alpha1" ,
645+ },
646+ ObjectMeta : metav1.ObjectMeta {
647+ Name : "my_kubean_ops_cluster_2_" + fmt .Sprint (i ),
648+ Labels : map [string ]string {constants .KubeanClusterLabelKey : "cluster1" },
649+ CreationTimestamp : metav1 .Unix (int64 (i ), 0 ),
650+ },
651+ }
652+ controller .KubeanClusterOpsSet .KubeanV1alpha1 ().ClusterOperations ().Create (context .Background (), clusterOperation , metav1.CreateOptions {})
653+ }
654+ result , _ := controller .Reconcile (context .Background (), controllerruntime.Request {NamespacedName : types.NamespacedName {Name : "cluster1" }})
655+ return result .RequeueAfter > 0
656+ },
657+ needRequeue : true ,
658+ },
494659 }
495660 for _ , test := range tests {
496661 t .Run (test .name , func (t * testing.T ) {
0 commit comments