@@ -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/v1beta2"
30
32
controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta2"
31
33
"sigs.k8s.io/cluster-api/controlplane/kubeadm/internal/etcd"
32
34
"sigs.k8s.io/cluster-api/util/collections"
33
35
v1beta1conditions "sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1"
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 ) {
@@ -332,6 +508,94 @@ func TestStatusToLogKeyAndValues(t *testing.T) {
332
508
g .Expect (got [3 ]).To (Equal ("m1, m2, m3" ))
333
509
}
334
510
511
+ func TestMachineInFailureDomainWithMostMachines (t * testing.T ) {
512
+ t .Run ("Machines in Failure Domain" , func (t * testing.T ) {
513
+ machines := collections.Machines {
514
+ "machine-3" : & clusterv1.Machine {
515
+ ObjectMeta : metav1.ObjectMeta {Name : "m3" },
516
+ Spec : clusterv1.MachineSpec {
517
+ Version : ptr .To ("v1.31.0" ),
518
+ FailureDomain : ptr .To ("three" ),
519
+ InfrastructureRef : corev1.ObjectReference {Kind : "GenericInfrastructureMachine" , APIVersion : "infrastructure.cluster.x-k8s.io/v1beta1" , Name : "m3" },
520
+ }},
521
+ }
522
+
523
+ c := & ControlPlane {
524
+ KCP : & controlplanev1.KubeadmControlPlane {},
525
+ Cluster : & clusterv1.Cluster {
526
+ Status : clusterv1.ClusterStatus {
527
+ FailureDomains : clusterv1.FailureDomains {
528
+ "three" : failureDomain (false ),
529
+ },
530
+ },
531
+ },
532
+ Machines : collections.Machines {
533
+ "machine-3" : machine ("machine-3" , withFailureDomain ("three" )),
534
+ },
535
+ }
536
+
537
+ g := NewWithT (t )
538
+ _ , err := c .MachineInFailureDomainWithMostMachines (ctx , machines )
539
+ g .Expect (err ).NotTo (HaveOccurred ())
540
+ })
541
+ t .Run ("Return error when no controlplane machine found" , func (t * testing.T ) {
542
+ machines := collections.Machines {}
543
+
544
+ c := & ControlPlane {
545
+ KCP : & controlplanev1.KubeadmControlPlane {},
546
+ Cluster : & clusterv1.Cluster {
547
+ Status : clusterv1.ClusterStatus {
548
+ FailureDomains : clusterv1.FailureDomains {},
549
+ },
550
+ },
551
+ Machines : collections.Machines {},
552
+ }
553
+
554
+ g := NewWithT (t )
555
+ _ , err := c .MachineInFailureDomainWithMostMachines (ctx , machines )
556
+ g .Expect (err ).To (HaveOccurred ())
557
+ })
558
+ }
559
+ func TestMachineWithDeleteAnnotation (t * testing.T ) {
560
+ t .Run ("Machines having delete annotation set" , func (t * testing.T ) {
561
+ machines := collections.Machines {
562
+ "machine-1" : & clusterv1.Machine {
563
+ ObjectMeta : metav1.ObjectMeta {Name : "m1" ,
564
+ Annotations : map [string ]string {
565
+ "cluster.x-k8s.io/delete-machine" : "" ,
566
+ },
567
+ },
568
+ Spec : clusterv1.MachineSpec {
569
+ Version : ptr .To ("v1.31.0" ),
570
+ FailureDomain : ptr .To ("one" ),
571
+ InfrastructureRef : corev1.ObjectReference {Kind : "GenericInfrastructureMachine" , APIVersion : "infrastructure.cluster.x-k8s.io/v1beta1" , Name : "m1" },
572
+ }},
573
+ "machine-2" : & clusterv1.Machine {
574
+ ObjectMeta : metav1.ObjectMeta {Name : "m2" ,
575
+ Annotations : map [string ]string {
576
+ "cluster.x-k8s.io/delete-machine" : "" ,
577
+ },
578
+ },
579
+ Spec : clusterv1.MachineSpec {
580
+ Version : ptr .To ("v1.31.0" ),
581
+ FailureDomain : ptr .To ("two" ),
582
+ InfrastructureRef : corev1.ObjectReference {Kind : "GenericInfrastructureMachine" , APIVersion : "infrastructure.cluster.x-k8s.io/v1beta1" , Name : "m2" },
583
+ }},
584
+ }
585
+
586
+ c := ControlPlane {
587
+ Machines : machines ,
588
+ Cluster : & clusterv1.Cluster {
589
+ Status : clusterv1.ClusterStatus {},
590
+ },
591
+ }
592
+
593
+ g := NewWithT (t )
594
+ annotedMachines := c .MachineWithDeleteAnnotation (machines )
595
+ g .Expect (annotedMachines ).NotTo (BeNil ())
596
+ })
597
+ }
598
+
335
599
type machineOpt func (* clusterv1.Machine )
336
600
337
601
func failureDomain (controlPlane bool ) clusterv1.FailureDomainSpec {
0 commit comments