Skip to content

Commit 22d7db0

Browse files
srm09zhanggbj
authored andcommitted
Selectively add node-pool AAF constraint
Signed-off-by: Sagar Muchhal <sagar.muchhal@broadcom.com>
1 parent 9f261d5 commit 22d7db0

File tree

2 files changed

+133
-57
lines changed

2 files changed

+133
-57
lines changed

pkg/services/vmoperator/vmopmachine.go

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -267,20 +267,25 @@ func (v *VmopMachineService) ReconcileNormal(ctx context.Context, machineCtx cap
267267
},
268268
TopologyKey: corev1.LabelHostname,
269269
},
270-
{
271-
LabelSelector: &metav1.LabelSelector{
272-
MatchExpressions: []metav1.LabelSelectorRequirement{
273-
{
274-
Key: clusterv1.MachineDeploymentNameLabel,
275-
Operator: metav1.LabelSelectorOpIn,
276-
Values: mdNames,
277-
},
270+
},
271+
},
272+
}
273+
if len(mdNames) > 0 {
274+
affInfo.affinitySpec.VMAntiAffinity.PreferredDuringSchedulingPreferredDuringExecution = append(
275+
affInfo.affinitySpec.VMAntiAffinity.PreferredDuringSchedulingPreferredDuringExecution,
276+
vmoprv1.VMAffinityTerm{
277+
LabelSelector: &metav1.LabelSelector{
278+
MatchExpressions: []metav1.LabelSelectorRequirement{
279+
{
280+
Key: clusterv1.MachineDeploymentNameLabel,
281+
Operator: metav1.LabelSelectorOpIn,
282+
Values: mdNames,
278283
},
279284
},
280-
TopologyKey: corev1.LabelTopologyZone,
281285
},
286+
TopologyKey: corev1.LabelTopologyZone,
282287
},
283-
},
288+
)
284289
}
285290
}
286291

pkg/services/vmoperator/vmopmachine_test.go

