Skip to content

Commit ced7c37

Browse files
committed
frontend: pod: Add quick status for containers
This change adds a new icon displaying the status of each container in the pods list. Hovering over the icon gives important info about the container at a glance: name, status, reason, exit code, and start/finish times. Fixes: #2689 Signed-off-by: Evangelos Skopelitis <[email protected]>
1 parent 948cb8c commit ced7c37

9 files changed

+272
-124
lines changed

frontend/src/components/pod/Details.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ export default function PodDetails(props: PodDetailsProps) {
472472
item && [
473473
{
474474
name: t('State'),
475-
value: makePodStatusLabel(item),
475+
value: makePodStatusLabel(item, false),
476476
},
477477
{
478478
name: t('Node'),

frontend/src/components/pod/List.tsx

+79-11
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Box } from '@mui/material';
33
import React from 'react';
44
import { useTranslation } from 'react-i18next';
55
import { ApiError } from '../../lib/k8s/apiProxy';
6+
import { KubeContainerStatus } from '../../lib/k8s/cluster';
67
import Pod from '../../lib/k8s/pod';
78
import { METRIC_REFETCH_INTERVAL_MS, PodMetrics } from '../../lib/k8s/PodMetrics';
89
import { parseCpu, parseRam, unparseCpu, unparseRam } from '../../lib/units';
@@ -13,7 +14,7 @@ import { LightTooltip, Link, SimpleTableProps } from '../common';
1314
import { StatusLabel, StatusLabelProps } from '../common/Label';
1415
import ResourceListView from '../common/Resource/ResourceListView';
1516

16-
export function makePodStatusLabel(pod: Pod) {
17+
export function makePodStatusLabel(pod: Pod, showContainerStatus: boolean = true) {
1718
const phase = pod.status.phase;
1819
let status: StatusLabelProps['status'] = '';
1920

@@ -30,17 +31,34 @@ export function makePodStatusLabel(pod: Pod) {
3031
}
3132
}
3233

34+
const containerStatuses = pod.status?.containerStatuses || [];
35+
const containerIndicators = containerStatuses.map((cs, index) => {
36+
const { color, tooltip } = getContainerDisplayStatus(cs);
37+
return (
38+
<LightTooltip title={tooltip} key={index}>
39+
<Icon icon="mdi:circle" style={{ color }} width="1rem" height="1rem" />
40+
</LightTooltip>
41+
);
42+
});
43+
3344
return (
34-
<LightTooltip title={tooltip} interactive>
35-
<Box display="inline">
36-
<StatusLabel status={status}>
37-
{reason}
38-
{(status === 'warning' || status === 'error') && (
39-
<Icon aria-label="hidden" icon="mdi:alert-outline" width="1.2rem" height="1.2rem" />
40-
)}
41-
</StatusLabel>
42-
</Box>
43-
</LightTooltip>
45+
<Box display="flex" alignItems="center" gap={1}>
46+
<LightTooltip title={tooltip} interactive>
47+
<Box display="inline">
48+
<StatusLabel status={status}>
49+
{reason}
50+
{(status === 'warning' || status === 'error') && (
51+
<Icon aria-label="hidden" icon="mdi:alert-outline" width="1.2rem" height="1.2rem" />
52+
)}
53+
</StatusLabel>
54+
</Box>
55+
</LightTooltip>
56+
{showContainerStatus && containerIndicators.length > 0 && (
57+
<Box display="flex" gap={0.5}>
58+
{containerIndicators}
59+
</Box>
60+
)}
61+
</Box>
4462
);
4563
}
4664

@@ -60,6 +78,56 @@ function getReadinessGatesStatus(pods: Pod) {
6078
return readinessGatesMap;
6179
}
6280

81+
function getContainerDisplayStatus(container: KubeContainerStatus) {
82+
const state = container.state || {};
83+
let color = 'grey';
84+
let label = '';
85+
const tooltipLines: string[] = [`Name: ${container.name}`];
86+
87+
if (state.waiting) {
88+
color = 'orange';
89+
label = 'Waiting';
90+
if (state.waiting.reason) {
91+
tooltipLines.push(`Reason: ${state.waiting.reason}`);
92+
}
93+
} else if (state.terminated) {
94+
color = 'green';
95+
label = 'Terminated';
96+
if (state.terminated.reason) {
97+
tooltipLines.push(`Reason: ${state.terminated.reason}`);
98+
}
99+
if (state.terminated.exitCode !== undefined) {
100+
tooltipLines.push(`Exit Code: ${state.terminated.exitCode}`);
101+
}
102+
if (state.terminated.startedAt) {
103+
tooltipLines.push(`Started: ${new Date(state.terminated.startedAt).toLocaleString()}`);
104+
}
105+
if (state.terminated.finishedAt) {
106+
tooltipLines.push(`Finished: ${new Date(state.terminated.finishedAt).toLocaleString()}`);
107+
}
108+
if (container.restartCount > 0) {
109+
tooltipLines.push(`Restarts: ${container.restartCount}`);
110+
}
111+
} else if (state.running) {
112+
color = 'green';
113+
label = 'Running';
114+
if (state.running.startedAt) {
115+
tooltipLines.push(`Started: ${new Date(state.running.startedAt).toLocaleString()}`);
116+
}
117+
if (container.restartCount > 0) {
118+
tooltipLines.push(`Restarts: ${container.restartCount}`);
119+
}
120+
}
121+
122+
tooltipLines.splice(1, 0, `Status: ${label}`);
123+
124+
return {
125+
color,
126+
label,
127+
tooltip: <span style={{ whiteSpace: 'pre-line' }}>{tooltipLines.join('\n')}</span>,
128+
};
129+
}
130+
63131
export interface PodListProps {
64132
pods: Pod[] | null;
65133
metrics: PodMetrics[] | null;

frontend/src/components/pod/__snapshots__/PodDetails.Error.stories.storyshot

+12-8
Original file line numberDiff line numberDiff line change
@@ -219,16 +219,20 @@
219219
class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12 MuiGrid-grid-sm-8 css-deb4a-MuiGrid-root"
220220
>
221221
<div
222-
aria-label=""
223-
class="MuiBox-root css-6n7j50"
224-
data-mui-internal-clone-element="true"
222+
class="MuiBox-root css-axw7ok"
225223
>
226-
<span
227-
class="MuiTypography-root MuiTypography-body1 css-1q14vbw-MuiTypography-root"
228-
style="background-color: rgb(255, 235, 238); color: rgb(198, 40, 40);"
224+
<div
225+
aria-label=""
226+
class="MuiBox-root css-6n7j50"
227+
data-mui-internal-clone-element="true"
229228
>
230-
Error
231-
</span>
229+
<span
230+
class="MuiTypography-root MuiTypography-body1 css-1q14vbw-MuiTypography-root"
231+
style="background-color: rgb(255, 235, 238); color: rgb(198, 40, 40);"
232+
>
233+
Error
234+
</span>
235+
</div>
232236
</div>
233237
</dd>
234238
<dt

frontend/src/components/pod/__snapshots__/PodDetails.Initializing.stories.storyshot

+12-8
Original file line numberDiff line numberDiff line change
@@ -219,16 +219,20 @@
219219
class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12 MuiGrid-grid-sm-8 css-deb4a-MuiGrid-root"
220220
>
221221
<div
222-
aria-label=""
223-
class="MuiBox-root css-6n7j50"
224-
data-mui-internal-clone-element="true"
222+
class="MuiBox-root css-axw7ok"
225223
>
226-
<span
227-
class="MuiTypography-root MuiTypography-body1 css-1q14vbw-MuiTypography-root"
228-
style="background-color: rgb(240, 240, 240); color: rgba(0, 0, 0, 0.87);"
224+
<div
225+
aria-label=""
226+
class="MuiBox-root css-6n7j50"
227+
data-mui-internal-clone-element="true"
229228
>
230-
Init:0/2
231-
</span>
229+
<span
230+
class="MuiTypography-root MuiTypography-body1 css-1q14vbw-MuiTypography-root"
231+
style="background-color: rgb(240, 240, 240); color: rgba(0, 0, 0, 0.87);"
232+
>
233+
Init:0/2
234+
</span>
235+
</div>
232236
</div>
233237
</dd>
234238
<dt

frontend/src/components/pod/__snapshots__/PodDetails.LivenessFailed.stories.storyshot

+12-8
Original file line numberDiff line numberDiff line change
@@ -219,16 +219,20 @@
219219
class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12 MuiGrid-grid-sm-8 css-deb4a-MuiGrid-root"
220220
>
221221
<div
222-
aria-label="back-off 5m0s restarting failed container=liveness pod=liveness-http_default(4f8b71a3-f99c-41c2-9523-83edc1de02ce)"
223-
class="MuiBox-root css-6n7j50"
224-
data-mui-internal-clone-element="true"
222+
class="MuiBox-root css-axw7ok"
225223
>
226-
<span
227-
class="MuiTypography-root MuiTypography-body1 css-1q14vbw-MuiTypography-root"
228-
style="background-color: rgb(255, 243, 224); color: rgb(196, 69, 0);"
224+
<div
225+
aria-label="back-off 5m0s restarting failed container=liveness pod=liveness-http_default(4f8b71a3-f99c-41c2-9523-83edc1de02ce)"
226+
class="MuiBox-root css-6n7j50"
227+
data-mui-internal-clone-element="true"
229228
>
230-
CrashLoopBackOff
231-
</span>
229+
<span
230+
class="MuiTypography-root MuiTypography-body1 css-1q14vbw-MuiTypography-root"
231+
style="background-color: rgb(255, 243, 224); color: rgb(196, 69, 0);"
232+
>
233+
CrashLoopBackOff
234+
</span>
235+
</div>
232236
</div>
233237
</dd>
234238
<dt

frontend/src/components/pod/__snapshots__/PodDetails.PullBackOff.stories.storyshot

+12-8
Original file line numberDiff line numberDiff line change
@@ -219,16 +219,20 @@
219219
class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12 MuiGrid-grid-sm-8 css-deb4a-MuiGrid-root"
220220
>
221221
<div
222-
aria-label="Back-off pulling image "doesnotexist:nover""
223-
class="MuiBox-root css-6n7j50"
224-
data-mui-internal-clone-element="true"
222+
class="MuiBox-root css-axw7ok"
225223
>
226-
<span
227-
class="MuiTypography-root MuiTypography-body1 css-1q14vbw-MuiTypography-root"
228-
style="background-color: rgb(240, 240, 240); color: rgba(0, 0, 0, 0.87);"
224+
<div
225+
aria-label="Back-off pulling image "doesnotexist:nover""
226+
class="MuiBox-root css-6n7j50"
227+
data-mui-internal-clone-element="true"
229228
>
230-
ImagePullBackOff
231-
</span>
229+
<span
230+
class="MuiTypography-root MuiTypography-body1 css-1q14vbw-MuiTypography-root"
231+
style="background-color: rgb(240, 240, 240); color: rgba(0, 0, 0, 0.87);"
232+
>
233+
ImagePullBackOff
234+
</span>
235+
</div>
232236
</div>
233237
</dd>
234238
<dt

frontend/src/components/pod/__snapshots__/PodDetails.Running.stories.storyshot

+12-8
Original file line numberDiff line numberDiff line change
@@ -219,16 +219,20 @@
219219
class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12 MuiGrid-grid-sm-8 css-deb4a-MuiGrid-root"
220220
>
221221
<div
222-
aria-label=""
223-
class="MuiBox-root css-6n7j50"
224-
data-mui-internal-clone-element="true"
222+
class="MuiBox-root css-axw7ok"
225223
>
226-
<span
227-
class="MuiTypography-root MuiTypography-body1 css-1q14vbw-MuiTypography-root"
228-
style="background-color: rgb(248, 255, 240); color: rgb(46, 125, 50);"
224+
<div
225+
aria-label=""
226+
class="MuiBox-root css-6n7j50"
227+
data-mui-internal-clone-element="true"
229228
>
230-
Running
231-
</span>
229+
<span
230+
class="MuiTypography-root MuiTypography-body1 css-1q14vbw-MuiTypography-root"
231+
style="background-color: rgb(248, 255, 240); color: rgb(46, 125, 50);"
232+
>
233+
Running
234+
</span>
235+
</div>
232236
</div>
233237
</dd>
234238
<dt

frontend/src/components/pod/__snapshots__/PodDetails.Successful.stories.storyshot

+12-8
Original file line numberDiff line numberDiff line change
@@ -219,16 +219,20 @@
219219
class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12 MuiGrid-grid-sm-8 css-deb4a-MuiGrid-root"
220220
>
221221
<div
222-
aria-label=""
223-
class="MuiBox-root css-6n7j50"
224-
data-mui-internal-clone-element="true"
222+
class="MuiBox-root css-axw7ok"
225223
>
226-
<span
227-
class="MuiTypography-root MuiTypography-body1 css-1q14vbw-MuiTypography-root"
228-
style="background-color: rgb(248, 255, 240); color: rgb(46, 125, 50);"
224+
<div
225+
aria-label=""
226+
class="MuiBox-root css-6n7j50"
227+
data-mui-internal-clone-element="true"
229228
>
230-
Completed
231-
</span>
229+
<span
230+
class="MuiTypography-root MuiTypography-body1 css-1q14vbw-MuiTypography-root"
231+
style="background-color: rgb(248, 255, 240); color: rgb(46, 125, 50);"
232+
>
233+
Completed
234+
</span>
235+
</div>
232236
</div>
233237
</dd>
234238
<dt

0 commit comments

Comments
 (0)