@@ -22,15 +22,20 @@ import (
22
22
"reflect"
23
23
"testing"
24
24
25
+ "github.com/stretchr/testify/assert"
25
26
appsv1 "k8s.io/api/apps/v1"
26
27
corev1 "k8s.io/api/core/v1"
28
+ apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
27
29
"k8s.io/apimachinery/pkg/api/meta"
28
30
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29
31
"k8s.io/apimachinery/pkg/runtime"
32
+ "k8s.io/apimachinery/pkg/runtime/schema"
30
33
"k8s.io/apimachinery/pkg/types"
34
+ "k8s.io/apimachinery/pkg/util/uuid"
31
35
fakedynamic "k8s.io/client-go/dynamic/fake"
32
36
"k8s.io/client-go/kubernetes/scheme"
33
37
"k8s.io/client-go/tools/record"
38
+ "k8s.io/utils/ptr"
34
39
controllerruntime "sigs.k8s.io/controller-runtime"
35
40
"sigs.k8s.io/controller-runtime/pkg/client"
36
41
"sigs.k8s.io/controller-runtime/pkg/client/fake"
@@ -39,6 +44,7 @@ import (
39
44
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
40
45
workv1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1"
41
46
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
47
+ "github.com/karmada-io/karmada/pkg/events"
42
48
testing2 "github.com/karmada-io/karmada/pkg/search/proxy/testing"
43
49
"github.com/karmada-io/karmada/pkg/util"
44
50
"github.com/karmada-io/karmada/pkg/util/fedinformer/genericmanager"
@@ -439,3 +445,119 @@ func TestClusterResourceBindingController_newOverridePolicyFunc(t *testing.T) {
439
445
})
440
446
}
441
447
}
448
+
449
+ func TestUpdateClusterBindingDispatchingConditionIfNeeded (t * testing.T ) {
450
+ tests := []struct {
451
+ name string
452
+ binding * workv1alpha2.ClusterResourceBinding
453
+ expectedCondition metav1.Condition
454
+ expectedEventCount int
455
+ expectEventMessage string
456
+ }{
457
+ {
458
+ name : "Binding scheduling is suspended" ,
459
+ binding : newCrb (true , metav1.Condition {}),
460
+ expectedCondition : metav1.Condition {
461
+ Type : workv1alpha2 .SchedulingSuspended ,
462
+ Status : metav1 .ConditionTrue ,
463
+ },
464
+ expectedEventCount : 1 ,
465
+ expectEventMessage : fmt .Sprintf ("%s %s %s" , corev1 .EventTypeNormal , events .EventReasonBindingScheduling , SuspendedSchedulingConditionMessage ),
466
+ },
467
+ {
468
+ name : "Binding scheduling is not suspended" ,
469
+ binding : newCrb (false , metav1.Condition {
470
+ Type : workv1alpha2 .SchedulingSuspended ,
471
+ Status : metav1 .ConditionTrue ,
472
+ Reason : SuspendedSchedulingConditionReason ,
473
+ Message : SuspendedSchedulingConditionMessage ,
474
+ }),
475
+ expectedCondition : metav1.Condition {
476
+ Type : workv1alpha2 .SchedulingSuspended ,
477
+ Status : metav1 .ConditionFalse ,
478
+ },
479
+ expectedEventCount : 1 ,
480
+ expectEventMessage : fmt .Sprintf ("%s %s %s" , corev1 .EventTypeNormal , events .EventReasonBindingScheduling , SchedulingConditionMessage ),
481
+ },
482
+ {
483
+ name : "Condition already matches, no update needed" ,
484
+ binding : newCrb (true , metav1.Condition {
485
+ Type : workv1alpha2 .SchedulingSuspended ,
486
+ Status : metav1 .ConditionTrue ,
487
+ Reason : SuspendedSchedulingConditionReason ,
488
+ Message : SuspendedSchedulingConditionMessage ,
489
+ }),
490
+ expectedCondition : metav1.Condition {
491
+ Type : workv1alpha2 .SchedulingSuspended ,
492
+ Status : metav1 .ConditionTrue ,
493
+ },
494
+ },
495
+ {
496
+ name : "No SchedulingSuspended condition and scheduling is not suspended, no update needed" ,
497
+ binding : newCrb (false , metav1.Condition {
498
+ Type : workv1alpha2 .BindingReasonUnschedulable ,
499
+ Status : metav1 .ConditionTrue ,
500
+ }),
501
+ expectedCondition : metav1.Condition {
502
+ Type : workv1alpha2 .BindingReasonUnschedulable ,
503
+ Status : metav1 .ConditionTrue ,
504
+ },
505
+ },
506
+ }
507
+
508
+ for _ , tt := range tests {
509
+ t .Run (tt .name , func (t * testing.T ) {
510
+ eventRecorder := record .NewFakeRecorder (1 )
511
+ c := newClusterResourceBindingController (tt .binding , eventRecorder )
512
+
513
+ updatedBinding := & workv1alpha2.ClusterResourceBinding {}
514
+ assert .NoError (t , c .Get (context .Background (), types.NamespacedName {Name : tt .binding .Name , Namespace : tt .binding .Namespace }, updatedBinding ))
515
+
516
+ err := updateBindingDispatchingConditionIfNeeded (context .Background (), c .Client , c .EventRecorder , tt .binding , apiextensionsv1 .ClusterScoped )
517
+ if err != nil {
518
+ t .Errorf ("updateBindingDispatchingConditionIfNeeded() returned an error: %v" , err )
519
+ }
520
+
521
+ assert .NoError (t , c .Get (context .Background (), types.NamespacedName {Name : tt .binding .Name , Namespace : tt .binding .Namespace }, updatedBinding ))
522
+ assert .True (t , meta .IsStatusConditionPresentAndEqual (updatedBinding .Status .Conditions , tt .expectedCondition .Type , tt .expectedCondition .Status ))
523
+ assert .Equal (t , tt .expectedEventCount , len (eventRecorder .Events ))
524
+ if tt .expectEventMessage != "" {
525
+ e := <- eventRecorder .Events
526
+ assert .Equal (t , tt .expectEventMessage , e )
527
+ }
528
+ })
529
+ }
530
+ }
531
+
532
+ func newClusterResourceBindingController (binding * workv1alpha2.ClusterResourceBinding , eventRecord record.EventRecorder ) ClusterResourceBindingController {
533
+ restMapper := meta .NewDefaultRESTMapper ([]schema.GroupVersion {corev1 .SchemeGroupVersion })
534
+ fakeClient := fake .NewClientBuilder ().WithScheme (gclient .NewSchema ()).WithObjects (binding ).WithStatusSubresource (binding ).WithRESTMapper (restMapper ).Build ()
535
+ return ClusterResourceBindingController {
536
+ Client : fakeClient ,
537
+ EventRecorder : eventRecord ,
538
+ }
539
+ }
540
+
541
+ func newCrb (suspended bool , condition metav1.Condition ) * workv1alpha2.ClusterResourceBinding {
542
+ return & workv1alpha2.ClusterResourceBinding {
543
+ TypeMeta : metav1.TypeMeta {
544
+ Kind : workv1alpha2 .ResourceKindResourceBinding ,
545
+ APIVersion : workv1alpha2 .GroupVersion .Version ,
546
+ },
547
+ ObjectMeta : metav1.ObjectMeta {
548
+ Name : "test-rb" ,
549
+ Namespace : "default" ,
550
+ UID : uuid .NewUUID (),
551
+ },
552
+ Spec : workv1alpha2.ResourceBindingSpec {
553
+ Suspension : & workv1alpha2.Suspension {
554
+ Scheduling : ptr .To (suspended ),
555
+ },
556
+ },
557
+ Status : workv1alpha2.ResourceBindingStatus {
558
+ Conditions : []metav1.Condition {
559
+ condition ,
560
+ },
561
+ },
562
+ }
563
+ }
0 commit comments