Lines changed: 118 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package vmoperator
1919
import (
2020
"context"
2121
"fmt"
22+
"slices"
2223
"testing"
2324
"time"
2425

@@ -68,8 +69,7 @@ func updateReconciledVMStatus(ctx context.Context, vmService VmopMachineService,
6869
Expect(err).ShouldNot(HaveOccurred())
6970
}
7071

71-
// verifyVMAffinityRules is a helper method to assert the VM affinity rules.
72-
func verifyVMAffinityRules(vmopVM *vmoprv1.VirtualMachine, machineDeploymentName, clusterName string) {
72+
func verifyVMAffinityRules(vmopVM *vmoprv1.VirtualMachine, machineDeploymentName string) {
7373
Expect(vmopVM.Spec.Affinity.VMAffinity).ShouldNot(BeNil())
7474
Expect(vmopVM.Spec.Affinity.VMAffinity.RequiredDuringSchedulingPreferredDuringExecution).To(HaveLen(1))
7575

@@ -78,21 +78,38 @@ func verifyVMAffinityRules(vmopVM *vmoprv1.VirtualMachine, machineDeploymentName
7878
Expect(vmAffinityTerm.TopologyKey).To(Equal(corev1.LabelTopologyZone))
7979
}
8080

81-
// verifyVMAntiAffinityRules is a helper method to assert the VM anti-affinity rules.
82-
func verifyVMAntiAffinityRules(vmopVM *vmoprv1.VirtualMachine, machineDeploymentName, clusterName string) {
81+
func verifyVMAntiAffinityRules(vmopVM *vmoprv1.VirtualMachine, machineDeploymentName string, extraMDs ...string) {
8382
Expect(vmopVM.Spec.Affinity.VMAntiAffinity).ShouldNot(BeNil())
84-
Expect(vmopVM.Spec.Affinity.VMAntiAffinity.PreferredDuringSchedulingPreferredDuringExecution).To(HaveLen(2))
8583

86-
// First anti-affinity term - same machine deployment, different hosts
87-
antiAffinityTerm1 := vmopVM.Spec.Affinity.VMAntiAffinity.PreferredDuringSchedulingPreferredDuringExecution[0]
84+
expectedNumAntiAffinityTerms := 1
85+
if len(extraMDs) > 0 {
86+
expectedNumAntiAffinityTerms = 2
87+
}
88+
89+
antiAffinityTerms := vmopVM.Spec.Affinity.VMAntiAffinity.PreferredDuringSchedulingPreferredDuringExecution
90+
Expect(antiAffinityTerms).To(HaveLen(expectedNumAntiAffinityTerms))
91+
92+
// First anti-affinity constraint - same machine deployment, different hosts
93+
antiAffinityTerm1 := antiAffinityTerms[0]
8894
Expect(antiAffinityTerm1.LabelSelector.MatchLabels).To(HaveKeyWithValue(clusterv1.MachineDeploymentNameLabel, machineDeploymentName))
8995
Expect(antiAffinityTerm1.TopologyKey).To(Equal(corev1.LabelHostname))
9096

9197
// Second anti-affinity term - different machine deployments
92-
antiAffinityTerm2 := vmopVM.Spec.Affinity.VMAntiAffinity.PreferredDuringSchedulingPreferredDuringExecution[1]
93-
Expect(antiAffinityTerm2.LabelSelector.MatchExpressions).To(HaveLen(1))
94-
Expect(antiAffinityTerm2.LabelSelector.MatchExpressions[0].Key).To(Equal(clusterv1.MachineDeploymentNameLabel))
95-
Expect(antiAffinityTerm2.LabelSelector.MatchExpressions[0].Operator).To(Equal(metav1.LabelSelectorOpIn))
98+
if len(extraMDs) > 0 {
99+
isSortedAlphabetically := func(actual []string) (bool, error) {
100+
return slices.IsSorted(actual), nil
101+
}
102+
antiAffinityTerm2 := antiAffinityTerms[1]
103+
Expect(antiAffinityTerm2.LabelSelector.MatchExpressions).To(HaveLen(1))
104+
Expect(antiAffinityTerm2.LabelSelector.MatchExpressions[0].Key).To(Equal(clusterv1.MachineDeploymentNameLabel))
105+
Expect(antiAffinityTerm2.LabelSelector.MatchExpressions[0].Operator).To(Equal(metav1.LabelSelectorOpIn))
106+
107+
Expect(antiAffinityTerm2.LabelSelector.MatchExpressions[0].Values).To(HaveLen(len(extraMDs)))
108+
Expect(antiAffinityTerm2.LabelSelector.MatchExpressions[0].Values).To(
109+
WithTransform(isSortedAlphabetically, BeTrue()),
110+
"Expected extra machine deployments to be sorted alphabetically",
111+
)
112+
}
96113
}
97114

98115
const (
@@ -111,6 +128,32 @@ const (
111128
clusterNameLabel = clusterv1.ClusterNameLabel
112129
)
113130

131+
func createMachineDeployment(name, namespace, clusterName, failureDomain string) *clusterv1.MachineDeployment {
132+
md := &clusterv1.MachineDeployment{
133+
ObjectMeta: metav1.ObjectMeta{
134+
Name: name,
135+
Namespace: namespace,
136+
Labels: map[string]string{
137+
clusterv1.ClusterNameLabel: clusterName,
138+
},
139+
},
140+
Spec: clusterv1.MachineDeploymentSpec{
141+
Template: clusterv1.MachineTemplateSpec{
142+
Spec: clusterv1.MachineSpec{
143+
// FailureDomain will be set conditionally below
144+
},
145+
},
146+
},
147+
}
148+
149+
// Only set failure domain if it's provided and not empty
150+
if failureDomain != "" {
151+
md.Spec.Template.Spec.FailureDomain = failureDomain
152+
}
153+
154+
return md
155+
}
156+
114157
var _ = Describe("VirtualMachine tests", func() {
115158

116159
var (
@@ -779,22 +822,7 @@ var _ = Describe("VirtualMachine tests", func() {
779822
Expect(vmService.Client.Create(ctx, vmGroup)).To(Succeed())
780823

781824
// Create a MachineDeployment for the worker
782-
machineDeployment := &clusterv1.MachineDeployment{
783-
ObjectMeta: metav1.ObjectMeta{
784-
Name: machineDeploymentName,
785-
Namespace: corev1.NamespaceDefault,
786-
Labels: map[string]string{
787-
clusterv1.ClusterNameLabel: clusterName,
788-
},
789-
},
790-
Spec: clusterv1.MachineDeploymentSpec{
791-
Template: clusterv1.MachineTemplateSpec{
792-
Spec: clusterv1.MachineSpec{
793-
// No failure domain set
794-
},
795-
},
796-
},
797-
}
825+
machineDeployment := createMachineDeployment(machineDeploymentName, corev1.NamespaceDefault, clusterName, "")
798826
Expect(vmService.Client.Create(ctx, machineDeployment)).To(Succeed())
799827
})
800828

@@ -831,10 +859,10 @@ var _ = Describe("VirtualMachine tests", func() {
831859
Expect(vmopVM.Spec.Affinity).ShouldNot(BeNil())
832860

833861
By("Verify VM affinity rules are set correctly")
834-
verifyVMAffinityRules(vmopVM, machineDeploymentName, clusterName)
862+
verifyVMAffinityRules(vmopVM, machineDeploymentName)
835863

836864
By("Verify VM anti-affinity rules are set correctly")
837-
verifyVMAntiAffinityRules(vmopVM, machineDeploymentName, clusterName)
865+
verifyVMAntiAffinityRules(vmopVM, machineDeploymentName)
838866

839867
By("Verify that worker machine has machine deploymet label set")
840868
Expect(vmopVM.Labels[clusterv1.MachineDeploymentNameLabel]).To(Equal(machineDeploymentName))
@@ -895,22 +923,7 @@ var _ = Describe("VirtualMachine tests", func() {
895923
Expect(vmService.Client.Create(ctx, vmGroup)).To(Succeed())
896924

897925
// Create a MachineDeployment for the worker with no explicit failure domain
898-
machineDeployment := &clusterv1.MachineDeployment{
899-
ObjectMeta: metav1.ObjectMeta{
900-
Name: machineDeploymentName,
901-
Namespace: corev1.NamespaceDefault,
902-
Labels: map[string]string{
903-
clusterv1.ClusterNameLabel: fdClusterName,
904-
},
905-
},
906-
Spec: clusterv1.MachineDeploymentSpec{
907-
Template: clusterv1.MachineTemplateSpec{
908-
Spec: clusterv1.MachineSpec{
909-
// No failure domain set on template
910-
},
911-
},
912-
},
913-
}
926+
machineDeployment := createMachineDeployment(machineDeploymentName, corev1.NamespaceDefault, fdClusterName, "")
914927
Expect(vmService.Client.Create(ctx, machineDeployment)).To(Succeed())
915928

916929
// Provide valid bootstrap data
@@ -940,10 +953,10 @@ var _ = Describe("VirtualMachine tests", func() {
940953
Expect(vmopVM.Spec.Affinity).ShouldNot(BeNil())
941954

942955
By("Verify VM affinity rules are set correctly")
943-
verifyVMAffinityRules(vmopVM, machineDeploymentName, fdClusterName)
956+
verifyVMAffinityRules(vmopVM, machineDeploymentName)
944957

945958
By("Verify VM anti-affinity rules are set correctly")
946-
verifyVMAntiAffinityRules(vmopVM, machineDeploymentName, fdClusterName)
959+
verifyVMAntiAffinityRules(vmopVM, machineDeploymentName)
947960

948961
By("Verify that worker machine has correct labels including topology")
949962
Expect(vmopVM.Labels[clusterv1.MachineDeploymentNameLabel]).To(Equal(machineDeploymentName))
@@ -952,6 +965,64 @@ var _ = Describe("VirtualMachine tests", func() {
952965
By("Verify that GroupName is set from VirtualMachineGroup")
953966
Expect(vmopVM.Spec.GroupName).To(Equal(fdClusterName))
954967
})
968+
969+
Context("For multiple machine deployments", func() {
970+
const (
971+
otherMdName1 = "other-md-1"
972+
otherMdName2 = "other-md-2"
973+
)
974+
975+
BeforeEach(func() {
976+
otherMd1 := createMachineDeployment(otherMdName1, corev1.NamespaceDefault, clusterName, "")
977+
Expect(vmService.Client.Create(ctx, otherMd1)).To(Succeed())
978+
979+
otherMd2 := createMachineDeployment(otherMdName2, corev1.NamespaceDefault, clusterName, "")
980+
Expect(vmService.Client.Create(ctx, otherMd2)).To(Succeed())
981+
982+
// Create a MachineDeployment with failure domain
983+
otherMdWithFd := createMachineDeployment("other-md-with-fd", corev1.NamespaceDefault, clusterName, "zone-1")
984+
Expect(vmService.Client.Create(ctx, otherMdWithFd)).To(Succeed())
985+
})
986+
987+
Specify("Reconcile valid machine with additional anti-affinity term added", func() {
988+
expectReconcileError = false
989+
expectVMOpVM = true
990+
expectedImageName = imageName
991+
expectedRequeue = true
992+
993+
// Provide valid bootstrap data
994+
By("bootstrap data is created")
995+
secretName := machine.GetName() + "-data"
996+
secret := &corev1.Secret{
997+
ObjectMeta: metav1.ObjectMeta{
998+
Name: secretName,
999+
Namespace: machine.GetNamespace(),
1000+
},
1001+
Data: map[string][]byte{
1002+
"value": []byte(bootstrapData),
1003+
},
1004+
}
1005+
Expect(vmService.Client.Create(ctx, secret)).To(Succeed())
1006+
1007+
machine.Spec.Bootstrap.DataSecretName = &secretName
1008+
1009+
By("VirtualMachine is created")
1010+
requeue, err = vmService.ReconcileNormal(ctx, supervisorMachineContext)
1011+
Expect(err).ShouldNot(HaveOccurred())
1012+
Expect(requeue).Should(BeTrue())
1013+
1014+
By("Verify that worker machine has affinity spec set")
1015+
vmopVM = getReconciledVM(ctx, vmService, supervisorMachineContext)
1016+
Expect(vmopVM).ShouldNot(BeNil())
1017+
Expect(vmopVM.Spec.Affinity).ShouldNot(BeNil())
1018+
1019+
By("Verify VM affinity rules are set correctly")
1020+
verifyVMAffinityRules(vmopVM, machineDeploymentName)
1021+
1022+
By("Verify VM anti-affinity rules are set correctly")
1023+
verifyVMAntiAffinityRules(vmopVM, machineDeploymentName, otherMdName1, otherMdName2)
1024+
})
1025+
})
9551026
})
9561027

9571028
})

0 commit comments

Comments
 (0)