@@ -19,6 +19,7 @@ package leaderelection
19
19
import (
20
20
"context"
21
21
"fmt"
22
+ "math/rand"
22
23
"testing"
23
24
"time"
24
25
@@ -27,7 +28,6 @@ import (
27
28
"k8s.io/apimachinery/pkg/api/errors"
28
29
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29
30
"k8s.io/apimachinery/pkg/types"
30
- "k8s.io/apimachinery/pkg/util/runtime"
31
31
"k8s.io/apimachinery/pkg/util/wait"
32
32
"k8s.io/client-go/informers"
33
33
"k8s.io/client-go/kubernetes/fake"
@@ -442,16 +442,16 @@ func TestController(t *testing.T) {
442
442
fakeClock := testingclock .NewFakeClock (time .Now ())
443
443
444
444
cases := []struct {
445
- name string
446
- leaseNN types.NamespacedName
447
- createAfterControllerStart []* v1alpha1.LeaseCandidate
448
- deleteAfterControllerStart []types.NamespacedName
449
- expectedLeaderLeases []* v1.Lease
445
+ name string
446
+ leases []* v1.Lease
447
+ candidates []* v1alpha1.LeaseCandidate
448
+ createAfterControllerStart []* v1alpha1.LeaseCandidate
449
+ deleteLeaseAfterControllerStart []types.NamespacedName
450
+ expectedLeaderLeases []* v1.Lease
450
451
}{
451
452
{
452
- name : "single candidate leader election" ,
453
- leaseNN : types.NamespacedName {Namespace : "kube-system" , Name : "component-A" },
454
- createAfterControllerStart : []* v1alpha1.LeaseCandidate {
453
+ name : "single candidate leader election" ,
454
+ candidates : []* v1alpha1.LeaseCandidate {
455
455
{
456
456
ObjectMeta : metav1.ObjectMeta {
457
457
Namespace : "kube-system" ,
@@ -479,9 +479,8 @@ func TestController(t *testing.T) {
479
479
},
480
480
},
481
481
{
482
- name : "multiple candidate leader election" ,
483
- leaseNN : types.NamespacedName {Namespace : "kube-system" , Name : "component-A" },
484
- createAfterControllerStart : []* v1alpha1.LeaseCandidate {
482
+ name : "multiple candidate leader election" ,
483
+ candidates : []* v1alpha1.LeaseCandidate {
485
484
{
486
485
ObjectMeta : metav1.ObjectMeta {
487
486
Namespace : "kube-system" ,
@@ -535,17 +534,21 @@ func TestController(t *testing.T) {
535
534
},
536
535
},
537
536
{
538
- name : "deletion of lease triggers reelection" ,
539
- leaseNN : types.NamespacedName {Namespace : "kube-system" , Name : "component-A" },
540
- createAfterControllerStart : []* v1alpha1.LeaseCandidate {
537
+ name : "deletion of lease triggers reelection" ,
538
+ leases : []* v1.Lease {
541
539
{
542
- // Leader lease
543
540
ObjectMeta : metav1.ObjectMeta {
544
541
Namespace : "kube-system" ,
545
542
Name : "component-A" ,
546
543
},
547
- Spec : v1alpha1.LeaseCandidateSpec {},
544
+ Spec : v1.LeaseSpec {
545
+ HolderIdentity : ptr .To ("some-other-component" ),
546
+ RenewTime : ptr .To (metav1 .NewMicroTime (fakeClock .Now ().Add (time .Second ))),
547
+ LeaseDurationSeconds : ptr .To (int32 (10 )),
548
+ },
548
549
},
550
+ },
551
+ candidates : []* v1alpha1.LeaseCandidate {
549
552
{
550
553
ObjectMeta : metav1.ObjectMeta {
551
554
Namespace : "kube-system" ,
@@ -560,7 +563,7 @@ func TestController(t *testing.T) {
560
563
},
561
564
},
562
565
},
563
- deleteAfterControllerStart : []types.NamespacedName {
566
+ deleteLeaseAfterControllerStart : []types.NamespacedName {
564
567
{Namespace : "kube-system" , Name : "component-A" },
565
568
},
566
569
expectedLeaderLeases : []* v1.Lease {
@@ -576,17 +579,65 @@ func TestController(t *testing.T) {
576
579
},
577
580
},
578
581
{
579
- name : "better candidate triggers reelection" ,
580
- leaseNN : types.NamespacedName {Namespace : "kube-system" , Name : "component-A" },
581
- createAfterControllerStart : []* v1alpha1.LeaseCandidate {
582
+ name : "expired lease is replaced" ,
583
+ leases : []* v1.Lease {
584
+ {
585
+ ObjectMeta : metav1.ObjectMeta {
586
+ Namespace : "kube-system" ,
587
+ Name : "component-A" ,
588
+ },
589
+ Spec : v1.LeaseSpec {
590
+ HolderIdentity : ptr .To ("some-other-component" ),
591
+ RenewTime : ptr .To (metav1 .NewMicroTime (fakeClock .Now ().Add (- 11 * time .Second ))),
592
+ LeaseDurationSeconds : ptr .To (int32 (10 )),
593
+ Strategy : ptr.To [v1.CoordinatedLeaseStrategy ]("OldestEmulationVersion" ),
594
+ },
595
+ },
596
+ },
597
+ candidates : []* v1alpha1.LeaseCandidate {
598
+ {
599
+ ObjectMeta : metav1.ObjectMeta {
600
+ Namespace : "kube-system" ,
601
+ Name : "component-identity-1" ,
602
+ },
603
+ Spec : v1alpha1.LeaseCandidateSpec {
604
+ LeaseName : "component-A" ,
605
+ EmulationVersion : "1.19.0" ,
606
+ BinaryVersion : "1.19.0" ,
607
+ RenewTime : ptr .To (metav1 .NewMicroTime (fakeClock .Now ())),
608
+ PreferredStrategies : []v1.CoordinatedLeaseStrategy {v1 .OldestEmulationVersion },
609
+ },
610
+ },
611
+ },
612
+ expectedLeaderLeases : []* v1.Lease {
613
+ {
614
+ ObjectMeta : metav1.ObjectMeta {
615
+ Namespace : "kube-system" ,
616
+ Name : "component-A" ,
617
+ },
618
+ Spec : v1.LeaseSpec {
619
+ HolderIdentity : ptr .To ("component-identity-1" ),
620
+ },
621
+ },
622
+ },
623
+ },
624
+ {
625
+ name : "better candidate triggers reelection" ,
626
+ leases : []* v1.Lease {
582
627
{
583
- // Leader lease
584
628
ObjectMeta : metav1.ObjectMeta {
585
629
Namespace : "kube-system" ,
586
630
Name : "component-A" ,
587
631
},
588
- Spec : v1alpha1.LeaseCandidateSpec {},
632
+ Spec : v1.LeaseSpec {
633
+ HolderIdentity : ptr .To ("component-identity-1" ),
634
+ Strategy : ptr.To [v1.CoordinatedLeaseStrategy ]("OldestEmulationVersion" ),
635
+ RenewTime : ptr .To (metav1 .NewMicroTime (fakeClock .Now ().Add (time .Second ))),
636
+ LeaseDurationSeconds : ptr .To (int32 (10 )),
637
+ },
589
638
},
639
+ },
640
+ candidates : []* v1alpha1.LeaseCandidate {
590
641
{
591
642
ObjectMeta : metav1.ObjectMeta {
592
643
Namespace : "kube-system" ,
@@ -600,6 +651,8 @@ func TestController(t *testing.T) {
600
651
PreferredStrategies : []v1.CoordinatedLeaseStrategy {v1 .OldestEmulationVersion },
601
652
},
602
653
},
654
+ },
655
+ createAfterControllerStart : []* v1alpha1.LeaseCandidate {
603
656
{
604
657
ObjectMeta : metav1.ObjectMeta {
605
658
Namespace : "kube-system" ,
@@ -645,9 +698,30 @@ func TestController(t *testing.T) {
645
698
t .Fatal (err )
646
699
}
647
700
701
+ for _ , obj := range tc .leases {
702
+ t .Logf ("Pre-creating lease %s/%s" , obj .Namespace , obj .Name )
703
+ _ , err := client .CoordinationV1 ().Leases (obj .Namespace ).Create (ctx , obj , metav1.CreateOptions {})
704
+ if err != nil {
705
+ t .Fatalf ("Error pre-creating lease %s/%s: %v" , obj .Namespace , obj .Name , err )
706
+ }
707
+ }
708
+ for _ , obj := range tc .candidates {
709
+ t .Logf ("Pre-creating lease candidate %s/%s" , obj .Namespace , obj .Name )
710
+ _ , err := client .CoordinationV1alpha1 ().LeaseCandidates (obj .Namespace ).Create (ctx , obj , metav1.CreateOptions {})
711
+ if err != nil {
712
+ t .Fatalf ("Error pre-creating lease candidate %s/%s: %v" , obj .Namespace , obj .Name , err )
713
+ }
714
+ }
715
+
648
716
informerFactory .Start (ctx .Done ())
717
+ informerFactory .WaitForCacheSync (ctx .Done ())
649
718
go controller .Run (ctx , 1 )
650
719
720
+ if rand .Intn (2 ) == 0 {
721
+ t .Logf ("Giving controller a chance to run" )
722
+ time .Sleep (time .Second )
723
+ }
724
+
651
725
go func () {
652
726
ticker := time .NewTicker (10 * time .Millisecond )
653
727
// Mock out the removal of preferredHolder leases.
@@ -658,14 +732,24 @@ func TestController(t *testing.T) {
658
732
return
659
733
case <- ticker .C :
660
734
for _ , expectedLease := range tc .expectedLeaderLeases {
661
- lease , err := client .CoordinationV1 ().Leases (expectedLease .Namespace ).Get (ctx , expectedLease .Name , metav1.GetOptions {})
662
- if err == nil {
663
- if preferredHolder := lease .Spec .PreferredHolder ; preferredHolder != nil {
664
- err = client .CoordinationV1 ().Leases (expectedLease .Namespace ).Delete (ctx , expectedLease .Name , metav1.DeleteOptions {})
665
- if err != nil {
666
- runtime .HandleError (err )
667
- }
668
- }
735
+ l , err := client .CoordinationV1 ().Leases (expectedLease .Namespace ).Get (ctx , expectedLease .Name , metav1.GetOptions {})
736
+ if err != nil {
737
+ continue
738
+ }
739
+ ph := l .Spec .PreferredHolder
740
+ if ph == nil || l .Spec .HolderIdentity == nil {
741
+ continue
742
+ }
743
+ if * ph == * l .Spec .HolderIdentity {
744
+ continue
745
+ }
746
+ if _ , err := client .CoordinationV1alpha1 ().LeaseCandidates (expectedLease .Namespace ).Get (ctx , * l .Spec .HolderIdentity , metav1.GetOptions {}); err != nil {
747
+ continue // only candidate-aware controllers will follow preferredHolder
748
+ }
749
+
750
+ t .Logf ("Deleting lease %s/%s because of preferredHolder %q != %q" , l .Namespace , l .Name , * ph , * l .Spec .HolderIdentity )
751
+ if err = client .CoordinationV1 ().Leases (expectedLease .Namespace ).Delete (ctx , expectedLease .Name , metav1.DeleteOptions {}); err != nil {
752
+ t .Logf ("Error deleting lease %s/%s: %v" , l .Namespace , l .Name , err )
669
753
}
670
754
}
671
755
}
@@ -682,16 +766,15 @@ func TestController(t *testing.T) {
682
766
return
683
767
case <- ticker .C :
684
768
for _ , lc := range tc .createAfterControllerStart {
685
- lease , err := client .CoordinationV1alpha1 ().LeaseCandidates (lc .Namespace ).Get (ctx , lc .Name , metav1.GetOptions {})
769
+ c , err := client .CoordinationV1alpha1 ().LeaseCandidates (lc .Namespace ).Get (ctx , lc .Name , metav1.GetOptions {})
686
770
if err == nil {
687
- if lease .Spec .PingTime != nil {
688
- c := lease . DeepCopy ( )
771
+ if c .Spec .PingTime != nil {
772
+ t . Logf ( "Answering ping for %s/%s" , c . Namespace , c . Name )
689
773
c .Spec .RenewTime = & metav1.MicroTime {Time : fakeClock .Now ()}
690
774
_ , err = client .CoordinationV1alpha1 ().LeaseCandidates (lc .Namespace ).Update (ctx , c , metav1.UpdateOptions {})
691
775
if err != nil {
692
- runtime . HandleError ( err )
776
+ t . Logf ( "Error updating lease candidate %s/%s: %v" , c . Namespace , c . Name , err )
693
777
}
694
-
695
778
}
696
779
}
697
780
}
@@ -700,45 +783,48 @@ func TestController(t *testing.T) {
700
783
}()
701
784
702
785
for _ , obj := range tc .createAfterControllerStart {
786
+ t .Logf ("Post-creating lease candidate %s/%s" , obj .Namespace , obj .Name )
703
787
_ , err := client .CoordinationV1alpha1 ().LeaseCandidates (obj .Namespace ).Create (ctx , obj , metav1.CreateOptions {})
704
788
if err != nil {
705
- t .Fatal ( err )
789
+ t .Fatalf ( "Error post-creating lease candidate %s/%s: %v" , obj . Namespace , obj . Name , err )
706
790
}
707
791
}
708
792
709
- for _ , obj := range tc .deleteAfterControllerStart {
710
- err := client .CoordinationV1alpha1 ().LeaseCandidates (obj .Namespace ).Delete (ctx , obj .Name , metav1.DeleteOptions {})
793
+ for _ , obj := range tc .deleteLeaseAfterControllerStart {
794
+ t .Logf ("Post-deleting lease %s/%s" , obj .Namespace , obj .Name )
795
+ err := client .CoordinationV1 ().Leases (obj .Namespace ).Delete (ctx , obj .Name , metav1.DeleteOptions {})
711
796
if err != nil {
712
- t .Fatal ( err )
797
+ t .Fatalf ( "Error post-deleting lease %s/%s: %v" , obj . Namespace , obj . Name , err )
713
798
}
714
799
}
715
800
716
801
for _ , expectedLease := range tc .expectedLeaderLeases {
717
802
var lease * v1.Lease
718
- err = wait .PollUntilContextTimeout (ctx , 100 * time .Millisecond , 600 * time .Second , true , func (ctx context.Context ) (done bool , err error ) {
803
+ t .Logf ("Waiting for lease %s/%s with holder %q" , expectedLease .Namespace , expectedLease .Name , strOrNil (expectedLease .Spec .HolderIdentity ))
804
+ err = wait .PollUntilContextTimeout (ctx , 100 * time .Millisecond , wait .ForeverTestTimeout , true , func (ctx context.Context ) (done bool , err error ) {
719
805
lease , err = client .CoordinationV1 ().Leases (expectedLease .Namespace ).Get (ctx , expectedLease .Name , metav1.GetOptions {})
720
806
if err != nil {
721
807
if errors .IsNotFound (err ) {
722
808
return false , nil
723
809
}
724
810
return true , err
725
811
}
726
- if expectedLease .Spec .HolderIdentity == nil || lease .Spec .HolderIdentity == nil {
727
- return expectedLease .Spec .HolderIdentity == nil && lease .Spec .HolderIdentity == nil , nil
812
+ if expectedLease .Spec .HolderIdentity == nil {
813
+ return lease .Spec .HolderIdentity == nil , nil
814
+ }
815
+ if lease .Spec .HolderIdentity == nil {
816
+ return false , nil
728
817
}
729
- if expectedLease . Spec . HolderIdentity != nil && lease . Spec . HolderIdentity != nil && * expectedLease .Spec .HolderIdentity != * lease .Spec .HolderIdentity {
818
+ if * expectedLease .Spec .HolderIdentity != * lease .Spec .HolderIdentity {
730
819
return false , nil
731
820
}
732
821
return true , nil
733
822
})
734
823
if err != nil {
735
- t .Fatal (err )
736
- }
737
- if lease .Spec .HolderIdentity == nil {
738
- t .Fatalf ("Expected HolderIdentity of %s but got nil" , expectedLease .Name )
739
- }
740
- if * lease .Spec .HolderIdentity != * expectedLease .Spec .HolderIdentity {
741
- t .Errorf ("Expected HolderIdentity of %s but got %s" , * expectedLease .Spec .HolderIdentity , * lease .Spec .HolderIdentity )
824
+ if lease == nil {
825
+ t .Fatalf ("Error waiting for lease %s/%s to exist: %v" , expectedLease .Namespace , expectedLease .Name , err )
826
+ }
827
+ t .Fatalf ("Error waiting for lease %s/%s with holder %q, but got %q: %v" , expectedLease .Namespace , expectedLease .Name , strOrNil (expectedLease .Spec .HolderIdentity ), strOrNil (lease .Spec .HolderIdentity ), err )
742
828
}
743
829
}
744
830
})
0 commit comments