11package debug
22
33import (
4+ "errors"
45 "testing"
56
67 corev1 "k8s.io/api/core/v1"
@@ -10,6 +11,7 @@ import (
1011 "k8s.io/kubectl/pkg/cmd/attach"
1112 "k8s.io/kubectl/pkg/cmd/exec"
1213 "k8s.io/pod-security-admission/api"
14+ utilexec "k8s.io/utils/exec"
1315
1416 fakekubeclient "k8s.io/client-go/kubernetes/fake"
1517 fakecorev1client "k8s.io/client-go/kubernetes/typed/core/v1/fake"
@@ -266,3 +268,209 @@ func TestCreateLabelMap(t *testing.T) {
266268 })
267269 }
268270}
271+
272+ func TestContainerExitCode (t * testing.T ) {
273+ tests := []struct {
274+ name string
275+ pod * corev1.Pod
276+ containerName string
277+ expectedExitCode int32
278+ }{
279+ {
280+ name : "terminated with non-zero exit code" ,
281+ pod : & corev1.Pod {
282+ Status : corev1.PodStatus {
283+ ContainerStatuses : []corev1.ContainerStatus {
284+ {
285+ Name : "debug" ,
286+ State : corev1.ContainerState {Terminated : & corev1.ContainerStateTerminated {ExitCode : 42 }},
287+ },
288+ },
289+ },
290+ },
291+ containerName : "debug" ,
292+ expectedExitCode : 42 ,
293+ },
294+ {
295+ name : "terminated with exit code 0" ,
296+ pod : & corev1.Pod {
297+ Status : corev1.PodStatus {
298+ ContainerStatuses : []corev1.ContainerStatus {
299+ {
300+ Name : "debug" ,
301+ State : corev1.ContainerState {Terminated : & corev1.ContainerStateTerminated {ExitCode : 0 }},
302+ },
303+ },
304+ },
305+ },
306+ containerName : "debug" ,
307+ expectedExitCode : 0 ,
308+ },
309+ {
310+ name : "container still running" ,
311+ pod : & corev1.Pod {
312+ Status : corev1.PodStatus {
313+ ContainerStatuses : []corev1.ContainerStatus {
314+ {
315+ Name : "debug" ,
316+ State : corev1.ContainerState {Running : & corev1.ContainerStateRunning {}},
317+ },
318+ },
319+ },
320+ },
321+ containerName : "debug" ,
322+ expectedExitCode : - 1 ,
323+ },
324+ {
325+ name : "container not found" ,
326+ pod : & corev1.Pod {
327+ Status : corev1.PodStatus {
328+ ContainerStatuses : []corev1.ContainerStatus {
329+ {
330+ Name : "other" ,
331+ State : corev1.ContainerState {Terminated : & corev1.ContainerStateTerminated {ExitCode : 1 }},
332+ },
333+ },
334+ },
335+ },
336+ containerName : "debug" ,
337+ expectedExitCode : - 1 ,
338+ },
339+ {
340+ name : "init container terminated with non-zero exit code" ,
341+ pod : & corev1.Pod {
342+ Status : corev1.PodStatus {
343+ InitContainerStatuses : []corev1.ContainerStatus {
344+ {
345+ Name : "init" ,
346+ State : corev1.ContainerState {Terminated : & corev1.ContainerStateTerminated {ExitCode : 137 }},
347+ },
348+ },
349+ },
350+ },
351+ containerName : "init" ,
352+ expectedExitCode : 137 ,
353+ },
354+ {
355+ name : "empty pod status" ,
356+ pod : & corev1.Pod {},
357+ containerName : "debug" ,
358+ expectedExitCode : - 1 ,
359+ },
360+ }
361+
362+ for _ , tt := range tests {
363+ t .Run (tt .name , func (t * testing.T ) {
364+ got := containerExitCode (tt .pod , tt .containerName )
365+ if got != tt .expectedExitCode {
366+ t .Errorf ("containerExitCode() = %d, want %d" , got , tt .expectedExitCode )
367+ }
368+ })
369+ }
370+ }
371+
372+ func TestExitCodeError (t * testing.T ) {
373+ tests := []struct {
374+ name string
375+ pod * corev1.Pod
376+ containerName string
377+ // expectedExitCode 0 is used to expect exitCodeError to return nil.
378+ expectedExitCode int
379+ }{
380+ {
381+ name : "non-zero exit code returns CodeExitError" ,
382+ pod : & corev1.Pod {
383+ Status : corev1.PodStatus {
384+ ContainerStatuses : []corev1.ContainerStatus {
385+ {
386+ Name : "debug" ,
387+ State : corev1.ContainerState {Terminated : & corev1.ContainerStateTerminated {ExitCode : 42 }},
388+ },
389+ },
390+ },
391+ },
392+ containerName : "debug" ,
393+ expectedExitCode : 42 ,
394+ },
395+ {
396+ name : "exit code 0 returns nil" ,
397+ pod : & corev1.Pod {
398+ Status : corev1.PodStatus {
399+ ContainerStatuses : []corev1.ContainerStatus {
400+ {
401+ Name : "debug" ,
402+ State : corev1.ContainerState {Terminated : & corev1.ContainerStateTerminated {ExitCode : 0 }},
403+ },
404+ },
405+ },
406+ },
407+ containerName : "debug" ,
408+ expectedExitCode : 0 ,
409+ },
410+ {
411+ name : "container not terminated returns nil" ,
412+ pod : & corev1.Pod {
413+ Status : corev1.PodStatus {
414+ ContainerStatuses : []corev1.ContainerStatus {
415+ {
416+ Name : "debug" ,
417+ State : corev1.ContainerState {Running : & corev1.ContainerStateRunning {}},
418+ },
419+ },
420+ },
421+ },
422+ containerName : "debug" ,
423+ expectedExitCode : 0 ,
424+ },
425+ {
426+ name : "container not found returns nil" ,
427+ pod : & corev1.Pod {
428+ Status : corev1.PodStatus {
429+ ContainerStatuses : []corev1.ContainerStatus {
430+ {
431+ Name : "other" ,
432+ State : corev1.ContainerState {Terminated : & corev1.ContainerStateTerminated {ExitCode : 1 }},
433+ },
434+ },
435+ },
436+ },
437+ containerName : "debug" ,
438+ expectedExitCode : 0 ,
439+ },
440+ {
441+ name : "exit code 127 returns correct code" ,
442+ pod : & corev1.Pod {
443+ Status : corev1.PodStatus {
444+ ContainerStatuses : []corev1.ContainerStatus {
445+ {
446+ Name : "debug" ,
447+ State : corev1.ContainerState {Terminated : & corev1.ContainerStateTerminated {ExitCode : 127 }},
448+ },
449+ },
450+ },
451+ },
452+ containerName : "debug" ,
453+ expectedExitCode : 127 ,
454+ },
455+ }
456+
457+ for _ , tt := range tests {
458+ t .Run (tt .name , func (t * testing.T ) {
459+ err := exitCodeError (tt .pod , tt .containerName )
460+ if tt .expectedExitCode == 0 {
461+ if err != nil {
462+ t .Errorf ("expected nil, got %v" , err )
463+ }
464+ return
465+ }
466+
467+ var exitErr utilexec.CodeExitError
468+ if ! errors .As (err , & exitErr ) {
469+ t .Fatalf ("expected utilexec.CodeExitError, got %T: %v" , err , err )
470+ }
471+ if exitErr .ExitStatus () != tt .expectedExitCode {
472+ t .Errorf ("ExitStatus() = %d, want %d" , exitErr .ExitStatus (), tt .expectedExitCode )
473+ }
474+ })
475+ }
476+ }
0 commit comments