@@ -24,13 +24,16 @@ import (
24
24
. "github.com/onsi/gomega"
25
25
corev1 "k8s.io/api/core/v1"
26
26
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
27
28
"k8s.io/utils/ptr"
29
+ "sigs.k8s.io/controller-runtime/pkg/client"
28
30
29
31
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
30
32
controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta1"
31
33
"sigs.k8s.io/cluster-api/controlplane/kubeadm/internal/etcd"
32
34
"sigs.k8s.io/cluster-api/util/collections"
33
35
"sigs.k8s.io/cluster-api/util/conditions"
36
+ "sigs.k8s.io/cluster-api/util/patch"
34
37
)
35
38
36
39
func TestControlPlane (t * testing.T ) {
@@ -64,6 +67,12 @@ func TestControlPlane(t *testing.T) {
64
67
controlPlane .Machines .Insert (machine ("machine-5" , withFailureDomain ("unknown" )))
65
68
g .Expect (* controlPlane .FailureDomainWithMostMachines (ctx , controlPlane .Machines )).To (Equal ("unknown" ))
66
69
})
70
+
71
+ t .Run ("With failure Domains is set empty" , func (* testing.T ) {
72
+ g := NewWithT (t )
73
+ controlPlane .Cluster .Status .FailureDomains = nil
74
+ g .Expect (* controlPlane .FailureDomainWithMostMachines (ctx , controlPlane .Machines )).To (Equal ("one" ))
75
+ })
67
76
})
68
77
69
78
t .Run ("MachinesUpToDate" , func (t * testing.T ) {
@@ -144,6 +153,173 @@ func TestControlPlane(t *testing.T) {
144
153
g .Expect (err ).NotTo (HaveOccurred ())
145
154
g .Expect (fd ).To (Equal (ptr .To ("two" ))) // deleted up-to-date machines (m4) should not be counted when picking the next failure domain for scale up
146
155
})
156
+
157
+ t .Run ("Next Failure Domains" , func (t * testing.T ) {
158
+ g := NewWithT (t )
159
+ cluster := clusterv1.Cluster {
160
+ Status : clusterv1.ClusterStatus {
161
+ FailureDomains : clusterv1.FailureDomains {
162
+ "one" : failureDomain (false ),
163
+ },
164
+ },
165
+ }
166
+ kcp := & controlplanev1.KubeadmControlPlane {
167
+ Spec : controlplanev1.KubeadmControlPlaneSpec {
168
+ Version : "v1.31.0" ,
169
+ },
170
+ }
171
+ machines := collections.Machines {
172
+ "machine-1" : & clusterv1.Machine {
173
+ ObjectMeta : metav1.ObjectMeta {Name : "m1" , DeletionTimestamp : ptr .To (metav1 .Now ())},
174
+ Spec : clusterv1.MachineSpec {
175
+ Version : ptr .To ("v1.31.0" ), // deleted
176
+ FailureDomain : ptr .To ("one" ),
177
+ InfrastructureRef : corev1.ObjectReference {Kind : "GenericInfrastructureMachine" , APIVersion : "infrastructure.cluster.x-k8s.io/v1beta1" , Name : "m1" },
178
+ }},
179
+ }
180
+ controlPlane , err := NewControlPlane (ctx , nil , env .GetClient (), & cluster , kcp , machines )
181
+ g .Expect (err ).NotTo (HaveOccurred ())
182
+ fd , err := controlPlane .NextFailureDomainForScaleUp (ctx )
183
+ g .Expect (err ).NotTo (HaveOccurred ())
184
+ g .Expect (fd ).To (BeNil ())
185
+ })
186
+
187
+ t .Run ("ControlPlane returns infra error" , func (t * testing.T ) {
188
+ g := NewWithT (t )
189
+ cluster := clusterv1.Cluster {
190
+ Status : clusterv1.ClusterStatus {
191
+ FailureDomains : clusterv1.FailureDomains {
192
+ "one" : failureDomain (true ),
193
+ "two" : failureDomain (true ),
194
+ "three" : failureDomain (true ),
195
+ },
196
+ },
197
+ }
198
+ kcp := & controlplanev1.KubeadmControlPlane {
199
+ Spec : controlplanev1.KubeadmControlPlaneSpec {
200
+ Version : "v1.31.0" ,
201
+ },
202
+ }
203
+ machines := collections.Machines {
204
+ "machine-1" : & clusterv1.Machine {
205
+ ObjectMeta : metav1.ObjectMeta {Name : "m1" },
206
+ Spec : clusterv1.MachineSpec {
207
+ Version : ptr .To ("v1.31.0" ),
208
+ FailureDomain : ptr .To ("one" ),
209
+ InfrastructureRef : corev1.ObjectReference {Name : "m1" },
210
+ }},
211
+ }
212
+ _ , err := NewControlPlane (ctx , nil , env .GetClient (), & cluster , kcp , machines )
213
+ g .Expect (err ).To (HaveOccurred ())
214
+ })
215
+
216
+ t .Run ("When infra and bootstrap config is exists" , func (t * testing.T ) {
217
+ g := NewWithT (t )
218
+ ns , err := env .CreateNamespace (ctx , "test-machine-watches" )
219
+ kcp := & controlplanev1.KubeadmControlPlane {
220
+ Spec : controlplanev1.KubeadmControlPlaneSpec {
221
+ Version : "v1.31.0" ,
222
+ },
223
+ }
224
+
225
+ g .Expect (err ).ToNot (HaveOccurred ())
226
+
227
+ infraMachine := & unstructured.Unstructured {
228
+ Object : map [string ]interface {}{
229
+ "kind" : "GenericInfrastructureMachine" ,
230
+ "apiVersion" : "infrastructure.cluster.x-k8s.io/v1beta1" ,
231
+ "metadata" : map [string ]interface {}{
232
+ "name" : "infra-config1" ,
233
+ "namespace" : ns .Name ,
234
+ },
235
+ "spec" : map [string ]interface {}{
236
+ "providerID" : "test://id-1" ,
237
+ },
238
+ "status" : map [string ]interface {}{
239
+ "ready" : true ,
240
+ "addresses" : []interface {}{
241
+ map [string ]interface {}{
242
+ "type" : "InternalIP" ,
243
+ "address" : "10.0.0.1" ,
244
+ },
245
+ },
246
+ },
247
+ },
248
+ }
249
+
250
+ bootstrap := & unstructured.Unstructured {
251
+ Object : map [string ]interface {}{
252
+ "kind" : "KubeadmConfig" ,
253
+ "apiVersion" : "bootstrap.cluster.x-k8s.io/v1beta1" ,
254
+ "metadata" : map [string ]interface {}{
255
+ "name" : "bootstrap-config-machinereconcile" ,
256
+ "namespace" : ns .Name ,
257
+ },
258
+ "spec" : map [string ]interface {}{
259
+ "providerID" : "test://id-1" ,
260
+ },
261
+ "status" : map [string ]interface {}{
262
+ "ready" : true ,
263
+ },
264
+ },
265
+ }
266
+
267
+ testCluster := & clusterv1.Cluster {
268
+ ObjectMeta : metav1.ObjectMeta {Name : "test-cluster" , Namespace : ns .Name },
269
+ Status : clusterv1.ClusterStatus {
270
+ FailureDomains : clusterv1.FailureDomains {
271
+ "one" : failureDomain (true ),
272
+ "two" : failureDomain (true ),
273
+ "three" : failureDomain (true ),
274
+ },
275
+ },
276
+ }
277
+
278
+ g .Expect (env .Create (ctx , infraMachine )).To (Succeed ())
279
+ g .Expect (env .Create (ctx , bootstrap )).To (Succeed ())
280
+
281
+ defer func (do ... client.Object ) {
282
+ g .Expect (env .Cleanup (ctx , do ... )).To (Succeed ())
283
+ }(ns , bootstrap , infraMachine )
284
+
285
+ // Patch infra machine ready
286
+ patchHelper , err := patch .NewHelper (infraMachine , env )
287
+ g .Expect (err ).ShouldNot (HaveOccurred ())
288
+ g .Expect (unstructured .SetNestedField (infraMachine .Object , true , "status" , "ready" )).To (Succeed ())
289
+ g .Expect (patchHelper .Patch (ctx , infraMachine , patch.WithStatusObservedGeneration {})).To (Succeed ())
290
+
291
+ // Patch bootstrap ready
292
+ patchHelper , err = patch .NewHelper (bootstrap , env )
293
+ g .Expect (err ).ShouldNot (HaveOccurred ())
294
+ g .Expect (unstructured .SetNestedField (bootstrap .Object , true , "status" , "ready" )).To (Succeed ())
295
+ g .Expect (patchHelper .Patch (ctx , bootstrap , patch.WithStatusObservedGeneration {})).To (Succeed ())
296
+
297
+ machines := collections.Machines {
298
+ "machine-1" : & clusterv1.Machine {
299
+ ObjectMeta : metav1.ObjectMeta {Name : "m1" ,
300
+ Namespace : ns .Name },
301
+ Spec : clusterv1.MachineSpec {
302
+ InfrastructureRef : corev1.ObjectReference {
303
+ APIVersion : "infrastructure.cluster.x-k8s.io/v1beta1" ,
304
+ Kind : "GenericInfrastructureMachine" ,
305
+ Name : "infra-config1" ,
306
+ Namespace : ns .Name ,
307
+ },
308
+ Bootstrap : clusterv1.Bootstrap {
309
+ ConfigRef : & corev1.ObjectReference {
310
+ APIVersion : "bootstrap.cluster.x-k8s.io/v1beta1" ,
311
+ Kind : "KubeadmConfig" ,
312
+ Name : "bootstrap-config-machinereconcile" ,
313
+ Namespace : ns .Name ,
314
+ },
315
+ },
316
+ },
317
+ },
318
+ }
319
+
320
+ _ , err = NewControlPlane (ctx , nil , env .GetClient (), testCluster , kcp , machines )
321
+ g .Expect (err ).NotTo (HaveOccurred ())
322
+ })
147
323
}
148
324
149
325
func TestHasMachinesToBeRemediated (t * testing.T ) {
@@ -324,6 +500,94 @@ func TestStatusToLogKeyAndValues(t *testing.T) {
324
500
g .Expect (got [3 ]).To (Equal ("m1, m2, m3" ))
325
501
}
326
502
503
+ func TestMachineInFailureDomainWithMostMachines (t * testing.T ) {
504
+ t .Run ("Machines in Failure Domain" , func (t * testing.T ) {
505
+ machines := collections.Machines {
506
+ "machine-3" : & clusterv1.Machine {
507
+ ObjectMeta : metav1.ObjectMeta {Name : "m3" },
508
+ Spec : clusterv1.MachineSpec {
509
+ Version : ptr .To ("v1.31.0" ),
510
+ FailureDomain : ptr .To ("three" ),
511
+ InfrastructureRef : corev1.ObjectReference {Kind : "GenericInfrastructureMachine" , APIVersion : "infrastructure.cluster.x-k8s.io/v1beta1" , Name : "m3" },
512
+ }},
513
+ }
514
+
515
+ c := & ControlPlane {
516
+ KCP : & controlplanev1.KubeadmControlPlane {},
517
+ Cluster : & clusterv1.Cluster {
518
+ Status : clusterv1.ClusterStatus {
519
+ FailureDomains : clusterv1.FailureDomains {
520
+ "three" : failureDomain (false ),
521
+ },
522
+ },
523
+ },
524
+ Machines : collections.Machines {
525
+ "machine-3" : machine ("machine-3" , withFailureDomain ("three" )),
526
+ },
527
+ }
528
+
529
+ g := NewWithT (t )
530
+ _ , err := c .MachineInFailureDomainWithMostMachines (ctx , machines )
531
+ g .Expect (err ).NotTo (HaveOccurred ())
532
+ })
533
+ t .Run ("Return error when no controlplane machine found" , func (t * testing.T ) {
534
+ machines := collections.Machines {}
535
+
536
+ c := & ControlPlane {
537
+ KCP : & controlplanev1.KubeadmControlPlane {},
538
+ Cluster : & clusterv1.Cluster {
539
+ Status : clusterv1.ClusterStatus {
540
+ FailureDomains : clusterv1.FailureDomains {},
541
+ },
542
+ },
543
+ Machines : collections.Machines {},
544
+ }
545
+
546
+ g := NewWithT (t )
547
+ _ , err := c .MachineInFailureDomainWithMostMachines (ctx , machines )
548
+ g .Expect (err ).To (HaveOccurred ())
549
+ })
550
+ }
551
+ func TestMachineWithDeleteAnnotation (t * testing.T ) {
552
+ t .Run ("Machines having delete annotation set" , func (t * testing.T ) {
553
+ machines := collections.Machines {
554
+ "machine-1" : & clusterv1.Machine {
555
+ ObjectMeta : metav1.ObjectMeta {Name : "m1" ,
556
+ Annotations : map [string ]string {
557
+ "cluster.x-k8s.io/delete-machine" : "" ,
558
+ },
559
+ },
560
+ Spec : clusterv1.MachineSpec {
561
+ Version : ptr .To ("v1.31.0" ),
562
+ FailureDomain : ptr .To ("one" ),
563
+ InfrastructureRef : corev1.ObjectReference {Kind : "GenericInfrastructureMachine" , APIVersion : "infrastructure.cluster.x-k8s.io/v1beta1" , Name : "m1" },
564
+ }},
565
+ "machine-2" : & clusterv1.Machine {
566
+ ObjectMeta : metav1.ObjectMeta {Name : "m2" ,
567
+ Annotations : map [string ]string {
568
+ "cluster.x-k8s.io/delete-machine" : "" ,
569
+ },
570
+ },
571
+ Spec : clusterv1.MachineSpec {
572
+ Version : ptr .To ("v1.31.0" ),
573
+ FailureDomain : ptr .To ("two" ),
574
+ InfrastructureRef : corev1.ObjectReference {Kind : "GenericInfrastructureMachine" , APIVersion : "infrastructure.cluster.x-k8s.io/v1beta1" , Name : "m2" },
575
+ }},
576
+ }
577
+
578
+ c := ControlPlane {
579
+ Machines : machines ,
580
+ Cluster : & clusterv1.Cluster {
581
+ Status : clusterv1.ClusterStatus {},
582
+ },
583
+ }
584
+
585
+ g := NewWithT (t )
586
+ annotedMachines := c .MachineWithDeleteAnnotation (machines )
587
+ g .Expect (annotedMachines ).NotTo (BeNil ())
588
+ })
589
+ }
590
+
327
591
type machineOpt func (* clusterv1.Machine )
328
592
329
593
func failureDomain (controlPlane bool ) clusterv1.FailureDomainSpec {
0 commit comments