@@ -22,12 +22,15 @@ import (
22
22
. "github.com/onsi/gomega"
23
23
corev1 "k8s.io/api/core/v1"
24
24
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
25
26
"k8s.io/utils/ptr"
27
+ "sigs.k8s.io/controller-runtime/pkg/client"
26
28
27
29
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
28
30
controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta1"
29
31
"sigs.k8s.io/cluster-api/util/collections"
30
32
"sigs.k8s.io/cluster-api/util/conditions"
33
+ "sigs.k8s.io/cluster-api/util/patch"
31
34
)
32
35
33
36
func TestControlPlane (t * testing.T ) {
@@ -61,6 +64,12 @@ func TestControlPlane(t *testing.T) {
61
64
controlPlane .Machines .Insert (machine ("machine-5" , withFailureDomain ("unknown" )))
62
65
g .Expect (* controlPlane .FailureDomainWithMostMachines (ctx , controlPlane .Machines )).To (Equal ("unknown" ))
63
66
})
67
+
68
+ t .Run ("With failure Domains is set empty" , func (* testing.T ) {
69
+ g := NewWithT (t )
70
+ controlPlane .Cluster .Status .FailureDomains = nil
71
+ g .Expect (* controlPlane .FailureDomainWithMostMachines (ctx , controlPlane .Machines )).To (Equal ("one" ))
72
+ })
64
73
})
65
74
66
75
t .Run ("MachinesUpToDate" , func (t * testing.T ) {
@@ -141,6 +150,173 @@ func TestControlPlane(t *testing.T) {
141
150
g .Expect (err ).NotTo (HaveOccurred ())
142
151
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
143
152
})
153
+
154
+ t .Run ("Next Failure Domains" , func (t * testing.T ) {
155
+ g := NewWithT (t )
156
+ cluster := clusterv1.Cluster {
157
+ Status : clusterv1.ClusterStatus {
158
+ FailureDomains : clusterv1.FailureDomains {
159
+ "one" : failureDomain (false ),
160
+ },
161
+ },
162
+ }
163
+ kcp := & controlplanev1.KubeadmControlPlane {
164
+ Spec : controlplanev1.KubeadmControlPlaneSpec {
165
+ Version : "v1.31.0" ,
166
+ },
167
+ }
168
+ machines := collections.Machines {
169
+ "machine-1" : & clusterv1.Machine {
170
+ ObjectMeta : metav1.ObjectMeta {Name : "m1" , DeletionTimestamp : ptr .To (metav1 .Now ())},
171
+ Spec : clusterv1.MachineSpec {
172
+ Version : ptr .To ("v1.31.0" ), // deleted
173
+ FailureDomain : ptr .To ("one" ),
174
+ InfrastructureRef : corev1.ObjectReference {Kind : "GenericInfrastructureMachine" , APIVersion : "infrastructure.cluster.x-k8s.io/v1beta1" , Name : "m1" },
175
+ }},
176
+ }
177
+ controlPlane , err := NewControlPlane (ctx , nil , env .GetClient (), & cluster , kcp , machines )
178
+ g .Expect (err ).NotTo (HaveOccurred ())
179
+ fd , err := controlPlane .NextFailureDomainForScaleUp (ctx )
180
+ g .Expect (err ).NotTo (HaveOccurred ())
181
+ g .Expect (fd ).To (BeNil ())
182
+ })
183
+
184
+ t .Run ("ControlPlane returns infra error" , func (t * testing.T ) {
185
+ g := NewWithT (t )
186
+ cluster := clusterv1.Cluster {
187
+ Status : clusterv1.ClusterStatus {
188
+ FailureDomains : clusterv1.FailureDomains {
189
+ "one" : failureDomain (true ),
190
+ "two" : failureDomain (true ),
191
+ "three" : failureDomain (true ),
192
+ },
193
+ },
194
+ }
195
+ kcp := & controlplanev1.KubeadmControlPlane {
196
+ Spec : controlplanev1.KubeadmControlPlaneSpec {
197
+ Version : "v1.31.0" ,
198
+ },
199
+ }
200
+ machines := collections.Machines {
201
+ "machine-1" : & clusterv1.Machine {
202
+ ObjectMeta : metav1.ObjectMeta {Name : "m1" },
203
+ Spec : clusterv1.MachineSpec {
204
+ Version : ptr .To ("v1.31.0" ),
205
+ FailureDomain : ptr .To ("one" ),
206
+ InfrastructureRef : corev1.ObjectReference {Name : "m1" },
207
+ }},
208
+ }
209
+ _ , err := NewControlPlane (ctx , nil , env .GetClient (), & cluster , kcp , machines )
210
+ g .Expect (err ).To (HaveOccurred ())
211
+ })
212
+
213
+ t .Run ("When infra and bootstrap config is exists" , func (t * testing.T ) {
214
+ g := NewWithT (t )
215
+ ns , err := env .CreateNamespace (ctx , "test-machine-watches" )
216
+ kcp := & controlplanev1.KubeadmControlPlane {
217
+ Spec : controlplanev1.KubeadmControlPlaneSpec {
218
+ Version : "v1.31.0" ,
219
+ },
220
+ }
221
+
222
+ g .Expect (err ).ToNot (HaveOccurred ())
223
+
224
+ infraMachine := & unstructured.Unstructured {
225
+ Object : map [string ]interface {}{
226
+ "kind" : "GenericInfrastructureMachine" ,
227
+ "apiVersion" : "infrastructure.cluster.x-k8s.io/v1beta1" ,
228
+ "metadata" : map [string ]interface {}{
229
+ "name" : "infra-config1" ,
230
+ "namespace" : ns .Name ,
231
+ },
232
+ "spec" : map [string ]interface {}{
233
+ "providerID" : "test://id-1" ,
234
+ },
235
+ "status" : map [string ]interface {}{
236
+ "ready" : true ,
237
+ "addresses" : []interface {}{
238
+ map [string ]interface {}{
239
+ "type" : "InternalIP" ,
240
+ "address" : "10.0.0.1" ,
241
+ },
242
+ },
243
+ },
244
+ },
245
+ }
246
+
247
+ bootstrap := & unstructured.Unstructured {
248
+ Object : map [string ]interface {}{
249
+ "kind" : "KubeadmConfig" ,
250
+ "apiVersion" : "bootstrap.cluster.x-k8s.io/v1beta1" ,
251
+ "metadata" : map [string ]interface {}{
252
+ "name" : "bootstrap-config-machinereconcile" ,
253
+ "namespace" : ns .Name ,
254
+ },
255
+ "spec" : map [string ]interface {}{
256
+ "providerID" : "test://id-1" ,
257
+ },
258
+ "status" : map [string ]interface {}{
259
+ "ready" : true ,
260
+ },
261
+ },
262
+ }
263
+
264
+ testCluster := & clusterv1.Cluster {
265
+ ObjectMeta : metav1.ObjectMeta {Name : "test-cluster" , Namespace : ns .Name },
266
+ Status : clusterv1.ClusterStatus {
267
+ FailureDomains : clusterv1.FailureDomains {
268
+ "one" : failureDomain (true ),
269
+ "two" : failureDomain (true ),
270
+ "three" : failureDomain (true ),
271
+ },
272
+ },
273
+ }
274
+
275
+ g .Expect (env .Create (ctx , infraMachine )).To (Succeed ())
276
+ g .Expect (env .Create (ctx , bootstrap )).To (Succeed ())
277
+
278
+ defer func (do ... client.Object ) {
279
+ g .Expect (env .Cleanup (ctx , do ... )).To (Succeed ())
280
+ }(ns , bootstrap , infraMachine )
281
+
282
+ // Patch infra machine ready
283
+ patchHelper , err := patch .NewHelper (infraMachine , env )
284
+ g .Expect (err ).ShouldNot (HaveOccurred ())
285
+ g .Expect (unstructured .SetNestedField (infraMachine .Object , true , "status" , "ready" )).To (Succeed ())
286
+ g .Expect (patchHelper .Patch (ctx , infraMachine , patch.WithStatusObservedGeneration {})).To (Succeed ())
287
+
288
+ // Patch bootstrap ready
289
+ patchHelper , err = patch .NewHelper (bootstrap , env )
290
+ g .Expect (err ).ShouldNot (HaveOccurred ())
291
+ g .Expect (unstructured .SetNestedField (bootstrap .Object , true , "status" , "ready" )).To (Succeed ())
292
+ g .Expect (patchHelper .Patch (ctx , bootstrap , patch.WithStatusObservedGeneration {})).To (Succeed ())
293
+
294
+ machines := collections.Machines {
295
+ "machine-1" : & clusterv1.Machine {
296
+ ObjectMeta : metav1.ObjectMeta {Name : "m1" ,
297
+ Namespace : ns .Name },
298
+ Spec : clusterv1.MachineSpec {
299
+ InfrastructureRef : corev1.ObjectReference {
300
+ APIVersion : "infrastructure.cluster.x-k8s.io/v1beta1" ,
301
+ Kind : "GenericInfrastructureMachine" ,
302
+ Name : "infra-config1" ,
303
+ Namespace : ns .Name ,
304
+ },
305
+ Bootstrap : clusterv1.Bootstrap {
306
+ ConfigRef : & corev1.ObjectReference {
307
+ APIVersion : "bootstrap.cluster.x-k8s.io/v1beta1" ,
308
+ Kind : "KubeadmConfig" ,
309
+ Name : "bootstrap-config-machinereconcile" ,
310
+ Namespace : ns .Name ,
311
+ },
312
+ },
313
+ },
314
+ },
315
+ }
316
+
317
+ _ , err = NewControlPlane (ctx , nil , env .GetClient (), testCluster , kcp , machines )
318
+ g .Expect (err ).NotTo (HaveOccurred ())
319
+ })
144
320
}
145
321
146
322
func TestHasMachinesToBeRemediated (t * testing.T ) {
@@ -252,6 +428,94 @@ func TestHasHealthyMachineStillProvisioning(t *testing.T) {
252
428
})
253
429
}
254
430
431
+ func TestMachineInFailureDomainWithMostMachines (t * testing.T ) {
432
+ t .Run ("Machines in Failure Domain" , func (t * testing.T ) {
433
+ machines := collections.Machines {
434
+ "machine-3" : & clusterv1.Machine {
435
+ ObjectMeta : metav1.ObjectMeta {Name : "m3" },
436
+ Spec : clusterv1.MachineSpec {
437
+ Version : ptr .To ("v1.31.0" ),
438
+ FailureDomain : ptr .To ("three" ),
439
+ InfrastructureRef : corev1.ObjectReference {Kind : "GenericInfrastructureMachine" , APIVersion : "infrastructure.cluster.x-k8s.io/v1beta1" , Name : "m3" },
440
+ }},
441
+ }
442
+
443
+ c := & ControlPlane {
444
+ KCP : & controlplanev1.KubeadmControlPlane {},
445
+ Cluster : & clusterv1.Cluster {
446
+ Status : clusterv1.ClusterStatus {
447
+ FailureDomains : clusterv1.FailureDomains {
448
+ "three" : failureDomain (false ),
449
+ },
450
+ },
451
+ },
452
+ Machines : collections.Machines {
453
+ "machine-3" : machine ("machine-3" , withFailureDomain ("three" )),
454
+ },
455
+ }
456
+
457
+ g := NewWithT (t )
458
+ _ , err := c .MachineInFailureDomainWithMostMachines (ctx , machines )
459
+ g .Expect (err ).NotTo (HaveOccurred ())
460
+ })
461
+ t .Run ("Return error when no controlplane machine found" , func (t * testing.T ) {
462
+ machines := collections.Machines {}
463
+
464
+ c := & ControlPlane {
465
+ KCP : & controlplanev1.KubeadmControlPlane {},
466
+ Cluster : & clusterv1.Cluster {
467
+ Status : clusterv1.ClusterStatus {
468
+ FailureDomains : clusterv1.FailureDomains {},
469
+ },
470
+ },
471
+ Machines : collections.Machines {},
472
+ }
473
+
474
+ g := NewWithT (t )
475
+ _ , err := c .MachineInFailureDomainWithMostMachines (ctx , machines )
476
+ g .Expect (err ).To (HaveOccurred ())
477
+ })
478
+ }
479
+ func TestMachineWithDeleteAnnotation (t * testing.T ) {
480
+ t .Run ("Machines having delete annotation set" , func (t * testing.T ) {
481
+ machines := collections.Machines {
482
+ "machine-1" : & clusterv1.Machine {
483
+ ObjectMeta : metav1.ObjectMeta {Name : "m1" ,
484
+ Annotations : map [string ]string {
485
+ "cluster.x-k8s.io/delete-machine" : "" ,
486
+ },
487
+ },
488
+ Spec : clusterv1.MachineSpec {
489
+ Version : ptr .To ("v1.31.0" ),
490
+ FailureDomain : ptr .To ("one" ),
491
+ InfrastructureRef : corev1.ObjectReference {Kind : "GenericInfrastructureMachine" , APIVersion : "infrastructure.cluster.x-k8s.io/v1beta1" , Name : "m1" },
492
+ }},
493
+ "machine-2" : & clusterv1.Machine {
494
+ ObjectMeta : metav1.ObjectMeta {Name : "m2" ,
495
+ Annotations : map [string ]string {
496
+ "cluster.x-k8s.io/delete-machine" : "" ,
497
+ },
498
+ },
499
+ Spec : clusterv1.MachineSpec {
500
+ Version : ptr .To ("v1.31.0" ),
501
+ FailureDomain : ptr .To ("two" ),
502
+ InfrastructureRef : corev1.ObjectReference {Kind : "GenericInfrastructureMachine" , APIVersion : "infrastructure.cluster.x-k8s.io/v1beta1" , Name : "m2" },
503
+ }},
504
+ }
505
+
506
+ c := ControlPlane {
507
+ Machines : machines ,
508
+ Cluster : & clusterv1.Cluster {
509
+ Status : clusterv1.ClusterStatus {},
510
+ },
511
+ }
512
+
513
+ g := NewWithT (t )
514
+ annotedMachines := c .MachineWithDeleteAnnotation (machines )
515
+ g .Expect (annotedMachines ).NotTo (BeNil ())
516
+ })
517
+ }
518
+
255
519
type machineOpt func (* clusterv1.Machine )
256
520
257
521
func failureDomain (controlPlane bool ) clusterv1.FailureDomainSpec {
0 commit comments