diff --git a/server/apis/v1/handler.go b/server/apis/v1/handler.go index f74ad7e7a..13d611dbc 100644 --- a/server/apis/v1/handler.go +++ b/server/apis/v1/handler.go @@ -1643,8 +1643,16 @@ func (h *handler) getPodDetails(pod corev1.Pod) (PodDetails, error) { } func (h *handler) getContainerDetails(pod corev1.Pod) map[string]ContainerDetails { - var containerDetailsMap = make(map[string]ContainerDetails) - for _, status := range pod.Status.ContainerStatuses { + totalContainers := len(pod.Spec.Containers) + len(pod.Spec.InitContainers) + containerDetailsMap := make(map[string]ContainerDetails, totalContainers) + + // Helper function to process container statuses + processContainerStatus := func(status corev1.ContainerStatus, isInitContainer bool) { + // Skip init containers without Always restart policy + if isInitContainer && h.isNotSidecarContainer(status.Name, pod) { + return + } + containerName := status.Name details := ContainerDetails{ Name: status.Name, @@ -1666,13 +1674,25 @@ func (h *handler) getContainerDetails(pod corev1.Pod) map[string]ContainerDetail containerDetailsMap[containerName] = details } - // Get CPU/Memory requests and limits from Pod spec - for _, container := range pod.Spec.Containers { + for _, status := range pod.Status.InitContainerStatuses { + processContainerStatus(status, true) + } + for _, status := range pod.Status.ContainerStatuses { + processContainerStatus(status, false) + } + + // Helper function to process container resources + processContainerResources := func(container corev1.Container, isInitContainer bool) { + // Skip init containers without Always restart policy + if isInitContainer && h.isNotSidecarContainer(container.Name, pod) { + return + } + cpuRequest := container.Resources.Requests.Cpu().MilliValue() memRequest := container.Resources.Requests.Memory().Value() / (1024 * 1024) cpuLimit := container.Resources.Limits.Cpu().MilliValue() memLimit := container.Resources.Limits.Memory().Value() / (1024 * 1024) - // Get the existing ContainerDetails or create a new one + details, ok := containerDetailsMap[container.Name] if !ok { details = ContainerDetails{Name: container.Name} // Initialize if not found @@ -1691,9 +1711,28 @@ func (h *handler) getContainerDetails(pod corev1.Pod) map[string]ContainerDetail } containerDetailsMap[container.Name] = details } + + for _, container := range pod.Spec.InitContainers { + processContainerResources(container, true) + } + for _, container := range pod.Spec.Containers { + processContainerResources(container, false) + } + return containerDetailsMap } +// Helper function to check if container is an init container without "Always" restart policy +// for sidecar containers (eg: ud containers), we set "Always" restart policy in k8s >= 1.29 +func (h *handler) isNotSidecarContainer(containerName string, pod corev1.Pod) bool { + for _, initContainer := range pod.Spec.InitContainers { + if initContainer.Name == containerName { + return initContainer.RestartPolicy == nil || *initContainer.RestartPolicy != corev1.ContainerRestartPolicyAlways + } + } + return true +} + func (h *handler) getContainerStatus(state corev1.ContainerState) string { if state.Running != nil { return "Running" diff --git a/server/apis/v1/handler_test.go b/server/apis/v1/handler_test.go index aeae24d8a..9e716f344 100644 --- a/server/apis/v1/handler_test.go +++ b/server/apis/v1/handler_test.go @@ -1028,3 +1028,66 @@ func TestHandler_GetContainerStatus(t *testing.T) { }) } } + +func TestHandler_IsNotSidecarContainer(t *testing.T) { + handler := &handler{} + + tests := []struct { + name string + containerName string + pod corev1.Pod + expected bool + }{ + { + name: "Init container with Always restart policy", + containerName: "init-container-1", + pod: corev1.Pod{ + Spec: corev1.PodSpec{ + InitContainers: []corev1.Container{ + { + Name: "init-container-1", + RestartPolicy: func() *corev1.ContainerRestartPolicy { p := corev1.ContainerRestartPolicyAlways; return &p }(), + }, + }, + }, + }, + expected: false, + }, + { + name: "Container not in init containers", + containerName: "app-container", + pod: corev1.Pod{ + Spec: corev1.PodSpec{ + InitContainers: []corev1.Container{ + { + Name: "init-container-1", + }, + }, + }, + }, + expected: true, + }, + { + name: "Init container with nil RestartPolicy", + containerName: "init-container-3", + pod: corev1.Pod{ + Spec: corev1.PodSpec{ + InitContainers: []corev1.Container{ + { + Name: "init-container-3", + RestartPolicy: nil, + }, + }, + }, + }, + expected: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := handler.isNotSidecarContainer(tt.containerName, tt.pod) + assert.Equal(t, tt.expected, result) + }) + } +} diff --git a/ui/src/utils/fetcherHooks/podsViewFetch.ts b/ui/src/utils/fetcherHooks/podsViewFetch.ts index cd9e15eb6..07520e66a 100644 --- a/ui/src/utils/fetcherHooks/podsViewFetch.ts +++ b/ui/src/utils/fetcherHooks/podsViewFetch.ts @@ -61,7 +61,7 @@ export const usePodsViewFetch = ( JSON.stringify(pod?.spec?.containers) ); pod?.spec?.initContainers - ?.filter((initContainer: any) => initContainer?.name !== "init") + ?.filter((initContainer: any) => initContainer?.restartPolicy === "Always") ?.forEach((container: any) => containersList.push(container)); containersList?.forEach((container: any) => {