From c175998eebd4e98e9944d519d69854599dd93a2f Mon Sep 17 00:00:00 2001 From: Marvin Beckers Date: Wed, 8 Feb 2023 13:41:31 +0100 Subject: [PATCH] Generate correct node affinity if no values are passed (#1557) * Generate correct node affinity if no values are passed Signed-off-by: Marvin Beckers * Add test for affinity without values Signed-off-by: Marvin Beckers * Fix yamllint complaint Signed-off-by: Marvin Beckers --------- Signed-off-by: Marvin Beckers --- .../provider/kubevirt/provider.go | 29 +++---- .../provider/kubevirt/provider_test.go | 13 ++- .../kubevirt/testdata/affinity-no-values.yaml | 83 +++++++++++++++++++ 3 files changed, 108 insertions(+), 17 deletions(-) create mode 100644 pkg/cloudprovider/provider/kubevirt/testdata/affinity-no-values.yaml diff --git a/pkg/cloudprovider/provider/kubevirt/provider.go b/pkg/cloudprovider/provider/kubevirt/provider.go index 28654c0f9..044439b1b 100644 --- a/pkg/cloudprovider/provider/kubevirt/provider.go +++ b/pkg/cloudprovider/provider/kubevirt/provider.go @@ -852,6 +852,19 @@ func getDataVolumeTemplates(config *Config, dataVolumeName string) []kubevirtv1. func getAffinity(config *Config, matchKey, matchValue string) *corev1.Affinity { affinity := &corev1.Affinity{} + expressions := []corev1.NodeSelectorRequirement{ + { + Key: config.NodeAffinityPreset.Key, + Operator: corev1.NodeSelectorOperator(metav1.LabelSelectorOpExists), + }, + } + + // change the operator if any values were passed for node affinity matching + if len(config.NodeAffinityPreset.Values) > 0 { + expressions[0].Operator = corev1.NodeSelectorOperator(metav1.LabelSelectorOpIn) + expressions[0].Values = config.NodeAffinityPreset.Values + } + // NodeAffinity switch config.NodeAffinityPreset.Type { case softAffinityType: @@ -860,13 +873,7 @@ func getAffinity(config *Config, matchKey, matchValue string) *corev1.Affinity { { Weight: 1, Preference: corev1.NodeSelectorTerm{ - MatchExpressions: []corev1.NodeSelectorRequirement{ - { - Key: config.NodeAffinityPreset.Key, - Values: config.NodeAffinityPreset.Values, - Operator: corev1.NodeSelectorOperator(metav1.LabelSelectorOpIn), - }, - }, + MatchExpressions: expressions, }, }, }, @@ -876,13 +883,7 @@ func getAffinity(config *Config, matchKey, matchValue string) *corev1.Affinity { RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ NodeSelectorTerms: []corev1.NodeSelectorTerm{ { - MatchExpressions: []corev1.NodeSelectorRequirement{ - { - Key: config.NodeAffinityPreset.Key, - Values: config.NodeAffinityPreset.Values, - Operator: corev1.NodeSelectorOperator(metav1.LabelSelectorOpIn), - }, - }, + MatchExpressions: expressions, }, }, }, diff --git a/pkg/cloudprovider/provider/kubevirt/provider_test.go b/pkg/cloudprovider/provider/kubevirt/provider_test.go index cdab28d29..1ec62cc0d 100644 --- a/pkg/cloudprovider/provider/kubevirt/provider_test.go +++ b/pkg/cloudprovider/provider/kubevirt/provider_test.go @@ -60,6 +60,7 @@ type kubevirtProviderSpecConf struct { OperatingSystem string TopologySpreadConstraint bool Affinity bool + AffinityValues bool SecondaryDisks bool OsImageSource imageSource } @@ -86,9 +87,11 @@ func (k kubevirtProviderSpecConf) rawProviderSpec(t *testing.T) []byte { "affinity": { "nodeAffinityPreset": { "type": "hard", - "key": "key1", - "values": [ + "key": "key1" + {{- if .AffinityValues }} + , "values": [ "foo1", "foo2" ] + {{- end }} } }, {{- end }} @@ -194,7 +197,11 @@ func TestNewVirtualMachine(t *testing.T) { }, { name: "affinity", - specConf: kubevirtProviderSpecConf{Affinity: true}, + specConf: kubevirtProviderSpecConf{Affinity: true, AffinityValues: true}, + }, + { + name: "affinity-no-values", + specConf: kubevirtProviderSpecConf{Affinity: true, AffinityValues: false}, }, { name: "secondary-disks", diff --git a/pkg/cloudprovider/provider/kubevirt/testdata/affinity-no-values.yaml b/pkg/cloudprovider/provider/kubevirt/testdata/affinity-no-values.yaml new file mode 100644 index 000000000..f304b2a6e --- /dev/null +++ b/pkg/cloudprovider/provider/kubevirt/testdata/affinity-no-values.yaml @@ -0,0 +1,83 @@ +apiVersion: kubevirt.io/v1 +kind: VirtualMachine +metadata: + annotations: + labels: + cluster.x-k8s.io/cluster-name: cluster-name + cluster.x-k8s.io/role: worker + kubevirt.io/vm: affinity-no-values + md: md-name + name: affinity-no-values + namespace: test-namespace +spec: + dataVolumeTemplates: + - metadata: + creationTimestamp: null + name: affinity-no-values + spec: + pvc: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi + storageClassName: longhorn + source: + http: + url: http://x.y.z.t/ubuntu.img + running: true + template: + metadata: + labels: + cluster.x-k8s.io/cluster-name: cluster-name + cluster.x-k8s.io/role: worker + kubevirt.io/vm: affinity-no-values + md: md-name + spec: + affinity: + nodeAffinity: # Section present if nodeAffinityPreset.type != "" + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: key1 + operator: Exists + domain: + devices: + disks: + - disk: + bus: virtio + name: datavolumedisk + - disk: + bus: virtio + name: cloudinitdisk + interfaces: + - macAddress: b6:f5:b4:fe:45:1d + name: default + bridge: {} + resources: + limits: + cpu: "2" + memory: 2Gi + requests: + cpu: "2" + memory: 2Gi + networks: + - name: default + pod: {} + terminationGracePeriodSeconds: 30 + topologyspreadconstraints: + - maxskew: 1 + topologykey: kubernetes.io/hostname + whenunsatisfiable: ScheduleAnyway + labelselector: + matchlabels: + md: md-name + volumes: + - dataVolume: + name: affinity-no-values + name: datavolumedisk + - cloudInitNoCloud: + secretRef: + name: udsn + name: cloudinitdisk + evictionStrategy: External