diff --git a/assets/src/components/kubernetes/common/Containers.tsx b/assets/src/components/kubernetes/common/Containers.tsx new file mode 100644 index 0000000000..6406d3bc40 --- /dev/null +++ b/assets/src/components/kubernetes/common/Containers.tsx @@ -0,0 +1,59 @@ +import { ReactElement } from 'react' +import { Table } from '@pluralsh/design-system' +import { createColumnHelper } from '@tanstack/react-table' + +import { + Pod_Container as ContainerT, + Maybe, +} from '../../../generated/graphql-kubernetes' + +const columnHelper = createColumnHelper() + +interface ContainersProps { + containers: Array> +} + +const columns = [ + // Name + columnHelper.accessor((container) => container?.name, { + id: 'name', + header: 'Name', + cell: ({ getValue }) => getValue(), + }), + // Image + columnHelper.accessor((container) => container?.image, { + id: 'image', + header: 'Image', + cell: ({ getValue }) => getValue(), + }), + // Args + columnHelper.accessor((container) => container?.args, { + id: 'args', + header: 'Args', + cell: ({ getValue }) => getValue(), + }), + // Status + columnHelper.accessor((container) => container?.status?.name, { + id: 'status', + header: 'Status', + cell: ({ getValue }) => getValue(), + }), +] + +export default function Containers({ + containers, +}: ContainersProps): ReactElement { + console.log(containers) + + return ( + + ) +} diff --git a/assets/src/components/kubernetes/storage/PersistentVolumeClaims.tsx b/assets/src/components/kubernetes/storage/PersistentVolumeClaims.tsx index e0acff3b3b..23a7987003 100644 --- a/assets/src/components/kubernetes/storage/PersistentVolumeClaims.tsx +++ b/assets/src/components/kubernetes/storage/PersistentVolumeClaims.tsx @@ -1,8 +1,6 @@ import { createColumnHelper } from '@tanstack/react-table' import { useMemo } from 'react' - import { ChipList } from '@pluralsh/design-system' - import { Link } from 'react-router-dom' import { @@ -14,14 +12,9 @@ import { } from '../../../generated/graphql-kubernetes' import { useDefaultColumns } from '../utils' import { ResourceList } from '../ResourceList' - import { ClusterTinyFragment } from '../../../generated/graphql' import { InlineLink } from '../../utils/typography/InlineLink' -import { - STORAGE_CLASSES_REL_PATH, - getResourceDetailsAbsPath, - getStorageResourceDetailsAbsPath, -} from '../../../routes/kubernetesRoutesConsts' +import { getResourceDetailsAbsPath } from '../../../routes/kubernetesRoutesConsts' import { PVCStatusChip } from './utils' diff --git a/assets/src/components/kubernetes/workloads/Pod.tsx b/assets/src/components/kubernetes/workloads/Pod.tsx index 8e7f28a40b..a3486d88c3 100644 --- a/assets/src/components/kubernetes/workloads/Pod.tsx +++ b/assets/src/components/kubernetes/workloads/Pod.tsx @@ -1,17 +1,61 @@ -import { ReactElement } from 'react' -import { useParams } from 'react-router-dom' -import { Flex } from 'honorable' +import { ReactElement, useRef } from 'react' +import { Link, useMatch, useParams } from 'react-router-dom' +import { useTheme } from 'styled-components' + +import { SubTab, TabList, Table } from '@pluralsh/design-system' + +import { createColumnHelper } from '@tanstack/react-table' import { KubernetesClient } from '../../../helpers/kubernetes.client' import { PodQueryVariables, + Pod_PodDetail as PodT, usePodQuery, } from '../../../generated/graphql-kubernetes' import LoadingIndicator from '../../utils/LoadingIndicator' -import { ScrollablePage } from '../../utils/layout/ScrollablePage' import { SubTitle } from '../../cluster/nodes/SubTitle' +import { Metadata } from '../utils' + +import { ResponsiveLayoutSidecarContainer } from '../../utils/layout/ResponsiveLayoutSidecarContainer' + +import { ResponsiveLayoutPage } from '../../utils/layout/ResponsiveLayoutPage' + +import { ResponsiveLayoutSpacer } from '../../utils/layout/ResponsiveLayoutSpacer' + +import { LinkTabWrap } from '../../utils/Tabs' + +import { getResourceDetailsAbsPath } from '../../../routes/kubernetesRoutesConsts' +import { ClusterTinyFragment } from '../../../generated/graphql' +import { InlineLink } from '../../utils/typography/InlineLink' + +import { ScrollablePage } from '../../utils/layout/ScrollablePage' + +import { ResponsiveLayoutContentContainer } from '../../utils/layout/ResponsiveLayoutContentContainer' + +import { ResponsiveLayoutHeader } from '../../utils/layout/ResponsiveLayoutHeader' + +import { ResponsivePageFullWidth } from '../../utils/layout/ResponsivePageFullWidth' + +import Containers from '../common/Containers' + +import PodSidecar from './PodSidecar' + +const directory = [ + { path: '', label: 'Info' }, + { path: 'events', label: 'Events' }, + { path: 'raw', label: 'Raw' }, +] as const + +const columnHelper = createColumnHelper() + +const colNode = columnHelper.accessor((pod) => pod, { + id: 'mock', + header: 'Mock', + cell: ({ getValue, table }) =>
, +}) export default function Pod(): ReactElement { + const theme = useTheme() const { clusterId, name, namespace } = useParams() const { data, loading } = usePodQuery({ client: KubernetesClient(clusterId ?? ''), @@ -23,43 +67,117 @@ export default function Pod(): ReactElement { } as PodQueryVariables, }) - const pod = data?.handleGetPodDetail + const pod = data?.handleGetPodDetail as PodT const containers = pod?.containers const conditions = pod?.conditions + const tabStateRef = useRef(null) + const pathMatch = useMatch(`:tab/*`) + const tab = pathMatch?.params?.tab || '' + const currentTab = directory.find(({ path }) => path === tab) + if (loading) { return } return ( - } - > - + div': { + paddingLeft: 0, + paddingTop: 0, + }, + }} > -
- Containers - {/* */} -
-
- Conditions - {/* */} -
-
- Metadata - {/* */} -
-
-
+ +
+ + {directory.map(({ label, path }) => ( + + + {label} + + + ))} + +
+
+ +
+
+ Containers + +
+
+ Conditions +
+ +
+ Metadata + +
+ + + + + + + + ) } diff --git a/assets/src/components/kubernetes/workloads/PodSidecar.tsx b/assets/src/components/kubernetes/workloads/PodSidecar.tsx new file mode 100644 index 0000000000..360cf57861 --- /dev/null +++ b/assets/src/components/kubernetes/workloads/PodSidecar.tsx @@ -0,0 +1,43 @@ +import { ReactElement } from 'react' + +import { useTheme } from 'styled-components' + +import { Sidecar, SidecarItem } from '@pluralsh/design-system' + +import { A } from 'honorable' +import { Link } from 'react-router-dom' + +import { Pod_PodDetail as PodT } from '../../../generated/graphql-kubernetes' +import { StatusChip } from '../../cluster/TableElements' +import { ReadinessT } from '../../../utils/status' + +interface PodSidecarProps { + pod: Nullable +} + +export default function PodSidecar({ pod }: PodSidecarProps): ReactElement { + return ( + + {pod?.objectMeta.name} + + {pod?.objectMeta?.namespace} + + {pod?.podIP} + + + {pod?.nodeName} + + + + {pod?.serviceAccountName} + + + + + + ) +} diff --git a/assets/src/components/utils/layout/ResponsiveLayoutHeader.tsx b/assets/src/components/utils/layout/ResponsiveLayoutHeader.tsx new file mode 100644 index 0000000000..0dea623087 --- /dev/null +++ b/assets/src/components/utils/layout/ResponsiveLayoutHeader.tsx @@ -0,0 +1,9 @@ +import styled from 'styled-components' + +export const ResponsiveLayoutHeader = styled.div(({ theme }) => ({ + display: 'flex', + width: '100%', + overflowX: 'hidden', + paddingBottom: theme.spacing.large, + flexGrow: 1, +})) diff --git a/assets/src/components/utils/layout/ScrollablePage.tsx b/assets/src/components/utils/layout/ScrollablePage.tsx index 1ef0f36a9b..927bd09434 100644 --- a/assets/src/components/utils/layout/ScrollablePage.tsx +++ b/assets/src/components/utils/layout/ScrollablePage.tsx @@ -9,35 +9,48 @@ const ScrollablePageContent = styled.div<{ extraStyles?: CSSProperties maxContentWidth?: number fullWidth?: boolean -}>(({ theme, scrollable, extraStyles, maxContentWidth, fullWidth }) => ({ - position: 'relative', - height: '100%', - maxHeight: '100%', - width: '100%', - overflowY: scrollable ? 'auto' : 'hidden', - overflowX: 'hidden', - paddingRight: scrollable ? theme.spacing.small : 0, - ...(scrollable ? { scrollbarGutter: 'stable' } : {}), - ...(scrollable && fullWidth - ? { - paddingRight: theme.spacing.large - 6, - } - : {}), - '& > .widthLimiter': { + noPadding?: boolean +}>( + ({ + theme, + scrollable, + extraStyles, + maxContentWidth, + fullWidth, + noPadding, + }) => ({ + position: 'relative', + height: '100%', + maxHeight: '100%', width: '100%', - paddingTop: theme.spacing.medium, - paddingBottom: scrollable ? theme.spacing.xxlarge : theme.spacing.large, - ...(!scrollable + overflowY: scrollable ? 'auto' : 'hidden', + overflowX: 'hidden', + paddingRight: scrollable ? theme.spacing.small : 0, + ...(scrollable ? { scrollbarGutter: 'stable' } : {}), + ...(scrollable && fullWidth ? { - height: '100%', + paddingRight: theme.spacing.large - 6, } : {}), - ...(maxContentWidth - ? { maxWidth: maxContentWidth, marginLeft: 'auto', marginRight: 'auto' } - : {}), - ...(extraStyles ?? {}), - }, -})) + '& > .widthLimiter': { + width: '100%', + ...(!noPadding && { + paddingTop: theme.spacing.medium, + paddingBottom: scrollable ? theme.spacing.xxlarge : theme.spacing.large, + }), + + ...(!scrollable + ? { + height: '100%', + } + : {}), + ...(maxContentWidth + ? { maxWidth: maxContentWidth, marginLeft: 'auto', marginRight: 'auto' } + : {}), + ...(extraStyles ?? {}), + }, + }) +) const ScrollShadow = styled.div(({ theme }) => ({ content: '""', @@ -60,6 +73,7 @@ export function ScrollablePage({ maxContentWidth, fullWidth, scrollRef, + noPadding = false, ...props }: { heading?: ReactNode @@ -70,6 +84,7 @@ export function ScrollablePage({ maxContentWidth?: number fullWidth?: boolean scrollRef?: Ref + noPadding?: boolean } & FlexProps) { return ( <> @@ -98,6 +113,7 @@ export function ScrollablePage({ maxContentWidth={maxContentWidth} fullWidth={fullWidth} ref={scrollRef} + noPadding={noPadding} >
{children}
diff --git a/assets/src/generated/graphql-kubernetes.ts b/assets/src/generated/graphql-kubernetes.ts index 9fe6ef11c4..7f0e4825a9 100644 --- a/assets/src/generated/graphql-kubernetes.ts +++ b/assets/src/generated/graphql-kubernetes.ts @@ -4862,9 +4862,9 @@ export type PodQueryVariables = Exact<{ }>; -export type PodQuery = { __typename?: 'Query', handleGetPodDetail?: { __typename?: 'pod_PodDetail', nodeName: string, restartCount: number, objectMeta: { __typename?: 'types_ObjectMeta', uid?: string | null, name?: string | null, namespace?: string | null, labels?: any | null, annotations?: any | null, creationTimestamp?: string | null }, conditions: Array<{ __typename?: 'common_Condition', message: string, type: string, status: string, lastProbeTime: string, lastTransitionTime: string, reason: string } | null>, containers: Array<{ __typename?: 'pod_Container', name: string, args: Array, commands: Array, image: string, livenessProbe: { __typename?: 'v1_Probe', failureThreshold?: number | null, initialDelaySeconds?: number | null, periodSeconds?: number | null, successThreshold?: number | null, terminationGracePeriodSeconds?: any | null, timeoutSeconds?: number | null, exec?: { __typename?: 'v1_ExecAction', command?: Array | null } | null }, readinessProbe: { __typename?: 'v1_Probe', failureThreshold?: number | null, initialDelaySeconds?: number | null, periodSeconds?: number | null, successThreshold?: number | null, terminationGracePeriodSeconds?: any | null, timeoutSeconds?: number | null, exec?: { __typename?: 'v1_ExecAction', command?: Array | null } | null } } | null>, controller?: { __typename?: 'controller_ResourceOwner', containerImages: Array, initContainerImages: Array, typeMeta: { __typename?: 'types_TypeMeta', kind?: string | null, restartable?: boolean | null, scalable?: boolean | null }, objectMeta: { __typename?: 'types_ObjectMeta', uid?: string | null, name?: string | null, namespace?: string | null, labels?: any | null, annotations?: any | null, creationTimestamp?: string | null }, pods: { __typename?: 'common_PodInfo', current: number, desired?: number | null, failed: number, pending: number, running: number, succeeded: number, warnings: Array<{ __typename?: 'common_Event', objectName?: string | null, objectNamespace?: string | null, reason: string, type: string, message: string, sourceComponent: string, sourceHost: string, count: number, firstSeen: string, lastSeen: string, typeMeta: { __typename?: 'types_TypeMeta', kind?: string | null, restartable?: boolean | null, scalable?: boolean | null }, objectMeta: { __typename?: 'types_ObjectMeta', uid?: string | null, name?: string | null, namespace?: string | null, labels?: any | null, annotations?: any | null, creationTimestamp?: string | null } } | null> } } | null, eventList: { __typename?: 'common_EventList', listMeta: { __typename?: 'types_ListMeta', totalItems: number }, events: Array<{ __typename?: 'common_Event', objectName?: string | null, objectNamespace?: string | null, reason: string, type: string, message: string, sourceComponent: string, sourceHost: string, count: number, firstSeen: string, lastSeen: string, typeMeta: { __typename?: 'types_TypeMeta', kind?: string | null, restartable?: boolean | null, scalable?: boolean | null }, objectMeta: { __typename?: 'types_ObjectMeta', uid?: string | null, name?: string | null, namespace?: string | null, labels?: any | null, annotations?: any | null, creationTimestamp?: string | null } } | null> } } | null }; +export type PodQuery = { __typename?: 'Query', handleGetPodDetail?: { __typename?: 'pod_PodDetail', nodeName: string, restartCount: number, serviceAccountName: string, podIP: string, podPhase: string, objectMeta: { __typename?: 'types_ObjectMeta', uid?: string | null, name?: string | null, namespace?: string | null, labels?: any | null, annotations?: any | null, creationTimestamp?: string | null }, conditions: Array<{ __typename?: 'common_Condition', message: string, type: string, status: string, lastProbeTime: string, lastTransitionTime: string, reason: string } | null>, containers: Array<{ __typename?: 'pod_Container', name: string, args: Array, commands: Array, image: string, livenessProbe: { __typename?: 'v1_Probe', failureThreshold?: number | null, initialDelaySeconds?: number | null, periodSeconds?: number | null, successThreshold?: number | null, terminationGracePeriodSeconds?: any | null, timeoutSeconds?: number | null, exec?: { __typename?: 'v1_ExecAction', command?: Array | null } | null }, readinessProbe: { __typename?: 'v1_Probe', failureThreshold?: number | null, initialDelaySeconds?: number | null, periodSeconds?: number | null, successThreshold?: number | null, terminationGracePeriodSeconds?: any | null, timeoutSeconds?: number | null, exec?: { __typename?: 'v1_ExecAction', command?: Array | null } | null }, status: { __typename?: 'v1_ContainerStatus', name: string, state?: { __typename?: 'v1_ContainerState', running?: { __typename?: 'v1_ContainerStateRunning', startedAt?: string | null } | null, terminated?: { __typename?: 'v1_ContainerStateTerminated', startedAt?: string | null, reason?: string | null, message?: string | null, containerID?: string | null, exitCode: number, finishedAt?: string | null, signal?: number | null } | null, waiting?: { __typename?: 'v1_ContainerStateWaiting', message?: string | null, reason?: string | null } | null } | null } } | null>, controller?: { __typename?: 'controller_ResourceOwner', containerImages: Array, initContainerImages: Array, typeMeta: { __typename?: 'types_TypeMeta', kind?: string | null, restartable?: boolean | null, scalable?: boolean | null }, objectMeta: { __typename?: 'types_ObjectMeta', uid?: string | null, name?: string | null, namespace?: string | null, labels?: any | null, annotations?: any | null, creationTimestamp?: string | null }, pods: { __typename?: 'common_PodInfo', current: number, desired?: number | null, failed: number, pending: number, running: number, succeeded: number, warnings: Array<{ __typename?: 'common_Event', objectName?: string | null, objectNamespace?: string | null, reason: string, type: string, message: string, sourceComponent: string, sourceHost: string, count: number, firstSeen: string, lastSeen: string, typeMeta: { __typename?: 'types_TypeMeta', kind?: string | null, restartable?: boolean | null, scalable?: boolean | null }, objectMeta: { __typename?: 'types_ObjectMeta', uid?: string | null, name?: string | null, namespace?: string | null, labels?: any | null, annotations?: any | null, creationTimestamp?: string | null } } | null> } } | null, eventList: { __typename?: 'common_EventList', listMeta: { __typename?: 'types_ListMeta', totalItems: number }, events: Array<{ __typename?: 'common_Event', objectName?: string | null, objectNamespace?: string | null, reason: string, type: string, message: string, sourceComponent: string, sourceHost: string, count: number, firstSeen: string, lastSeen: string, typeMeta: { __typename?: 'types_TypeMeta', kind?: string | null, restartable?: boolean | null, scalable?: boolean | null }, objectMeta: { __typename?: 'types_ObjectMeta', uid?: string | null, name?: string | null, namespace?: string | null, labels?: any | null, annotations?: any | null, creationTimestamp?: string | null } } | null> } } | null }; -export type ContainerFragment = { __typename?: 'pod_Container', name: string, args: Array, commands: Array, image: string, livenessProbe: { __typename?: 'v1_Probe', failureThreshold?: number | null, initialDelaySeconds?: number | null, periodSeconds?: number | null, successThreshold?: number | null, terminationGracePeriodSeconds?: any | null, timeoutSeconds?: number | null, exec?: { __typename?: 'v1_ExecAction', command?: Array | null } | null }, readinessProbe: { __typename?: 'v1_Probe', failureThreshold?: number | null, initialDelaySeconds?: number | null, periodSeconds?: number | null, successThreshold?: number | null, terminationGracePeriodSeconds?: any | null, timeoutSeconds?: number | null, exec?: { __typename?: 'v1_ExecAction', command?: Array | null } | null } }; +export type ContainerFragment = { __typename?: 'pod_Container', name: string, args: Array, commands: Array, image: string, livenessProbe: { __typename?: 'v1_Probe', failureThreshold?: number | null, initialDelaySeconds?: number | null, periodSeconds?: number | null, successThreshold?: number | null, terminationGracePeriodSeconds?: any | null, timeoutSeconds?: number | null, exec?: { __typename?: 'v1_ExecAction', command?: Array | null } | null }, readinessProbe: { __typename?: 'v1_Probe', failureThreshold?: number | null, initialDelaySeconds?: number | null, periodSeconds?: number | null, successThreshold?: number | null, terminationGracePeriodSeconds?: any | null, timeoutSeconds?: number | null, exec?: { __typename?: 'v1_ExecAction', command?: Array | null } | null }, status: { __typename?: 'v1_ContainerStatus', name: string, state?: { __typename?: 'v1_ContainerState', running?: { __typename?: 'v1_ContainerStateRunning', startedAt?: string | null } | null, terminated?: { __typename?: 'v1_ContainerStateTerminated', startedAt?: string | null, reason?: string | null, message?: string | null, containerID?: string | null, exitCode: number, finishedAt?: string | null, signal?: number | null } | null, waiting?: { __typename?: 'v1_ContainerStateWaiting', message?: string | null, reason?: string | null } | null } | null } }; export type ReplicaSetsQueryVariables = Exact<{ namespace: Scalars['String']['input']; @@ -5015,9 +5015,30 @@ export const ContainerFragmentDoc = gql` livenessProbe @type(name: "v1_Probe") { ...Probe } - readinessProbe { + readinessProbe @type(name: "v1_Probe") { ...Probe } + status @type(name: "v1_ContainerStatus") { + name + state { + running { + startedAt + } + terminated { + startedAt + reason + message + containerID + exitCode + finishedAt + signal + } + waiting { + message + reason + } + } + } } ${ProbeFragmentDoc}`; export const ClusterRolesDocument = gql` @@ -6581,6 +6602,9 @@ export const PodDocument = gql` } nodeName restartCount + serviceAccountName + podIP + podPhase conditions @type(name: "common_Condition") { ...Condition } diff --git a/assets/src/graph-kubernetes/workloads/pod.graphql b/assets/src/graph-kubernetes/workloads/pod.graphql index f9bbea2f1e..7c2fb28093 100644 --- a/assets/src/graph-kubernetes/workloads/pod.graphql +++ b/assets/src/graph-kubernetes/workloads/pod.graphql @@ -44,6 +44,9 @@ query Pod($name: String!, $namespace: String!) { } nodeName restartCount + serviceAccountName + podIP + podPhase conditions @type(name: "common_Condition") { ...Condition } diff --git a/assets/src/graph-kubernetes/workloads/pod_fragments.graphql b/assets/src/graph-kubernetes/workloads/pod_fragments.graphql index fa9c3ebc45..76b2bfdf25 100644 --- a/assets/src/graph-kubernetes/workloads/pod_fragments.graphql +++ b/assets/src/graph-kubernetes/workloads/pod_fragments.graphql @@ -6,7 +6,28 @@ fragment Container on pod_Container { livenessProbe @type(name: "v1_Probe") { ...Probe } - readinessProbe { + readinessProbe @type(name: "v1_Probe") { ...Probe } + status @type(name: "v1_ContainerStatus") { + name + state { + running { + startedAt + } + terminated { + startedAt + reason + message + containerID + exitCode + finishedAt + signal + } + waiting { + message + reason + } + } + } } diff --git a/assets/src/routes/kubernetesRoutesConsts.tsx b/assets/src/routes/kubernetesRoutesConsts.tsx index efbdf2c4d6..2f25c7cc75 100644 --- a/assets/src/routes/kubernetesRoutesConsts.tsx +++ b/assets/src/routes/kubernetesRoutesConsts.tsx @@ -73,20 +73,6 @@ export function getClusterAbsPath(clusterId: string | null | undefined) { export function getAccessAbsPath(clusterId: string | null | undefined) { return `/kubernetes/${clusterId}/${ACCESS_REL_PATH}` } - -export function getCustomResourcesAbsPath( - clusterId: string | null | undefined -) { - return `/kubernetes/${clusterId}/${CUSTOM_RESOURCES_REL_PATH}` -} - -export function getResourceDetailsRelPath( - name: string, - namespace?: Nullable -): string { - return namespace ? `${namespace}/${name}` : name -} - export function getResourceDetailsAbsPath( clusterId: Nullable, kind: string, @@ -97,14 +83,3 @@ export function getResourceDetailsAbsPath( ? `/kubernetes/${clusterId}/${pluralize(kind)}/${namespace}/${name}` : `/kubernetes/${clusterId}/${pluralize(kind)}/${name}` } - -export function getStorageResourceDetailsAbsPath( - resourceRelPath, - clusterId: string | null | undefined, - name: string, - namespace?: Nullable -): string { - return `${getStorageAbsPath( - clusterId - )}/${resourceRelPath}/${getResourceDetailsRelPath(name, namespace)}` -} diff --git a/assets/src/utils/status.ts b/assets/src/utils/status.ts index 62a9d08ec4..62ec2896d2 100644 --- a/assets/src/utils/status.ts +++ b/assets/src/utils/status.ts @@ -7,12 +7,13 @@ import { } from 'generated/graphql' import { ComponentProps } from 'react' -type ReadinessI = 'Ready' | 'InProgress' | 'Failed' | 'Complete' +type ReadinessI = 'Ready' | 'InProgress' | 'Failed' | 'Complete' | 'Running' export const Readiness = { Ready: 'Ready', InProgress: 'InProgress', Failed: 'Failed', Complete: 'Complete', + Running: 'Running', } as const satisfies Record export type ReadinessT = (typeof Readiness)[ReadinessI] @@ -21,6 +22,7 @@ export const readinessToLabel = { [Readiness.InProgress]: 'Pending', [Readiness.Failed]: 'Failed', [Readiness.Complete]: 'Complete', + [Readiness.Running]: 'Ready', } as const satisfies Record export const readinessToContainerLabel = { @@ -28,6 +30,7 @@ export const readinessToContainerLabel = { [Readiness.InProgress]: 'Pending', [Readiness.Failed]: 'Failed', [Readiness.Complete]: 'Complete', + [Readiness.Running]: 'Ready', } as const satisfies Record export const readinessToSeverity = { @@ -35,6 +38,7 @@ export const readinessToSeverity = { [Readiness.InProgress]: 'info', [Readiness.Failed]: 'critical', [Readiness.Complete]: 'neutral', + [Readiness.Running]: 'success', } as const satisfies Record['severity']> export const readinessToColor = { @@ -42,6 +46,7 @@ export const readinessToColor = { [Readiness.InProgress]: 'text-warning-light', [Readiness.Failed]: 'text-danger-light', [Readiness.Complete]: 'text-success-light', + [Readiness.Running]: 'text-success-light', } as const satisfies Record export function nodeStatusToReadiness(status: NodeStatus): ReadinessT {