Skip to content

Commit f68e2cd

Browse files
committed
test(e2e): add precheck for affinity and toleration e2e
Signed-off-by: Dmitry Lopatin <dmitry.lopatin@flant.com>
1 parent a01cf49 commit f68e2cd

3 files changed

Lines changed: 113 additions & 1 deletion

File tree

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
Copyright 2026 Flant JSC
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package precheck
18+
19+
import (
20+
"context"
21+
"fmt"
22+
23+
. "github.com/onsi/ginkgo/v2"
24+
corev1 "k8s.io/api/core/v1"
25+
crclient "sigs.k8s.io/controller-runtime/pkg/client"
26+
27+
"github.com/deckhouse/virtualization/test/e2e/internal/framework"
28+
)
29+
30+
const (
31+
affinityTolerationPrecheckEnvName = "AFFINITY_TOLERATION_PRECHECK"
32+
affinityTolerationNodeGroupLabelKey = "node.deckhouse.io/group"
33+
affinityTolerationKVMLabelKey = "virtualization.deckhouse.io/kvm-enabled"
34+
35+
minReadyKVMNodes = 2
36+
minReadyKVMMasterNodes = 1
37+
minReadyKVMWorkerNodes = 2
38+
)
39+
40+
// affinityTolerationPrecheck implements Precheck interface for VM affinity/toleration test cluster requirements.
41+
type affinityTolerationPrecheck struct{}
42+
43+
func (a *affinityTolerationPrecheck) Label() string {
44+
return PrecheckAffinityToleration
45+
}
46+
47+
func (a *affinityTolerationPrecheck) Run(ctx context.Context, f *framework.Framework) error {
48+
if !isCheckEnabled(affinityTolerationPrecheckEnvName) {
49+
_, _ = GinkgoWriter.Write([]byte("Affinity/toleration precheck is disabled.\n"))
50+
return nil
51+
}
52+
53+
kvmNodes, err := listReadyNodesByLabels(ctx, f, map[string]string{affinityTolerationKVMLabelKey: "true"})
54+
if err != nil {
55+
return fmt.Errorf("%s=no to disable this precheck: failed to list ready KVM-enabled nodes: %w", affinityTolerationPrecheckEnvName, err)
56+
}
57+
if len(kvmNodes) < minReadyKVMNodes {
58+
return fmt.Errorf("%s=no to disable this precheck: at least %d ready KVM-enabled nodes are required, got %d", affinityTolerationPrecheckEnvName, minReadyKVMNodes, len(kvmNodes))
59+
}
60+
61+
masterNodes, err := listReadyNodesByLabels(ctx, f, map[string]string{
62+
affinityTolerationKVMLabelKey: "true",
63+
affinityTolerationNodeGroupLabelKey: "master",
64+
})
65+
if err != nil {
66+
return fmt.Errorf("%s=no to disable this precheck: failed to list ready KVM-enabled master nodes: %w", affinityTolerationPrecheckEnvName, err)
67+
}
68+
if len(masterNodes) < minReadyKVMMasterNodes {
69+
return fmt.Errorf("%s=no to disable this precheck: at least %d ready KVM-enabled master node is required, got %d", affinityTolerationPrecheckEnvName, minReadyKVMMasterNodes, len(masterNodes))
70+
}
71+
72+
workerNodes, err := listReadyNodesByLabels(ctx, f, map[string]string{
73+
affinityTolerationKVMLabelKey: "true",
74+
affinityTolerationNodeGroupLabelKey: "worker",
75+
})
76+
if err != nil {
77+
return fmt.Errorf("%s=no to disable this precheck: failed to list ready KVM-enabled worker nodes: %w", affinityTolerationPrecheckEnvName, err)
78+
}
79+
if len(workerNodes) < minReadyKVMWorkerNodes {
80+
return fmt.Errorf("%s=no to disable this precheck: at least %d ready KVM-enabled worker nodes are required, got %d", affinityTolerationPrecheckEnvName, minReadyKVMWorkerNodes, len(workerNodes))
81+
}
82+
83+
return nil
84+
}
85+
86+
func listReadyNodesByLabels(ctx context.Context, f *framework.Framework, labels map[string]string) ([]corev1.Node, error) {
87+
nodes := &corev1.NodeList{}
88+
err := f.GenericClient().List(ctx, nodes, crclient.MatchingLabels(labels))
89+
if err != nil {
90+
return nil, err
91+
}
92+
93+
readyNodes := make([]corev1.Node, 0, len(nodes.Items))
94+
for _, node := range nodes.Items {
95+
for _, condition := range node.Status.Conditions {
96+
if condition.Type == corev1.NodeReady && condition.Status == corev1.ConditionTrue {
97+
readyNodes = append(readyNodes, node)
98+
break
99+
}
100+
}
101+
}
102+
103+
return readyNodes, nil
104+
}
105+
106+
func init() {
107+
RegisterPrecheck(&affinityTolerationPrecheck{}, false)
108+
}

test/e2e/internal/precheck/labels.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ const (
4545
// PrecheckUSB - test requires USB device with dummy_hcd to be configured.
4646
PrecheckUSB = "usb-precheck"
4747

48+
// PrecheckAffinityToleration - test requires enough ready KVM-enabled master/worker nodes.
49+
PrecheckAffinityToleration = "affinity-toleration-precheck"
50+
4851
// PrecheckPostCleanup - test requires postcleanup to be configured.
4952
PrecheckPostCleanup = "postcleanup-precheck"
5053

@@ -68,6 +71,7 @@ func KnownPrecheckLabels() []string {
6871
PrecheckSnapshot,
6972
PrecheckVirtualization,
7073
PrecheckUSB,
74+
PrecheckAffinityToleration,
7175
PrecheckPostCleanup,
7276
PrecheckPrecreatedCVI,
7377
NoPrecheck,

test/e2e/vm/affinity_toleration.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const (
5555
migrationTargetMustDiffer
5656
)
5757

58-
var _ = Describe("VirtualMachineAffinityAndToleration", Ordered, Label(precheck.NoPrecheck), func() {
58+
var _ = Describe("VirtualMachineAffinityAndToleration", Ordered, Label(precheck.PrecheckAffinityToleration), func() {
5959
var (
6060
f *framework.Framework
6161
ctx context.Context

0 commit comments

Comments
 (0)