1
19
20 package api
21
22 import (
23 . "github.com/onsi/ginkgo/v2"
24 . "github.com/onsi/gomega"
25 k8sv1 "k8s.io/api/core/v1"
26 "k8s.io/apimachinery/pkg/api/resource"
27 k8smetav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28
29 v1 "kubevirt.io/api/core/v1"
30 )
31
32 var _ = Describe("PodSelectors", func() {
33
34 It("should detect if VMIs want guaranteed QOS", func() {
35 vmi := NewMinimalVMI("testvmi")
36 vmi.Spec.Domain.Resources = v1.ResourceRequirements{
37 Requests: k8sv1.ResourceList{
38 k8sv1.ResourceCPU: resource.MustParse("1"),
39 k8sv1.ResourceMemory: resource.MustParse("64M"),
40 },
41 Limits: k8sv1.ResourceList{
42 k8sv1.ResourceCPU: resource.MustParse("1"),
43 k8sv1.ResourceMemory: resource.MustParse("64M"),
44 },
45 }
46 Expect(vmi.WantsToHaveQOSGuaranteed()).To(BeTrue())
47 })
48
49 It("should detect if VMIs don't want guaranteed QOS", func() {
50 vmi := NewMinimalVMI("testvmi")
51 vmi.Spec.Domain.Resources = v1.ResourceRequirements{
52 Requests: k8sv1.ResourceList{
53 k8sv1.ResourceMemory: resource.MustParse("64M"),
54 },
55 Limits: k8sv1.ResourceList{
56 k8sv1.ResourceCPU: resource.MustParse("1"),
57 k8sv1.ResourceMemory: resource.MustParse("64M"),
58 },
59 }
60 Expect(vmi.WantsToHaveQOSGuaranteed()).To(BeFalse())
61 })
62
63 Context("Pod affinity rules", func() {
64
65 It("should work", func() {
66 vmi := NewMinimalVMI("testvmi")
67 vmi.Status.NodeName = "test-node"
68 pod := &k8sv1.Pod{}
69 affinity := v1.UpdateAntiAffinityFromVMINode(pod, vmi)
70 newSelector := affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0]
71 Expect(newSelector).ToNot(BeNil())
72 Expect(newSelector.MatchExpressions).To(HaveLen(1))
73 Expect(newSelector.MatchExpressions[0].Values).To(HaveLen(1))
74 Expect(newSelector.MatchExpressions[0].Values[0]).To(Equal("test-node"))
75 })
76
77 It("should merge", func() {
78 vmi := NewMinimalVMI("testvmi")
79 vmi.Status.NodeName = "test-node"
80
81 existingTerm := k8sv1.NodeSelectorTerm{}
82 secondExistingTerm := k8sv1.NodeSelectorTerm{
83 MatchExpressions: []k8sv1.NodeSelectorRequirement{
84 {},
85 },
86 }
87
88 pod := &k8sv1.Pod{
89 Spec: k8sv1.PodSpec{
90 Affinity: &k8sv1.Affinity{
91 PodAffinity: &k8sv1.PodAffinity{},
92 NodeAffinity: &k8sv1.NodeAffinity{
93 RequiredDuringSchedulingIgnoredDuringExecution: &k8sv1.NodeSelector{
94 NodeSelectorTerms: []k8sv1.NodeSelectorTerm{
95 existingTerm,
96 secondExistingTerm,
97 },
98 },
99 },
100 },
101 },
102 }
103
104 affinity := v1.UpdateAntiAffinityFromVMINode(pod, vmi)
105
106 Expect(affinity.NodeAffinity).ToNot(BeNil())
107 Expect(affinity.PodAffinity).ToNot(BeNil())
108 Expect(affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution).ToNot(BeNil())
109 Expect(affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms).ToNot(BeNil())
110 Expect(affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms).To(HaveLen(2))
111
112 selector := affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0]
113 Expect(selector).ToNot(BeNil())
114 Expect(selector.MatchExpressions).To(HaveLen(1))
115 Expect(selector.MatchExpressions[0].Values).To(HaveLen(1))
116 Expect(selector.MatchExpressions[0].Values[0]).To(Equal("test-node"))
117
118 selector = affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[1]
119 Expect(selector).ToNot(BeNil())
120 Expect(selector.MatchExpressions).To(HaveLen(2))
121 Expect(selector.MatchExpressions[1].Values).To(HaveLen(1))
122 Expect(selector.MatchExpressions[1].Values[0]).To(Equal("test-node"))
123 })
124 })
125
126 Context("RunStrategy Rules", func() {
127 var vm = v1.VirtualMachine{}
128 BeforeEach(func() {
129 vm = v1.VirtualMachine{
130 TypeMeta: k8smetav1.TypeMeta{APIVersion: v1.GroupVersion.String(), Kind: "VirtualMachine"},
131 ObjectMeta: k8smetav1.ObjectMeta{Name: "testvm"}}
132 })
133
134 It("should fail if both Running and RunStrategy are defined", func() {
135 notRunning := false
136 runStrategy := v1.RunStrategyAlways
137 vm.Spec.Running = ¬Running
138 vm.Spec.RunStrategy = &runStrategy
139
140 _, err := vm.RunStrategy()
141 Expect(err).To(HaveOccurred())
142 })
143
144 It("should convert running=false to Halted", func() {
145 notRunning := false
146 vm.Spec.Running = ¬Running
147 vm.Spec.RunStrategy = nil
148
149 runStrategy, err := vm.RunStrategy()
150 Expect(err).ToNot(HaveOccurred())
151 Expect(runStrategy).To(Equal(v1.RunStrategyHalted))
152 })
153
154 It("should convert running=true to RunStrategyAlways", func() {
155 running := true
156 vm.Spec.Running = &running
157 vm.Spec.RunStrategy = nil
158
159 runStrategy, err := vm.RunStrategy()
160 Expect(err).ToNot(HaveOccurred())
161 Expect(runStrategy).To(Equal(v1.RunStrategyAlways))
162 })
163
164 DescribeTable("should return RunStrategy", func(runStrategy v1.VirtualMachineRunStrategy) {
165 vm.Spec.Running = nil
166 vm.Spec.RunStrategy = &runStrategy
167
168 newRunStrategy, err := vm.RunStrategy()
169 Expect(err).ToNot(HaveOccurred())
170 Expect(newRunStrategy).To(Equal(runStrategy))
171 },
172 Entry(string(v1.RunStrategyAlways), v1.RunStrategyAlways),
173 Entry(string(v1.RunStrategyHalted), v1.RunStrategyHalted),
174 Entry(string(v1.RunStrategyManual), v1.RunStrategyManual),
175 Entry(string(v1.RunStrategyRerunOnFailure), v1.RunStrategyRerunOnFailure),
176 )
177
178 It("should default to RunStrategyHalted", func() {
179 vm.Spec.Running = nil
180 vm.Spec.RunStrategy = nil
181
182 runStrategy, err := vm.RunStrategy()
183 Expect(err).ToNot(HaveOccurred())
184 Expect(runStrategy).To(Equal(v1.RunStrategyHalted))
185 })
186 })
187 })
188
View as plain text