@@ -1441,6 +1441,155 @@ func TestBootstrapTokenRotationMachinePool(t *testing.T) {
14411441 g .Expect (foundNew ).To (BeTrue ())
14421442}
14431443
1444+ func TestBootstrapTokenRefreshIfTokenSecretCleaned (t * testing.T ) {
1445+ t .Run ("should not recreate the token for Machines" , func (t * testing.T ) {
1446+ g := NewWithT (t )
1447+
1448+ cluster := builder .Cluster (metav1 .NamespaceDefault , "cluster" ).Build ()
1449+ cluster .Status .InfrastructureReady = true
1450+ conditions .MarkTrue (cluster , clusterv1 .ControlPlaneInitializedCondition )
1451+ cluster .Spec .ControlPlaneEndpoint = clusterv1.APIEndpoint {Host : "100.105.150.1" , Port : 6443 }
1452+
1453+ controlPlaneInitMachine := newControlPlaneMachine (cluster , "control-plane-init-machine" )
1454+ initConfig := newControlPlaneInitKubeadmConfig (controlPlaneInitMachine .Namespace , "control-plane-init-config" )
1455+
1456+ addKubeadmConfigToMachine (initConfig , controlPlaneInitMachine )
1457+
1458+ workerMachine := newWorkerMachineForCluster (cluster )
1459+ workerJoinConfig := newWorkerJoinKubeadmConfig (metav1 .NamespaceDefault , "worker-join-cfg" )
1460+ addKubeadmConfigToMachine (workerJoinConfig , workerMachine )
1461+ objects := []client.Object {
1462+ cluster ,
1463+ workerMachine ,
1464+ workerJoinConfig ,
1465+ }
1466+
1467+ objects = append (objects , createSecrets (t , cluster , initConfig )... )
1468+ myclient := fake .NewClientBuilder ().WithObjects (objects ... ).WithStatusSubresource (& bootstrapv1.KubeadmConfig {}).Build ()
1469+ remoteClient := fake .NewClientBuilder ().Build ()
1470+ k := & KubeadmConfigReconciler {
1471+ Client : myclient ,
1472+ SecretCachingClient : myclient ,
1473+ KubeadmInitLock : & myInitLocker {},
1474+ TokenTTL : DefaultTokenTTL ,
1475+ ClusterCache : clustercache .NewFakeClusterCache (remoteClient , client.ObjectKey {Name : cluster .Name , Namespace : cluster .Namespace }),
1476+ }
1477+ request := ctrl.Request {
1478+ NamespacedName : client.ObjectKey {
1479+ Namespace : metav1 .NamespaceDefault ,
1480+ Name : "worker-join-cfg" ,
1481+ },
1482+ }
1483+ result , err := k .Reconcile (ctx , request )
1484+ g .Expect (err ).ToNot (HaveOccurred ())
1485+ g .Expect (result .RequeueAfter ).To (Equal (k .TokenTTL / 3 ))
1486+
1487+ cfg , err := getKubeadmConfig (myclient , "worker-join-cfg" , metav1 .NamespaceDefault )
1488+ g .Expect (err ).ToNot (HaveOccurred ())
1489+ g .Expect (cfg .Status .Ready ).To (BeTrue ())
1490+ g .Expect (cfg .Status .DataSecretName ).NotTo (BeNil ())
1491+ g .Expect (cfg .Status .ObservedGeneration ).NotTo (BeNil ())
1492+ g .Expect (cfg .Spec .JoinConfiguration .Discovery .BootstrapToken .Token ).ToNot (BeEmpty ())
1493+ firstToken := cfg .Spec .JoinConfiguration .Discovery .BootstrapToken .Token
1494+
1495+ l := & corev1.SecretList {}
1496+ g .Expect (remoteClient .List (ctx , l , client .ListOption (client .InNamespace (metav1 .NamespaceSystem )))).To (Succeed ())
1497+ g .Expect (l .Items ).To (HaveLen (1 ))
1498+
1499+ t .Log ("Token should not get recreated for single Machine since it will not use the new token if spec.bootstrap.dataSecretName was already set" )
1500+
1501+ // Simulate token cleaner of Kubernetes having deleted the token secret
1502+ err = remoteClient .Delete (ctx , & l .Items [0 ])
1503+ g .Expect (err ).ToNot (HaveOccurred ())
1504+
1505+ result , err = k .Reconcile (ctx , request )
1506+ g .Expect (err ).To (HaveOccurred ())
1507+ g .Expect (err .Error ()).To (ContainSubstring ("failed to get bootstrap token secret in order to refresh it" ))
1508+ // New token should not have been created
1509+ cfg , err = getKubeadmConfig (myclient , "worker-join-cfg" , metav1 .NamespaceDefault )
1510+ g .Expect (err ).ToNot (HaveOccurred ())
1511+ g .Expect (cfg .Spec .JoinConfiguration .Discovery .BootstrapToken .Token ).To (Equal (firstToken ))
1512+
1513+ l = & corev1.SecretList {}
1514+ g .Expect (remoteClient .List (ctx , l , client .ListOption (client .InNamespace (metav1 .NamespaceSystem )))).To (Succeed ())
1515+ g .Expect (l .Items ).To (BeEmpty ())
1516+ })
1517+ t .Run ("should recreate the token for MachinePools" , func (t * testing.T ) {
1518+ _ = feature .MutableGates .Set ("MachinePool=true" )
1519+ g := NewWithT (t )
1520+
1521+ cluster := builder .Cluster (metav1 .NamespaceDefault , "cluster" ).Build ()
1522+ cluster .Status .InfrastructureReady = true
1523+ conditions .MarkTrue (cluster , clusterv1 .ControlPlaneInitializedCondition )
1524+ cluster .Spec .ControlPlaneEndpoint = clusterv1.APIEndpoint {Host : "100.105.150.1" , Port : 6443 }
1525+
1526+ controlPlaneInitMachine := newControlPlaneMachine (cluster , "control-plane-init-machine" )
1527+ initConfig := newControlPlaneInitKubeadmConfig (controlPlaneInitMachine .Namespace , "control-plane-init-config" )
1528+
1529+ addKubeadmConfigToMachine (initConfig , controlPlaneInitMachine )
1530+
1531+ workerMachinePool := newWorkerMachinePoolForCluster (cluster )
1532+ workerJoinConfig := newWorkerJoinKubeadmConfig (workerMachinePool .Namespace , "workerpool-join-cfg" )
1533+ addKubeadmConfigToMachinePool (workerJoinConfig , workerMachinePool )
1534+ objects := []client.Object {
1535+ cluster ,
1536+ workerMachinePool ,
1537+ workerJoinConfig ,
1538+ }
1539+
1540+ objects = append (objects , createSecrets (t , cluster , initConfig )... )
1541+ myclient := fake .NewClientBuilder ().WithObjects (objects ... ).WithStatusSubresource (& bootstrapv1.KubeadmConfig {}, & expv1.MachinePool {}).Build ()
1542+ remoteClient := fake .NewClientBuilder ().Build ()
1543+ k := & KubeadmConfigReconciler {
1544+ Client : myclient ,
1545+ SecretCachingClient : myclient ,
1546+ KubeadmInitLock : & myInitLocker {},
1547+ TokenTTL : DefaultTokenTTL ,
1548+ ClusterCache : clustercache .NewFakeClusterCache (remoteClient , client.ObjectKey {Name : cluster .Name , Namespace : cluster .Namespace }),
1549+ }
1550+ request := ctrl.Request {
1551+ NamespacedName : client.ObjectKey {
1552+ Namespace : metav1 .NamespaceDefault ,
1553+ Name : "workerpool-join-cfg" ,
1554+ },
1555+ }
1556+ result , err := k .Reconcile (ctx , request )
1557+ g .Expect (err ).ToNot (HaveOccurred ())
1558+ g .Expect (result .RequeueAfter ).To (Equal (k .TokenTTL / 3 ))
1559+
1560+ cfg , err := getKubeadmConfig (myclient , "workerpool-join-cfg" , metav1 .NamespaceDefault )
1561+ g .Expect (err ).ToNot (HaveOccurred ())
1562+ g .Expect (cfg .Status .Ready ).To (BeTrue ())
1563+ g .Expect (cfg .Status .DataSecretName ).NotTo (BeNil ())
1564+ g .Expect (cfg .Status .ObservedGeneration ).NotTo (BeNil ())
1565+ g .Expect (cfg .Spec .JoinConfiguration .Discovery .BootstrapToken .Token ).ToNot (BeEmpty ())
1566+ firstToken := cfg .Spec .JoinConfiguration .Discovery .BootstrapToken .Token
1567+
1568+ l := & corev1.SecretList {}
1569+ g .Expect (remoteClient .List (ctx , l , client .ListOption (client .InNamespace (metav1 .NamespaceSystem )))).To (Succeed ())
1570+ g .Expect (l .Items ).To (HaveLen (1 ))
1571+
1572+ t .Log ("Ensure that the token gets recreated if it was cleaned up by Kubernetes (e.g. on expiry)" )
1573+
1574+ // Simulate token cleaner of Kubernetes having deleted the token secret
1575+ err = remoteClient .Delete (ctx , & l .Items [0 ])
1576+ g .Expect (err ).ToNot (HaveOccurred ())
1577+
1578+ result , err = k .Reconcile (ctx , request )
1579+ g .Expect (err ).ToNot (HaveOccurred ())
1580+ g .Expect (result .RequeueAfter ).To (Equal (k .TokenTTL / 3 ))
1581+ // New token should have been created
1582+ cfg , err = getKubeadmConfig (myclient , "workerpool-join-cfg" , metav1 .NamespaceDefault )
1583+ g .Expect (err ).ToNot (HaveOccurred ())
1584+ g .Expect (cfg .Spec .JoinConfiguration .Discovery .BootstrapToken .Token ).ToNot (BeEmpty ())
1585+ g .Expect (cfg .Spec .JoinConfiguration .Discovery .BootstrapToken .Token ).ToNot (Equal (firstToken ))
1586+
1587+ l = & corev1.SecretList {}
1588+ g .Expect (remoteClient .List (ctx , l , client .ListOption (client .InNamespace (metav1 .NamespaceSystem )))).To (Succeed ())
1589+ g .Expect (l .Items ).To (HaveLen (1 ))
1590+ })
1591+ }
1592+
14441593// Ensure the discovery portion of the JoinConfiguration gets generated correctly.
14451594func TestKubeadmConfigReconciler_Reconcile_DiscoveryReconcileBehaviors (t * testing.T ) {
14461595 caHash := []string {"...." }
0 commit comments