/** * DriverStatusCard — reusable component showing tns-csi driver health. * Displays controller pods, node pods, CSIDriver capabilities, and * WebSocket connection health from Prometheus metrics. */ import { NameValueTable, SectionBox, StatusLabel, } from '@kinvolk/headlamp-plugin/lib/CommonComponents'; import React from 'react'; import type { CSIDriver, TnsCsiPod } from '../api/k8s'; import { formatAge, getPodImage, getPodRestarts, isPodReady } from '../api/k8s'; import type { TnsCsiMetrics } from '../api/metrics'; // --------------------------------------------------------------------------- // Sub-components // --------------------------------------------------------------------------- function WebSocketStatus({ metrics }: { metrics: TnsCsiMetrics | null }) { if (!metrics) { return Metrics unavailable; } const connected = metrics.websocketConnected; if (connected === null) { return Unknown; } return ( {connected === 1 ? 'Connected' : 'Disconnected'} ); } function PodStatusBadge({ pod }: { pod: TnsCsiPod }) { const ready = isPodReady(pod); const phase = pod.status?.phase ?? 'Unknown'; return ( {phase} ); } function PodRow({ pod }: { pod: TnsCsiPod }) { const name = pod.metadata.name; const node = pod.spec?.nodeName ?? '—'; const restarts = getPodRestarts(pod); const image = getPodImage(pod); const age = formatAge(pod.metadata.creationTimestamp); return ( }, { name: 'Restarts', value: String(restarts) }, { name: 'Image', value: image }, { name: 'Age', value: age }, ]} /> ); } // --------------------------------------------------------------------------- // Main component // --------------------------------------------------------------------------- interface DriverStatusCardProps { csiDriver: CSIDriver | null; controllerPods: TnsCsiPod[]; nodePods: TnsCsiPod[]; metrics?: TnsCsiMetrics | null; } export default function DriverStatusCard({ csiDriver, controllerPods, nodePods, metrics, }: DriverStatusCardProps) { const driverInstalled = csiDriver !== null; const allPodsReady = controllerPods.length > 0 && nodePods.length > 0 && [...controllerPods, ...nodePods].every(isPodReady); return ( <> {driverInstalled ? 'tns.csi.io installed' : 'Not detected'} ), }, { name: 'Overall Health', value: ( {allPodsReady ? 'Healthy' : 'Degraded'} ), }, { name: 'WebSocket', value: , }, ...(metrics?.websocketReconnectsTotal !== null && metrics?.websocketReconnectsTotal !== undefined ? [{ name: 'WS Reconnects', value: String(metrics.websocketReconnectsTotal) }] : []), ]} /> {csiDriver && ( )} {controllerPods.length > 0 && ( 1 ? 's' : ''}`}> {controllerPods.map(pod => ( ))} )} {controllerPods.length === 0 && ( No controller pod found }]} /> )} {nodePods.length > 0 && ( 1 ? 's' : ''} (${nodePods.length})`}> {nodePods.map(pod => ( ))} )} {nodePods.length === 0 && ( No node pods found }]} /> )} ); }