Skip to content

Commit d373a7c

Browse files
committed
Add UTs for failure domain
1 parent 3d6f63d commit d373a7c

File tree

2 files changed

+607
-0
lines changed

2 files changed

+607
-0
lines changed

Diff for: controlplane/kubeadm/internal/control_plane_test.go

+264
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,16 @@ import (
2424
. "github.com/onsi/gomega"
2525
corev1 "k8s.io/api/core/v1"
2626
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2728
"k8s.io/utils/ptr"
29+
"sigs.k8s.io/controller-runtime/pkg/client"
2830

2931
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta2"
3032
controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta2"
3133
"sigs.k8s.io/cluster-api/controlplane/kubeadm/internal/etcd"
3234
"sigs.k8s.io/cluster-api/util/collections"
3335
v1beta1conditions "sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1"
36+
"sigs.k8s.io/cluster-api/util/patch"
3437
)
3538

3639
func TestControlPlane(t *testing.T) {
@@ -64,6 +67,12 @@ func TestControlPlane(t *testing.T) {
6467
controlPlane.Machines.Insert(machine("machine-5", withFailureDomain("unknown")))
6568
g.Expect(*controlPlane.FailureDomainWithMostMachines(ctx, controlPlane.Machines)).To(Equal("unknown"))
6669
})
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+
})
6776
})
6877

6978
t.Run("MachinesUpToDate", func(t *testing.T) {
@@ -144,6 +153,173 @@ func TestControlPlane(t *testing.T) {
144153
g.Expect(err).NotTo(HaveOccurred())
145154
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
146155
})
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+
})
147323
}
148324

149325
func TestHasMachinesToBeRemediated(t *testing.T) {
@@ -332,6 +508,94 @@ func TestStatusToLogKeyAndValues(t *testing.T) {
332508
g.Expect(got[3]).To(Equal("m1, m2, m3"))
333509
}
334510

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+
335599
type machineOpt func(*clusterv1.Machine)
336600

337601
func failureDomain(controlPlane bool) clusterv1.FailureDomainSpec {

0 commit comments

Comments
 (0)