@@ -17,6 +17,7 @@ limitations under the License.
17
17
package controllers
18
18
19
19
import (
20
+ "bytes"
20
21
"context"
21
22
"fmt"
22
23
"reflect"
@@ -30,6 +31,7 @@ import (
30
31
"k8s.io/apimachinery/pkg/types"
31
32
fakeclient "k8s.io/client-go/kubernetes/fake"
32
33
typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
34
+ bootstrapapi "k8s.io/cluster-bootstrap/token/api"
33
35
"k8s.io/klog/klogr"
34
36
bootstrapv1 "sigs.k8s.io/cluster-api-bootstrap-provider-kubeadm/api/v1alpha2"
35
37
internalcluster "sigs.k8s.io/cluster-api-bootstrap-provider-kubeadm/internal/cluster"
@@ -577,7 +579,7 @@ func TestReconcileIfJoinNodesAndControlPlaneIsReady(t *testing.T) {
577
579
myremoteclient , _ := k .SecretsClientFactory .NewSecretsClient (nil , nil )
578
580
l , err := myremoteclient .List (metav1.ListOptions {})
579
581
if err != nil {
580
- t .Fatal (fmt .Sprintf ("Failed to get secrets after reconcyle :\n %+v" , err ))
582
+ t .Fatal (fmt .Sprintf ("Failed to get secrets after reconcile :\n %+v" , err ))
581
583
}
582
584
583
585
if len (l .Items ) != 1 {
@@ -588,6 +590,204 @@ func TestReconcileIfJoinNodesAndControlPlaneIsReady(t *testing.T) {
588
590
}
589
591
}
590
592
593
+ func TestBootstrapTokenTTLExtension (t * testing.T ) {
594
+ cluster := newCluster ("cluster" )
595
+ cluster .Status .InfrastructureReady = true
596
+ cluster .Status .ControlPlaneInitialized = true
597
+ cluster .Status .APIEndpoints = []clusterv1.APIEndpoint {{Host : "100.105.150.1" , Port : 6443 }}
598
+
599
+ controlPlaneInitMachine := newControlPlaneMachine (cluster , "control-plane-init-machine" )
600
+ initConfig := newControlPlaneInitKubeadmConfig (controlPlaneInitMachine , "control-plane-init-config" )
601
+ workerMachine := newWorkerMachine (cluster )
602
+ workerJoinConfig := newWorkerJoinKubeadmConfig (workerMachine )
603
+ controlPlaneJoinMachine := newControlPlaneMachine (cluster , "control-plane-join-machine" )
604
+ controlPlaneJoinConfig := newControlPlaneJoinKubeadmConfig (controlPlaneJoinMachine , "control-plane-join-cfg" )
605
+ objects := []runtime.Object {
606
+ cluster ,
607
+ workerMachine ,
608
+ workerJoinConfig ,
609
+ controlPlaneJoinMachine ,
610
+ controlPlaneJoinConfig ,
611
+ }
612
+
613
+ objects = append (objects , createSecrets (t , cluster , initConfig )... )
614
+ myclient := fake .NewFakeClientWithScheme (setupScheme (), objects ... )
615
+ k := & KubeadmConfigReconciler {
616
+ Log : log .Log ,
617
+ Client : myclient ,
618
+ SecretsClientFactory : newFakeSecretFactory (),
619
+ KubeadmInitLock : & myInitLocker {},
620
+ }
621
+ request := ctrl.Request {
622
+ NamespacedName : types.NamespacedName {
623
+ Namespace : "default" ,
624
+ Name : "worker-join-cfg" ,
625
+ },
626
+ }
627
+ result , err := k .Reconcile (request )
628
+ if err != nil {
629
+ t .Fatalf ("Failed to reconcile:\n %+v" , err )
630
+ }
631
+ if result .Requeue == true {
632
+ t .Fatal ("did not expect to requeue" )
633
+ }
634
+ if result .RequeueAfter != time .Duration (0 ) {
635
+ t .Fatal ("did not expect to requeue after" )
636
+ }
637
+ cfg , err := getKubeadmConfig (myclient , "worker-join-cfg" )
638
+ if err != nil {
639
+ t .Fatalf ("Failed to reconcile:\n %+v" , err )
640
+ }
641
+ if cfg .Status .Ready != true {
642
+ t .Fatal ("Expected status ready" )
643
+ }
644
+ if cfg .Status .BootstrapData == nil {
645
+ t .Fatal ("Expected status ready" )
646
+ }
647
+ request = ctrl.Request {
648
+ NamespacedName : types.NamespacedName {
649
+ Namespace : "default" ,
650
+ Name : "control-plane-join-cfg" ,
651
+ },
652
+ }
653
+ result , err = k .Reconcile (request )
654
+ if err != nil {
655
+ t .Fatalf ("Failed to reconcile:\n %+v" , err )
656
+ }
657
+ if result .Requeue == true {
658
+ t .Fatal ("did not expect to requeue" )
659
+ }
660
+ if result .RequeueAfter != time .Duration (0 ) {
661
+ t .Fatal ("did not expect to requeue after" )
662
+ }
663
+ cfg , err = getKubeadmConfig (myclient , "control-plane-join-cfg" )
664
+ if err != nil {
665
+ t .Fatalf ("Failed to reconcile:\n %+v" , err )
666
+ }
667
+ if cfg .Status .Ready != true {
668
+ t .Fatal ("Expected status ready" )
669
+ }
670
+ if cfg .Status .BootstrapData == nil {
671
+ t .Fatal ("Expected status ready" )
672
+ }
673
+
674
+ myremoteclient , _ := k .SecretsClientFactory .NewSecretsClient (nil , nil )
675
+ l , err := myremoteclient .List (metav1.ListOptions {})
676
+ if err != nil {
677
+ t .Fatalf ("Failed to read secrets:\n %+v" , err )
678
+ }
679
+
680
+ if len (l .Items ) != 2 {
681
+ t .Fatalf ("Expected two bootstrap tokens, saw:\n %+d" , len (l .Items ))
682
+ }
683
+
684
+ // ensure that the token is refreshed...
685
+ tokenExpires := make ([][]byte , len (l .Items ))
686
+
687
+ for i , item := range l .Items {
688
+ tokenExpires [i ] = item .Data [bootstrapapi .BootstrapTokenExpirationKey ]
689
+ }
690
+
691
+ <- time .After (1 * time .Second )
692
+
693
+ for _ , req := range []ctrl.Request {
694
+ {
695
+ NamespacedName : types.NamespacedName {
696
+ Namespace : "default" ,
697
+ Name : "worker-join-cfg" ,
698
+ },
699
+ },
700
+ {
701
+ NamespacedName : types.NamespacedName {
702
+ Namespace : "default" ,
703
+ Name : "control-plane-join-cfg" ,
704
+ },
705
+ },
706
+ } {
707
+
708
+ result , err := k .Reconcile (req )
709
+ if err != nil {
710
+ t .Fatalf ("Failed to reconcile:\n %+v" , err )
711
+ }
712
+ if result .RequeueAfter >= DefaultTokenTTL {
713
+ t .Fatal ("expected a requeue duration less than the token TTL" )
714
+ }
715
+ }
716
+
717
+ l , err = myremoteclient .List (metav1.ListOptions {})
718
+ if err != nil {
719
+ t .Fatalf ("Failed to read secrets:\n %+v" , err )
720
+ }
721
+
722
+ if len (l .Items ) != 2 {
723
+ t .Fatalf ("Expected two bootstrap tokens, saw:\n %+d" , len (l .Items ))
724
+ }
725
+
726
+ for i , item := range l .Items {
727
+ if bytes .Equal (tokenExpires [i ], item .Data [bootstrapapi .BootstrapTokenExpirationKey ]) {
728
+ t .Fatal ("Reconcile should have refreshed bootstrap token's expiration until the infrastructure was ready" )
729
+ }
730
+ tokenExpires [i ] = item .Data [bootstrapapi .BootstrapTokenExpirationKey ]
731
+ }
732
+
733
+ // ...until the infrastructure is marked "ready"
734
+ workerMachine .Status .InfrastructureReady = true
735
+ err = myclient .Update (context .Background (), workerMachine )
736
+ if err != nil {
737
+ t .Fatalf ("unable to set machine infrastructure ready: %v" , err )
738
+ }
739
+
740
+ controlPlaneJoinMachine .Status .InfrastructureReady = true
741
+ err = myclient .Update (context .Background (), controlPlaneJoinMachine )
742
+ if err != nil {
743
+ t .Fatalf ("unable to set machine infrastructure ready: %v" , err )
744
+ }
745
+
746
+ <- time .After (1 * time .Second )
747
+
748
+ for _ , req := range []ctrl.Request {
749
+ {
750
+ NamespacedName : types.NamespacedName {
751
+ Namespace : "default" ,
752
+ Name : "worker-join-cfg" ,
753
+ },
754
+ },
755
+ {
756
+ NamespacedName : types.NamespacedName {
757
+ Namespace : "default" ,
758
+ Name : "control-plane-join-cfg" ,
759
+ },
760
+ },
761
+ } {
762
+
763
+ result , err := k .Reconcile (req )
764
+ if err != nil {
765
+ t .Fatalf ("Failed to reconcile:\n %+v" , err )
766
+ }
767
+ if result .Requeue == true {
768
+ t .Fatal ("did not expect to requeue" )
769
+ }
770
+ if result .RequeueAfter != time .Duration (0 ) {
771
+ t .Fatal ("did not expect to requeue after" )
772
+ }
773
+ }
774
+
775
+ l , err = myremoteclient .List (metav1.ListOptions {})
776
+ if err != nil {
777
+ t .Fatalf ("Failed to read secrets:\n %+v" , err )
778
+ }
779
+
780
+ if len (l .Items ) != 2 {
781
+ t .Fatalf ("Expected two bootstrap tokens, saw:\n %+d" , len (l .Items ))
782
+ }
783
+
784
+ for i , item := range l .Items {
785
+ if ! bytes .Equal (tokenExpires [i ], item .Data [bootstrapapi .BootstrapTokenExpirationKey ]) {
786
+ t .Fatal ("Reconcile should have let the bootstrap token expire after the infrastructure was ready" )
787
+ }
788
+ }
789
+ }
790
+
591
791
// Ensure the discovery portion of the JoinConfiguration gets generated correctly.
592
792
func TestKubeadmConfigReconciler_Reconcile_DisocveryReconcileBehaviors (t * testing.T ) {
593
793
k := & KubeadmConfigReconciler {
0 commit comments