From 75d6b805409e1af209250ee28902ed4138f7f0f9 Mon Sep 17 00:00:00 2001 From: linghaoSu Date: Wed, 9 Oct 2024 18:35:01 +0800 Subject: [PATCH] fix(controller): add restartable sidecar count in total container display Signed-off-by: linghaoSu --- controller/cache/info.go | 8 ++ controller/cache/info_test.go | 260 +++++++++++++++++++++++++++++++++- 2 files changed, 267 insertions(+), 1 deletion(-) diff --git a/controller/cache/info.go b/controller/cache/info.go index eeca3f89f2ff6..7ea83cb7556eb 100644 --- a/controller/cache/info.go +++ b/controller/cache/info.go @@ -361,6 +361,9 @@ func populatePodInfo(un *unstructured.Unstructured, res *ResourceInfo) { initContainers := make(map[string]*v1.Container) for i := range pod.Spec.InitContainers { initContainers[pod.Spec.InitContainers[i].Name] = &pod.Spec.InitContainers[i] + if isRestartableInitContainer(&pod.Spec.InitContainers[i]) { + totalContainers++ + } } initializing := false @@ -372,6 +375,9 @@ func populatePodInfo(un *unstructured.Unstructured, res *ResourceInfo) { continue case isRestartableInitContainer(initContainers[container.Name]) && container.Started != nil && *container.Started: + if container.Ready { + readyContainers++ + } continue case container.State.Terminated != nil: // initialization is failed @@ -429,6 +435,8 @@ func populatePodInfo(un *unstructured.Unstructured, res *ResourceInfo) { // and https://github.com/kubernetes/kubernetes/issues/90358#issuecomment-617859364 if pod.DeletionTimestamp != nil && pod.Status.Reason == "NodeLost" { reason = "Unknown" + // If the pod is being deleted and the pod phase is not succeeded or failed, set the reason to "Terminating". + // See https://github.com/kubernetes/kubectl/issues/1595#issuecomment-2080001023 } else if pod.DeletionTimestamp != nil && !IsPodPhaseTerminal(podPhase) { reason = "Terminating" } diff --git a/controller/cache/info_test.go b/controller/cache/info_test.go index 0b6a673365015..05d7109e3344f 100644 --- a/controller/cache/info_test.go +++ b/controller/cache/info_test.go @@ -414,7 +414,265 @@ func TestGetPodInfoWithSidecar(t *testing.T) { assert.Equal(t, []v1alpha1.InfoItem{ {Name: "Status Reason", Value: "Running"}, {Name: "Node", Value: "minikube"}, - {Name: "Containers", Value: "1/1"}, + {Name: "Containers", Value: "2/2"}, + }, info.Info) +} + +func TestGetPodInfoWithInitialContainer(t *testing.T) { + pod := strToUnstructured(` + apiVersion: v1 + kind: Pod + metadata: + generateName: myapp-long-exist-56b7d8794d- + labels: + app: myapp-long-exist + name: myapp-long-exist-56b7d8794d-pbgrd + namespace: linghao + ownerReferences: + - apiVersion: apps/v1 + kind: ReplicaSet + name: myapp-long-exist-56b7d8794d + spec: + containers: + - image: alpine:latest + imagePullPolicy: Always + name: myapp-long-exist + initContainers: + - image: alpine:latest + imagePullPolicy: Always + name: myapp-long-exist-logshipper + nodeName: minikube + status: + containerStatuses: + - image: alpine:latest + name: myapp-long-exist + ready: false + restartCount: 0 + started: false + state: + waiting: + reason: PodInitializing + initContainerStatuses: + - image: alpine:latest + name: myapp-long-exist-logshipper + ready: false + restartCount: 0 + started: true + state: + running: + startedAt: '2024-10-09T08:03:45Z' + phase: Pending + startTime: '2024-10-09T08:02:39Z' +`) + + info := &ResourceInfo{} + populateNodeInfo(pod, info, []string{}) + assert.Equal(t, []v1alpha1.InfoItem{ + {Name: "Status Reason", Value: "Init:0/1"}, + {Name: "Node", Value: "minikube"}, + {Name: "Containers", Value: "0/1"}, + }, info.Info) +} + +// Test pod has 2 restartable init containers, the first one running but not started. +func TestGetPodInfoWithRestartableInitContainer(t *testing.T) { + pod := strToUnstructured(` + apiVersion: v1 + kind: Pod + metadata: + name: test1 + spec: + initContainers: + - name: restartable-init-1 + restartPolicy: Always + - name: restartable-init-2 + restartPolicy: Always + containers: + - name: container + nodeName: minikube + status: + phase: Pending + initContainerStatuses: + - name: restartable-init-1 + ready: false + restartCount: 3 + state: + running: {} + started: false + lastTerminationState: + terminated: + finishedAt: "2023-10-01T00:00:00Z" # Replace with actual time + - name: restartable-init-2 + ready: false + state: + waiting: {} + started: false + containerStatuses: + - ready: false + restartCount: 0 + state: + waiting: {} + conditions: + - type: PodInitialized + status: "False" +`) + + info := &ResourceInfo{} + populateNodeInfo(pod, info, []string{}) + assert.Equal(t, []v1alpha1.InfoItem{ + {Name: "Status Reason", Value: "Init:0/2"}, + {Name: "Node", Value: "minikube"}, + {Name: "Containers", Value: "0/3"}, + {Name: "Restart Count", Value: "3"}, + }, info.Info) +} + +// Test pod has 2 restartable init containers, the first one started and the second one running but not started. +func TestGetPodInfoWithPartiallyStartedInitContainers(t *testing.T) { + pod := strToUnstructured(` + apiVersion: v1 + kind: Pod + metadata: + name: test1 + spec: + initContainers: + - name: restartable-init-1 + restartPolicy: Always + - name: restartable-init-2 + restartPolicy: Always + containers: + - name: container + nodeName: minikube + status: + phase: Pending + initContainerStatuses: + - name: restartable-init-1 + ready: false + restartCount: 3 + state: + running: {} + started: true + lastTerminationState: + terminated: + finishedAt: "2023-10-01T00:00:00Z" # Replace with actual time + - name: restartable-init-2 + ready: false + state: + running: {} + started: false + containerStatuses: + - ready: false + restartCount: 0 + state: + waiting: {} + conditions: + - type: PodInitialized + status: "False" +`) + + info := &ResourceInfo{} + populateNodeInfo(pod, info, []string{}) + assert.Equal(t, []v1alpha1.InfoItem{ + {Name: "Status Reason", Value: "Init:1/2"}, + {Name: "Node", Value: "minikube"}, + {Name: "Containers", Value: "0/3"}, + {Name: "Restart Count", Value: "3"}, + }, info.Info) +} + +// Test pod has 2 restartable init containers started and 1 container running +func TestGetPodInfoWithStartedInitContainers(t *testing.T) { + pod := strToUnstructured(` + apiVersion: v1 + kind: Pod + metadata: + name: test2 + spec: + initContainers: + - name: restartable-init-1 + restartPolicy: Always + - name: restartable-init-2 + restartPolicy: Always + containers: + - name: container + nodeName: minikube + status: + phase: Running + initContainerStatuses: + - name: restartable-init-1 + ready: false + restartCount: 3 + state: + running: {} + started: true + lastTerminationState: + terminated: + finishedAt: "2023-10-01T00:00:00Z" # Replace with actual time + - name: restartable-init-2 + ready: false + state: + running: {} + started: true + containerStatuses: + - ready: true + restartCount: 4 + state: + running: {} + lastTerminationState: + terminated: + finishedAt: "2023-10-01T00:00:00Z" # Replace with actual time + conditions: + - type: PodInitialized + status: "True" +`) + + info := &ResourceInfo{} + populateNodeInfo(pod, info, []string{}) + assert.Equal(t, []v1alpha1.InfoItem{ + {Name: "Status Reason", Value: "Running"}, + {Name: "Node", Value: "minikube"}, + {Name: "Containers", Value: "1/3"}, + {Name: "Restart Count", Value: "7"}, + }, info.Info) +} + +// Test pod has 1 init container restarting and 1 container not running +func TestGetPodInfoWithNormalInitContainer(t *testing.T) { + pod := strToUnstructured(` + apiVersion: v1 + kind: Pod + metadata: + name: test7 + spec: + initContainers: + - name: init-container + containers: + - name: main-container + nodeName: minikube + status: + phase: podPhase + initContainerStatuses: + - ready: false + restartCount: 3 + state: + running: {} + lastTerminationState: + terminated: + finishedAt: "2023-10-01T00:00:00Z" # Replace with the actual time + containerStatuses: + - ready: false + restartCount: 0 + state: + waiting: {} +`) + + info := &ResourceInfo{} + populateNodeInfo(pod, info, []string{}) + assert.Equal(t, []v1alpha1.InfoItem{ + {Name: "Status Reason", Value: "Init:0/1"}, + {Name: "Node", Value: "minikube"}, + {Name: "Containers", Value: "0/1"}, + {Name: "Restart Count", Value: "3"}, }, info.Info) }