diff --git a/pkg/analyze/cluster_pod_statuses.go b/pkg/analyze/cluster_pod_statuses.go index d8657548..3d3d8b25 100644 --- a/pkg/analyze/cluster_pod_statuses.go +++ b/pkg/analyze/cluster_pod_statuses.go @@ -22,7 +22,7 @@ func clusterPodStatuses(analyzer *troubleshootv1beta2.ClusterPodStatuses, getChi var pods []corev1.Pod for fileName, fileContent := range collected { - podsNs := strings.TrimSuffix(fileName, ".json") + podsNs := strings.TrimSuffix(filepath.Base(fileName), ".json") include := len(analyzer.Namespaces) == 0 for _, ns := range analyzer.Namespaces { if ns == podsNs { @@ -33,9 +33,14 @@ func clusterPodStatuses(analyzer *troubleshootv1beta2.ClusterPodStatuses, getChi if include { var nsPods corev1.PodList if err := json.Unmarshal(fileContent, &nsPods); err != nil { - return nil, errors.Wrapf(err, "failed to unmarshal pods list for namespace %s", podsNs) + var nsPodsArr []corev1.Pod + if err := json.Unmarshal(fileContent, &nsPodsArr); err != nil { + return nil, errors.Wrapf(err, "failed to unmarshal pods list for namespace %s", podsNs) + } + pods = append(pods, nsPodsArr...) + } else { + pods = append(pods, nsPods.Items...) } - pods = append(pods, nsPods.Items...) } } diff --git a/pkg/k8sutil/pod.go b/pkg/k8sutil/pod.go index 98a6fc0f..068e3a52 100644 --- a/pkg/k8sutil/pod.go +++ b/pkg/k8sutil/pod.go @@ -114,13 +114,20 @@ func IsPodUnhealthy(pod *corev1.Pod) bool { } reason := GetPodStatusReason(pod) - - switch PodStatusReason(reason) { - case PodStatusReasonRunning: - fallthrough - case PodStatusReasonCompleted: - return false + if PodStatusReason(reason) == PodStatusReasonCompleted { + return false // completed pods are healthy pods } - return true + if PodStatusReason(reason) != PodStatusReasonRunning { + return true // pods that are not completed or running are unhealthy + } + + // running pods with unready containers are not healthy + for _, containerStatus := range pod.Status.ContainerStatuses { + if !containerStatus.Ready { + return true + } + } + + return false } diff --git a/pkg/k8sutil/pod_test.go b/pkg/k8sutil/pod_test.go new file mode 100644 index 00000000..e7c9a9bb --- /dev/null +++ b/pkg/k8sutil/pod_test.go @@ -0,0 +1,101 @@ +package k8sutil + +import ( + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + "testing" +) + +func TestIsPodUnhealthy(t *testing.T) { + andTrue := true + tests := []struct { + name string + pod *corev1.Pod + want bool + }{ + { + name: "healthy pod with init containers", + want: false, + pod: &corev1.Pod{ + Status: corev1.PodStatus{ + Phase: "Running", + Conditions: []corev1.PodCondition{ + // ignored here + }, + InitContainerStatuses: []corev1.ContainerStatus{ + { + Name: "init", + State: corev1.ContainerState{ + Terminated: &corev1.ContainerStateTerminated{ + ExitCode: 0, + Reason: "Completed", + }, + }, + Ready: true, + RestartCount: 2, + Image: "projectcontour/contour:v1.11.0", + ImageID: "docker://sha256:12878e02b6f969de1456b51b0093f289fd195db956837ccd75aa679e9dac24d9", + ContainerID: "docker://50fc0794fa1402b1a48521e2fd380a92521a69db70ad25c9699c91fccd839d70", + }, + }, + ContainerStatuses: []corev1.ContainerStatus{ + { + Name: "contour", + State: corev1.ContainerState{ + Running: &corev1.ContainerStateRunning{}, + }, + Ready: true, + RestartCount: 5, + Image: "projectcontour/contour:v1.11.0", + ImageID: "docker://sha256:12878e02b6f969de1456b51b0093f289fd195db956837ccd75aa679e9dac24d9", + ContainerID: "docker://50fc0794fa1402b1a48521e2fd380a92521a69db70ad25c9699c91fccd839d70", + Started: &andTrue, + }, + }, + QOSClass: corev1.PodQOSBestEffort, + }, + }, + }, + { + name: "running pod with one unhealthy container", + want: true, + pod: &corev1.Pod{ + Status: corev1.PodStatus{ + Phase: "Running", + Conditions: []corev1.PodCondition{ + // ignored here + }, + ContainerStatuses: []corev1.ContainerStatus{ + { + Name: "envoy", + State: corev1.ContainerState{ + Running: &corev1.ContainerStateRunning{}, + }, + Ready: false, + RestartCount: 5, + Started: &andTrue, + }, + { + Name: "shutdown-manager", + State: corev1.ContainerState{ + Running: &corev1.ContainerStateRunning{}, + }, + Ready: true, + RestartCount: 5, + Started: &andTrue, + }, + }, + QOSClass: corev1.PodQOSBestEffort, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + req := require.New(t) + + got := IsPodUnhealthy(tt.pod) + req.Equal(tt.want, got) + }) + } +}