1 package k8s
2
3 import (
4 "context"
5 "testing"
6
7 corev1 "k8s.io/api/core/v1"
8 )
9
10 func TestGetPodStatus(t *testing.T) {
11 scenarios := []struct {
12 desc string
13 pod string
14 expected string
15 }{
16 {
17 desc: "Pod is running",
18 expected: "Running",
19 pod: `
20 apiVersion: v1
21 kind: Pod
22 metadata:
23 name: emoji
24 namespace: emojivoto
25 labels:
26 app: emoji-svc
27 linkerd.io/control-plane-ns: linkerd
28 status:
29 phase: Running
30 `,
31 },
32 {
33 desc: "Pod with proxy native sidecar is running",
34 expected: "Running",
35 pod: `
36 apiVersion: v1
37 kind: Pod
38 metadata:
39 name: emoji
40 namespace: emojivoto
41 labels:
42 app: emoji-svc
43 linkerd.io/control-plane-ns: linkerd
44 spec:
45 initContainers:
46 - name: linkerd-proxy
47 restartPolicy: Always
48 status:
49 phase: Running
50 initContainerStatuses:
51 - name: linkerd-proxy
52 ready: true
53 started: true
54 `,
55 },
56 {
57 desc: "Pod's reason is filled",
58 expected: "podReason",
59 pod: `
60 apiVersion: v1
61 kind: Pod
62 metadata:
63 name: emoji
64 namespace: emojivoto
65 labels:
66 app: emoji-svc
67 linkerd.io/control-plane-ns: linkerd
68 status:
69 phase: Pending
70 reason: podReason
71 `,
72 },
73 {
74 desc: "Pod waiting is filled",
75 expected: "CrashLoopBackOff",
76 pod: `
77 apiVersion: v1
78 kind: Pod
79 metadata:
80 name: emoji
81 namespace: emojivoto
82 labels:
83 app: emoji-svc
84 linkerd.io/control-plane-ns: linkerd
85 status:
86 phase: Pending
87 reason: podReason
88 containerStatuses:
89 - state:
90 waiting:
91 reason: CrashLoopBackOff
92 `,
93 },
94 {
95 desc: "Pod is terminated",
96 expected: "podTerminated",
97 pod: `
98 apiVersion: v1
99 kind: Pod
100 metadata:
101 name: emoji
102 namespace: emojivoto
103 labels:
104 app: emoji-svc
105 linkerd.io/control-plane-ns: linkerd
106 status:
107 phase: Pending
108 reason: podReason
109 containerStatuses:
110 - state:
111 terminated:
112 reason: podTerminated
113 exitCode: 2
114 `,
115 },
116 {
117 desc: "Pod terminated with signal",
118 expected: "Signal:9",
119 pod: `
120 apiVersion: v1
121 kind: Pod
122 metadata:
123 name: emoji
124 namespace: emojivoto
125 labels:
126 app: emoji-svc
127 linkerd.io/control-plane-ns: linkerd
128 status:
129 phase: Pending
130 reason: podReason
131 containerStatuses:
132 - state:
133 terminated:
134 signal: 9
135 `,
136 },
137 {
138 desc: "Pod terminated with exti code",
139 expected: "ExitCode:2",
140 pod: `
141 apiVersion: v1
142 kind: Pod
143 metadata:
144 name: emoji
145 namespace: emojivoto
146 labels:
147 app: emoji-svc
148 linkerd.io/control-plane-ns: linkerd
149 status:
150 phase: Pending
151 reason: podReason
152 containerStatuses:
153 - state:
154 terminated:
155 exitCode: 2
156 `,
157 },
158 {
159 desc: "Pod has a running container",
160 expected: "Running",
161 pod: `
162 apiVersion: v1
163 kind: Pod
164 metadata:
165 name: emoji
166 namespace: emojivoto
167 labels:
168 app: emoji-svc
169 linkerd.io/control-plane-ns: linkerd
170 status:
171 phase: Running
172 reason: Completed
173 containerStatuses:
174 - ready: true
175 state:
176 running:
177 startedAt: 1995-02-10T00:42:42Z
178 `,
179 },
180 {
181 desc: "Pod init container terminated with exit code 0",
182 expected: "Running",
183 pod: `
184 apiVersion: v1
185 kind: Pod
186 metadata:
187 name: emoji
188 namespace: emojivoto
189 labels:
190 app: emoji-svc
191 linkerd.io/control-plane-ns: linkerd
192 spec:
193 initContainers:
194 - name: foo
195 status:
196 phase: Running
197 containerStatuses:
198 - state:
199 running:
200 startedAt: 1995-02-10T00:42:42Z
201 initContainerStatuses:
202 - name: foo
203 state:
204 terminated:
205 exitCode: 0
206 reason: Completed
207 `,
208 },
209 {
210 desc: "Pod init container terminated with exit code 2",
211 expected: "Init:ExitCode:2",
212 pod: `
213 apiVersion: v1
214 kind: Pod
215 metadata:
216 name: emoji
217 namespace: emojivoto
218 labels:
219 app: emoji-svc
220 linkerd.io/control-plane-ns: linkerd
221 spec:
222 initContainers:
223 - name: foo
224 containers:
225 - name: bar
226 status:
227 phase: Running
228 containerStatuses:
229 - name: bar
230 state:
231 running:
232 startedAt: 1995-02-10T00:42:42Z
233 initContainerStatuses:
234 - name: foo
235 state:
236 terminated:
237 exitCode: 2
238 `,
239 },
240 {
241 desc: "Pod init container terminated with signal",
242 expected: "Init:Signal:9",
243 pod: `
244 apiVersion: v1
245 kind: Pod
246 metadata:
247 name: emoji
248 namespace: emojivoto
249 labels:
250 app: emoji-svc
251 linkerd.io/control-plane-ns: linkerd
252 spec:
253 initContainers:
254 - name: foo
255 containers:
256 - name: bar
257 status:
258 phase: Running
259 containerStatuses:
260 - name: bar
261 state:
262 running:
263 startedAt: 1995-02-10T00:42:42Z
264 initContainerStatuses:
265 - name: foo
266 state:
267 terminated:
268 signal: 9
269 `,
270 },
271 {
272 desc: "Pod init container in CrashLooBackOff",
273 expected: "Init:CrashLoopBackOff",
274 pod: `
275 apiVersion: v1
276 kind: Pod
277 metadata:
278 name: emoji
279 namespace: emojivoto
280 labels:
281 app: emoji-svc
282 linkerd.io/control-plane-ns: linkerd
283 spec:
284 initContainers:
285 - name: foo
286 status:
287 phase: Pending
288 initContainerStatuses:
289 - name: foo
290 state:
291 terminated:
292 exitCode: 2
293 reason: CrashLoopBackOff
294 `,
295 },
296 {
297 desc: "Pod init container waiting for someReason",
298 expected: "Init:someReason",
299 pod: `
300 apiVersion: v1
301 kind: Pod
302 metadata:
303 name: emoji
304 namespace: emojivoto
305 labels:
306 app: emoji-svc
307 linkerd.io/control-plane-ns: linkerd
308 spec:
309 initContainers:
310 - name: foo
311 status:
312 phase: Pending
313 initContainerStatuses:
314 - name: foo
315 state:
316 waiting:
317 reason: someReason
318 `,
319 },
320 {
321 desc: "Pod init container is waiting on PodInitializing",
322 expected: "Init:0/1",
323 pod: `
324 apiVersion: v1
325 kind: Pod
326 metadata:
327 name: emoji
328 namespace: emojivoto
329 labels:
330 app: emoji-svc
331 linkerd.io/control-plane-ns: linkerd
332 spec:
333 initContainers:
334 - name: foo
335 status:
336 phase: Pending
337 initContainerStatuses:
338 - name: foo
339 state:
340 waiting:
341 reason: PodInitializing
342 `,
343 },
344 }
345 for _, s := range scenarios {
346 obj, err := ToRuntimeObject(s.pod)
347 if err != nil {
348 t.Fatalf("could not decode yml: %s", err)
349 }
350 pod, ok := obj.(*corev1.Pod)
351 if !ok {
352 t.Fatalf("could not convert returned object to pod")
353 }
354
355 got := GetPodStatus(*pod)
356 if s.expected != got {
357 t.Fatalf("Wrong pod status on '%s'. Expected '%s', got '%s'", s.desc, s.expected, got)
358 }
359 }
360 }
361
362 func TestGetPodsFor(t *testing.T) {
363
364 configs := []string{
365
366 `apiVersion: v1
367 kind: Pod
368 metadata:
369 name: pod-1
370 namespace: ns
371 uid: pod-1
372 labels:
373 app: foo
374 ownerReferences:
375 - apiVersion: apps/v1
376 controller: true
377 kind: ReplicaSet
378 name: rs-1
379 uid: rs-1
380 `,
381
382 `apiVersion: apps/v1
383 kind: ReplicaSet
384 metadata:
385 name: rs-1
386 namespace: ns
387 uid: rs-1
388 labels:
389 app: foo
390 ownerReferences:
391 - apiVersion: apps/v1
392 controller: true
393 kind: Deployment
394 name: deploy-1
395 uid: deploy-1
396 spec:
397 selector:
398 matchLabels:
399 app: foo
400 `,
401
402 `apiVersion: apps/v1
403 kind: Deployment
404 metadata:
405 name: deploy-1
406 namespace: ns
407 uid: deploy-1
408 spec:
409 selector:
410 matchLabels:
411 app: foo
412 `,
413
414 `apiVersion: v1
415 kind: Pod
416 metadata:
417 name: pod-2
418 namespace: ns
419 uid: pod-2
420 labels:
421 app: foo
422 ownerReferences:
423 - apiVersion: apps/v1
424 controller: true
425 kind: ReplicaSet
426 name: rs-2
427 uid: rs-2
428 `,
429
430 `apiVersion: apps/v1
431 kind: ReplicaSet
432 metadata:
433 name: rs-2
434 namespace: ns
435 uid: rs-2
436 labels:
437 app: foo
438 ownerReferences:
439 - apiVersion: apps/v1
440 controller: true
441 kind: Deployment
442 name: deploy-2
443 uid: deploy-2
444 spec:
445 selector:
446 matchLabels:
447 app: foo
448 `,
449
450 `apiVersion: apps/v1
451 kind: Deployment
452 metadata:
453 name: deploy-2
454 namespace: ns
455 uid: deploy-2
456 spec:
457 selector:
458 matchLabels:
459 app: foo
460 `}
461
462 k8sClient, err := NewFakeAPI(configs...)
463 if err != nil {
464 t.Fatalf("Unexpected error %s", err)
465 }
466
467
468
469
470
471 pods, err := GetPodsFor(context.Background(), k8sClient, "ns", "deploy/deploy-1")
472 if err != nil {
473 t.Fatalf("Unexpected error %s", err)
474 }
475
476 if len(pods) != 1 {
477 for _, p := range pods {
478 t.Logf("%s/%s", p.Namespace, p.Name)
479 }
480 t.Fatalf("Expected 1 pod, got %d", len(pods))
481 }
482 }
483
View as plain text