diff --git a/pkg/kubelet/kubelet_pods_test.go b/pkg/kubelet/kubelet_pods_test.go index d93e1a9a2e2..94844df2101 100644 --- a/pkg/kubelet/kubelet_pods_test.go +++ b/pkg/kubelet/kubelet_pods_test.go @@ -1733,6 +1733,19 @@ func waitingStateWithLastTermination(cName string) v1.ContainerStatus { }, } } +func waitingStateWithNonZeroTermination(cName string) v1.ContainerStatus { + return v1.ContainerStatus{ + Name: cName, + State: v1.ContainerState{ + Waiting: &v1.ContainerStateWaiting{}, + }, + LastTerminationState: v1.ContainerState{ + Terminated: &v1.ContainerStateTerminated{ + ExitCode: -1, + }, + }, + } +} func runningState(cName string) v1.ContainerStatus { return v1.ContainerStatus{ Name: cName, @@ -1870,6 +1883,109 @@ func TestPodPhaseWithRestartAlways(t *testing.T) { } } +func TestPodPhaseWithRestartAlwaysInitContainers(t *testing.T) { + desiredState := v1.PodSpec{ + NodeName: "machine", + InitContainers: []v1.Container{ + {Name: "containerX"}, + }, + Containers: []v1.Container{ + {Name: "containerA"}, + {Name: "containerB"}, + }, + RestartPolicy: v1.RestartPolicyAlways, + } + + tests := []struct { + pod *v1.Pod + status v1.PodPhase + test string + }{ + {&v1.Pod{Spec: desiredState, Status: v1.PodStatus{}}, v1.PodPending, "empty, waiting"}, + { + &v1.Pod{ + Spec: desiredState, + Status: v1.PodStatus{ + InitContainerStatuses: []v1.ContainerStatus{ + runningState("containerX"), + }, + }, + }, + v1.PodPending, + "init container running", + }, + { + &v1.Pod{ + Spec: desiredState, + Status: v1.PodStatus{ + InitContainerStatuses: []v1.ContainerStatus{ + failedState("containerX"), + }, + }, + }, + v1.PodPending, + "init container terminated non-zero", + }, + { + &v1.Pod{ + Spec: desiredState, + Status: v1.PodStatus{ + InitContainerStatuses: []v1.ContainerStatus{ + waitingStateWithLastTermination("containerX"), + }, + }, + }, + v1.PodPending, + "init container waiting, terminated zero", + }, + { + &v1.Pod{ + Spec: desiredState, + Status: v1.PodStatus{ + InitContainerStatuses: []v1.ContainerStatus{ + waitingStateWithNonZeroTermination("containerX"), + }, + }, + }, + v1.PodPending, + "init container waiting, terminated non-zero", + }, + { + &v1.Pod{ + Spec: desiredState, + Status: v1.PodStatus{ + InitContainerStatuses: []v1.ContainerStatus{ + waitingState("containerX"), + }, + }, + }, + v1.PodPending, + "init container waiting, not terminated", + }, + { + &v1.Pod{ + Spec: desiredState, + Status: v1.PodStatus{ + InitContainerStatuses: []v1.ContainerStatus{ + succeededState("containerX"), + }, + ContainerStatuses: []v1.ContainerStatus{ + runningState("containerA"), + runningState("containerB"), + }, + }, + }, + v1.PodRunning, + "init container succeeded", + }, + } + for _, test := range tests { + statusInfo := append(test.pod.Status.InitContainerStatuses[:], test.pod.Status.ContainerStatuses[:]...) + status := getPhase(&test.pod.Spec, statusInfo) + assert.Equal(t, test.status, status, "[test %s]", test.test) + } +} + func TestPodPhaseWithRestartNever(t *testing.T) { desiredState := v1.PodSpec{ NodeName: "machine", @@ -1970,6 +2086,109 @@ func TestPodPhaseWithRestartNever(t *testing.T) { } } +func TestPodPhaseWithRestartNeverInitContainers(t *testing.T) { + desiredState := v1.PodSpec{ + NodeName: "machine", + InitContainers: []v1.Container{ + {Name: "containerX"}, + }, + Containers: []v1.Container{ + {Name: "containerA"}, + {Name: "containerB"}, + }, + RestartPolicy: v1.RestartPolicyNever, + } + + tests := []struct { + pod *v1.Pod + status v1.PodPhase + test string + }{ + {&v1.Pod{Spec: desiredState, Status: v1.PodStatus{}}, v1.PodPending, "empty, waiting"}, + { + &v1.Pod{ + Spec: desiredState, + Status: v1.PodStatus{ + InitContainerStatuses: []v1.ContainerStatus{ + runningState("containerX"), + }, + }, + }, + v1.PodPending, + "init container running", + }, + { + &v1.Pod{ + Spec: desiredState, + Status: v1.PodStatus{ + InitContainerStatuses: []v1.ContainerStatus{ + failedState("containerX"), + }, + }, + }, + v1.PodFailed, + "init container terminated non-zero", + }, + { + &v1.Pod{ + Spec: desiredState, + Status: v1.PodStatus{ + InitContainerStatuses: []v1.ContainerStatus{ + waitingStateWithLastTermination("containerX"), + }, + }, + }, + v1.PodPending, + "init container waiting, terminated zero", + }, + { + &v1.Pod{ + Spec: desiredState, + Status: v1.PodStatus{ + InitContainerStatuses: []v1.ContainerStatus{ + waitingStateWithNonZeroTermination("containerX"), + }, + }, + }, + v1.PodFailed, + "init container waiting, terminated non-zero", + }, + { + &v1.Pod{ + Spec: desiredState, + Status: v1.PodStatus{ + InitContainerStatuses: []v1.ContainerStatus{ + waitingState("containerX"), + }, + }, + }, + v1.PodPending, + "init container waiting, not terminated", + }, + { + &v1.Pod{ + Spec: desiredState, + Status: v1.PodStatus{ + InitContainerStatuses: []v1.ContainerStatus{ + succeededState("containerX"), + }, + ContainerStatuses: []v1.ContainerStatus{ + runningState("containerA"), + runningState("containerB"), + }, + }, + }, + v1.PodRunning, + "init container succeeded", + }, + } + for _, test := range tests { + statusInfo := append(test.pod.Status.InitContainerStatuses[:], test.pod.Status.ContainerStatuses[:]...) + status := getPhase(&test.pod.Spec, statusInfo) + assert.Equal(t, test.status, status, "[test %s]", test.test) + } +} + func TestPodPhaseWithRestartOnFailure(t *testing.T) { desiredState := v1.PodSpec{ NodeName: "machine", @@ -2083,6 +2302,10 @@ func TestPodPhaseWithRestartOnFailure(t *testing.T) { } } +// No special init-specific logic for this, see RestartAlways case +// func TestPodPhaseWithRestartOnFailureInitContainers(t *testing.T) { +// } + func TestGetExec(t *testing.T) { const ( podName = "podFoo"