diff --git a/ui/src/app/applications/components/application-node-info/application-node-info.scss b/ui/src/app/applications/components/application-node-info/application-node-info.scss index 4edf2235eea22..1d1fbf941fac7 100644 --- a/ui/src/app/applications/components/application-node-info/application-node-info.scss +++ b/ui/src/app/applications/components/application-node-info/application-node-info.scss @@ -39,4 +39,31 @@ color: $argo-color-gray-8; } } + + &__container { + display: flex; + align-items: center; + flex-direction: row; + line-height: 1.8; + border-bottom: 1px solid rgba(222, 230, 235, 0.7); + + &--name { + width: 15%; + } + &--highlight { + font-style: italic; + } + + &--hint { + text-decoration: underline; + text-decoration-style: dashed; + cursor: pointer; + &:hover { + text-decoration: none; + } + } + &:last-child { + border-bottom: none; + } + } } diff --git a/ui/src/app/applications/components/application-node-info/application-node-info.tsx b/ui/src/app/applications/components/application-node-info/application-node-info.tsx index ee0e2516cce15..8ecb965a1ab8b 100644 --- a/ui/src/app/applications/components/application-node-info/application-node-info.tsx +++ b/ui/src/app/applications/components/application-node-info/application-node-info.tsx @@ -1,4 +1,5 @@ import {Checkbox, DataLoader, Tab, Tabs} from 'argo-ui'; +import classNames from 'classnames'; import * as deepMerge from 'deepmerge'; import * as React from 'react'; @@ -16,10 +17,72 @@ import { getPodStateReason, HealthStatusIcon } from '../utils'; - import './application-node-info.scss'; import {ReadinessGatesFailedWarning} from './readiness-gates-failed-warning'; +const RenderContainerState = (props: {container: any}) => { + const state = (props.container.state?.waiting && 'waiting') || (props.container.state?.terminated && 'terminated') || (props.container.state?.running && 'running'); + const status = props.container.state.waiting?.reason || props.container.state.terminated?.reason || props.container.state.running?.reason; + const lastState = props.container.lastState?.terminated; + const msg = props.container.state.waiting?.message || props.container.state.terminated?.message || props.container.state.running?.message; + + return ( +
+
{props.container.name}
+
+ {state && ( + <> + Container is {state} + {status && ' because of '} + + )} + + {status && ( + + {status} + + )} + + {'.'} + {(props.container.state.terminated?.exitCode === 0 || props.container.state.terminated?.exitCode) && ( + <> + {' '} + It exited with exit code {props.container.state.terminated.exitCode}. + + )} + <> + {' '} + It is {props.container?.started ? 'started' : 'not started'} and + {props.container?.ready ? ' ready.' : ' not ready.'} + +
+ {lastState && ( + <> + <> + The container last terminated with exit code {lastState?.exitCode} + + {lastState?.reason && ' because of '} + + {lastState?.reason && ( + + {lastState?.reason} + + )} + + {'.'} + + )} +
+
+ ); +}; + export const ApplicationNodeInfo = (props: { application: models.Application; node: models.ResourceNode; @@ -54,11 +117,23 @@ export const ApplicationNodeInfo = (props: { } if (props.live) { if (props.node.kind === 'Pod') { - const {reason, message} = getPodStateReason(props.live); + const {reason, message, netContainerStatuses} = getPodStateReason(props.live); attributes.push({title: 'STATE', value: reason}); if (message) { attributes.push({title: 'STATE DETAILS', value: message}); } + if (netContainerStatuses.length > 0) { + attributes.push({ + title: 'CONTAINER STATE', + value: ( +
+ {netContainerStatuses.map((container, i) => { + return ; + })} +
+ ) + }); + } } else if (props.node.kind === 'Service') { attributes.push({title: 'TYPE', value: props.live.spec.type}); let hostNames = ''; diff --git a/ui/src/app/applications/components/application-resource-tree/application-resource-tree.tsx b/ui/src/app/applications/components/application-resource-tree/application-resource-tree.tsx index e58282acada04..29707816b7e05 100644 --- a/ui/src/app/applications/components/application-resource-tree/application-resource-tree.tsx +++ b/ui/src/app/applications/components/application-resource-tree/application-resource-tree.tsx @@ -3,6 +3,7 @@ import * as classNames from 'classnames'; import * as dagre from 'dagre'; import * as React from 'react'; import Moment from 'react-moment'; +import * as moment from 'moment'; import * as models from '../../../shared/models'; @@ -611,6 +612,61 @@ function expandCollapse(node: ResourceTreeNode, props: ApplicationResourceTreePr props.setNodeExpansion(node.uid, isExpanded); } +function NodeInfoDetails({tag: tag, kind: kind}: {tag: models.InfoItem; kind: string}) { + if (kind === 'Pod') { + const val = `${tag.name}`; + if (val === 'Status Reason') { + if (`${tag.value}` !== 'ImagePullBackOff') + return ( + + {tag.value} + + ); + else { + return ( + + {tag.value} + + ); + } + } else if (val === 'Containers') { + const arr = `${tag.value}`.split('/'); + const title = `Number of containers in total: ${arr[1]} \nNumber of ready containers: ${arr[0]}`; + return ( + + {tag.value} + + ); + } else if (val === 'Restart Count') { + return ( + + {tag.value} + + ); + } else if (val === 'Revision') { + return ( + + {tag.value} + + ); + } else { + return ( + + {tag.value} + + ); + } + } else { + return ( + + {tag.value} + + ); + } +} + function renderResourceNode(props: ApplicationResourceTreeProps, id: string, node: ResourceTreeNode & dagre.Node, nodesHavingChildren: Map) { const fullName = nodeKey(node); let comparisonStatus: models.SyncStatusCode = null; @@ -685,18 +741,18 @@ function renderResourceNode(props: ApplicationResourceTreeProps, id: string, nod
{node.createdAt || rootNode ? ( - - {node.createdAt || props.app.metadata.creationTimestamp} - + + + {node.createdAt || props.app.metadata.creationTimestamp} + + ) : null} {(node.info || []) .filter(tag => !tag.name.includes('Node')) .slice(0, 4) - .map((tag, i) => ( - - {tag.value} - - ))} + .map((tag, i) => { + return ; + })} {(node.info || []).length > 4 && ( ( diff --git a/ui/src/app/applications/components/utils.tsx b/ui/src/app/applications/components/utils.tsx index 7e4fed73cbd17..3819f7d911074 100644 --- a/ui/src/app/applications/components/utils.tsx +++ b/ui/src/app/applications/components/utils.tsx @@ -872,7 +872,7 @@ export const OperationState = ({app, quiet}: {app: appModels.Application; quiet? ); }; -export function getPodStateReason(pod: appModels.State): {message: string; reason: string} { +export function getPodStateReason(pod: appModels.State): {message: string; reason: string; netContainerStatuses: any[]} { let reason = pod.status.phase; let message = ''; if (pod.status.reason) { @@ -880,6 +880,10 @@ export function getPodStateReason(pod: appModels.State): {message: string; reaso } let initializing = false; + + let netContainerStatuses = pod.status.initContainerStatuses || []; + netContainerStatuses = netContainerStatuses.concat(pod.status.containerStatuses || []); + for (const container of (pod.status.initContainerStatuses || []).slice().reverse()) { if (container.state.terminated && container.state.terminated.exitCode === 0) { continue; @@ -939,7 +943,7 @@ export function getPodStateReason(pod: appModels.State): {message: string; reaso message = ''; } - return {reason, message}; + return {reason, message, netContainerStatuses}; } export const getPodReadinessGatesState = (pod: appModels.State): {nonExistingConditions: string[]; failedConditions: string[]} => {