1
16
17 package extendedresourcetoleration
18
19 import (
20 "context"
21 "testing"
22
23 "k8s.io/apimachinery/pkg/api/resource"
24 "k8s.io/apiserver/pkg/admission"
25 admissiontesting "k8s.io/apiserver/pkg/admission/testing"
26 "k8s.io/kubernetes/pkg/apis/core"
27 "k8s.io/kubernetes/pkg/apis/core/helper"
28 )
29
30 func TestAdmit(t *testing.T) {
31
32 plugin := admissiontesting.WithReinvocationTesting(t, newExtendedResourceToleration())
33
34 containerRequestingCPU := core.Container{
35 Resources: core.ResourceRequirements{
36 Requests: core.ResourceList{
37 core.ResourceCPU: *resource.NewQuantity(2, resource.DecimalSI),
38 },
39 },
40 }
41
42 containerRequestingMemory := core.Container{
43 Resources: core.ResourceRequirements{
44 Requests: core.ResourceList{
45 core.ResourceMemory: *resource.NewQuantity(2048, resource.DecimalSI),
46 },
47 },
48 }
49
50 extendedResource1 := "example.com/device-ek"
51 extendedResource2 := "example.com/device-do"
52
53 containerRequestingExtendedResource1 := core.Container{
54 Resources: core.ResourceRequirements{
55 Requests: core.ResourceList{
56 core.ResourceName(extendedResource1): *resource.NewQuantity(1, resource.DecimalSI),
57 },
58 },
59 }
60 containerRequestingExtendedResource2 := core.Container{
61 Resources: core.ResourceRequirements{
62 Requests: core.ResourceList{
63 core.ResourceName(extendedResource2): *resource.NewQuantity(2, resource.DecimalSI),
64 },
65 },
66 }
67
68 tests := []struct {
69 description string
70 requestedPod core.Pod
71 expectedPod core.Pod
72 }{
73 {
74 description: "empty pod without any extended resources, expect no change in tolerations",
75 requestedPod: core.Pod{
76 Spec: core.PodSpec{},
77 },
78 expectedPod: core.Pod{
79 Spec: core.PodSpec{},
80 },
81 },
82 {
83 description: "pod with container without any extended resources, expect no change in tolerations",
84 requestedPod: core.Pod{
85 Spec: core.PodSpec{
86 Containers: []core.Container{
87 containerRequestingCPU,
88 },
89 },
90 },
91 expectedPod: core.Pod{
92 Spec: core.PodSpec{
93 Containers: []core.Container{
94 containerRequestingCPU,
95 },
96 },
97 },
98 },
99 {
100 description: "pod with init container without any extended resources, expect no change in tolerations",
101 requestedPod: core.Pod{
102 Spec: core.PodSpec{
103 InitContainers: []core.Container{
104 containerRequestingMemory,
105 },
106 },
107 },
108 expectedPod: core.Pod{
109 Spec: core.PodSpec{
110 InitContainers: []core.Container{
111 containerRequestingMemory,
112 },
113 },
114 },
115 },
116 {
117 description: "pod with container with extended resource, expect toleration to be added",
118 requestedPod: core.Pod{
119 Spec: core.PodSpec{
120 Containers: []core.Container{
121 containerRequestingExtendedResource1,
122 },
123 },
124 },
125 expectedPod: core.Pod{
126 Spec: core.PodSpec{
127 Containers: []core.Container{
128 containerRequestingExtendedResource1,
129 },
130 Tolerations: []core.Toleration{
131 {
132 Key: extendedResource1,
133 Operator: core.TolerationOpExists,
134 Effect: core.TaintEffectNoSchedule,
135 },
136 },
137 },
138 },
139 },
140 {
141 description: "pod with init container with extended resource, expect toleration to be added",
142 requestedPod: core.Pod{
143 Spec: core.PodSpec{
144 InitContainers: []core.Container{
145 containerRequestingExtendedResource2,
146 },
147 },
148 },
149 expectedPod: core.Pod{
150 Spec: core.PodSpec{
151 InitContainers: []core.Container{
152 containerRequestingExtendedResource2,
153 },
154 Tolerations: []core.Toleration{
155 {
156 Key: extendedResource2,
157 Operator: core.TolerationOpExists,
158 Effect: core.TaintEffectNoSchedule,
159 },
160 },
161 },
162 },
163 },
164 {
165 description: "pod with existing tolerations and container with extended resource, expect existing tolerations to be preserved and new toleration to be added",
166 requestedPod: core.Pod{
167 Spec: core.PodSpec{
168 Containers: []core.Container{
169 containerRequestingCPU,
170 containerRequestingExtendedResource1,
171 },
172 Tolerations: []core.Toleration{
173 {
174 Key: "foo",
175 Operator: core.TolerationOpEqual,
176 Value: "bar",
177 Effect: core.TaintEffectNoSchedule,
178 },
179 },
180 },
181 },
182 expectedPod: core.Pod{
183 Spec: core.PodSpec{
184 Containers: []core.Container{
185 containerRequestingCPU,
186 containerRequestingExtendedResource1,
187 },
188 Tolerations: []core.Toleration{
189 {
190 Key: "foo",
191 Operator: core.TolerationOpEqual,
192 Value: "bar",
193 Effect: core.TaintEffectNoSchedule,
194 },
195 {
196 Key: extendedResource1,
197 Operator: core.TolerationOpExists,
198 Effect: core.TaintEffectNoSchedule,
199 },
200 },
201 },
202 },
203 },
204 {
205 description: "pod with multiple extended resources, expect multiple tolerations to be added",
206 requestedPod: core.Pod{
207 Spec: core.PodSpec{
208 Containers: []core.Container{
209 containerRequestingMemory,
210 containerRequestingExtendedResource1,
211 },
212 InitContainers: []core.Container{
213 containerRequestingCPU,
214 containerRequestingExtendedResource2,
215 },
216 },
217 },
218 expectedPod: core.Pod{
219 Spec: core.PodSpec{
220 Containers: []core.Container{
221 containerRequestingMemory,
222 containerRequestingExtendedResource1,
223 },
224 InitContainers: []core.Container{
225 containerRequestingCPU,
226 containerRequestingExtendedResource2,
227 },
228 Tolerations: []core.Toleration{
229
230 {
231 Key: extendedResource2,
232 Operator: core.TolerationOpExists,
233 Effect: core.TaintEffectNoSchedule,
234 },
235 {
236 Key: extendedResource1,
237 Operator: core.TolerationOpExists,
238 Effect: core.TaintEffectNoSchedule,
239 },
240 },
241 },
242 },
243 },
244 {
245 description: "pod with container requesting extended resource and existing correct toleration, expect no change in tolerations",
246 requestedPod: core.Pod{
247 Spec: core.PodSpec{
248 Containers: []core.Container{
249 containerRequestingCPU,
250 containerRequestingMemory,
251 containerRequestingExtendedResource1,
252 },
253 Tolerations: []core.Toleration{
254 {
255 Key: extendedResource1,
256 Operator: core.TolerationOpExists,
257 Effect: core.TaintEffectNoSchedule,
258 },
259 },
260 },
261 },
262 expectedPod: core.Pod{
263 Spec: core.PodSpec{
264 Containers: []core.Container{
265 containerRequestingCPU,
266 containerRequestingMemory,
267 containerRequestingExtendedResource1,
268 },
269 Tolerations: []core.Toleration{
270 {
271 Key: extendedResource1,
272 Operator: core.TolerationOpExists,
273 Effect: core.TaintEffectNoSchedule,
274 },
275 },
276 },
277 },
278 },
279 {
280 description: "pod with container requesting extended resource and existing toleration with the same key but different effect and value, expect existing tolerations to be preserved and new toleration to be added",
281 requestedPod: core.Pod{
282 Spec: core.PodSpec{
283 Containers: []core.Container{
284 containerRequestingCPU,
285 containerRequestingMemory,
286 containerRequestingExtendedResource1,
287 },
288 Tolerations: []core.Toleration{
289 {
290 Key: extendedResource1,
291 Operator: core.TolerationOpEqual,
292 Value: "foo",
293 Effect: core.TaintEffectNoExecute,
294 },
295 },
296 },
297 },
298 expectedPod: core.Pod{
299 Spec: core.PodSpec{
300 Containers: []core.Container{
301 containerRequestingCPU,
302 containerRequestingMemory,
303 containerRequestingExtendedResource1,
304 },
305 Tolerations: []core.Toleration{
306 {
307 Key: extendedResource1,
308 Operator: core.TolerationOpEqual,
309 Value: "foo",
310 Effect: core.TaintEffectNoExecute,
311 },
312 {
313 Key: extendedResource1,
314 Operator: core.TolerationOpExists,
315 Effect: core.TaintEffectNoSchedule,
316 },
317 },
318 },
319 },
320 },
321 {
322 description: "pod with wildcard toleration and container requesting extended resource, expect existing tolerations to be preserved and new toleration to be added",
323 requestedPod: core.Pod{
324 Spec: core.PodSpec{
325 Containers: []core.Container{
326 containerRequestingCPU,
327 containerRequestingMemory,
328 containerRequestingExtendedResource1,
329 },
330 Tolerations: []core.Toleration{
331 {
332 Operator: core.TolerationOpExists,
333 },
334 },
335 },
336 },
337 expectedPod: core.Pod{
338 Spec: core.PodSpec{
339 Containers: []core.Container{
340 containerRequestingCPU,
341 containerRequestingMemory,
342 containerRequestingExtendedResource1,
343 },
344 Tolerations: []core.Toleration{
345 {
346 Operator: core.TolerationOpExists,
347 },
348 {
349 Key: extendedResource1,
350 Operator: core.TolerationOpExists,
351 Effect: core.TaintEffectNoSchedule,
352 },
353 },
354 },
355 },
356 },
357 }
358 for i, test := range tests {
359 err := plugin.Admit(context.TODO(), admission.NewAttributesRecord(&test.requestedPod, nil, core.Kind("Pod").WithVersion("version"), "foo", "name", core.Resource("pods").WithVersion("version"), "", "ignored", nil, false, nil), nil)
360 if err != nil {
361 t.Errorf("[%d: %s] unexpected error %v for pod %+v", i, test.description, err, test.requestedPod)
362 }
363
364 if !helper.Semantic.DeepEqual(test.expectedPod.Spec.Tolerations, test.requestedPod.Spec.Tolerations) {
365 t.Errorf("[%d: %s] expected %#v got %#v", i, test.description, test.expectedPod.Spec.Tolerations, test.requestedPod.Spec.Tolerations)
366 }
367 }
368 }
369
370 func TestHandles(t *testing.T) {
371 plugin := newExtendedResourceToleration()
372 tests := map[admission.Operation]bool{
373 admission.Create: true,
374 admission.Update: true,
375 admission.Delete: false,
376 admission.Connect: false,
377 }
378 for op, expected := range tests {
379 result := plugin.Handles(op)
380 if result != expected {
381 t.Errorf("Unexpected result for operation %s: %v\n", op, result)
382 }
383 }
384 }
385
View as plain text