/** * ClusterStatusCard — reusable component showing Rook-Ceph cluster health. * Displays CephCluster health, phase, capacity, version, and daemon pod counts. */ import { NameValueTable, PercentageBar, SectionBox, StatusLabel, } from '@kinvolk/headlamp-plugin/lib/CommonComponents'; import React from 'react'; import type { CephCluster, RookCephPod } from '../api/k8s'; import { formatAge, formatBytes, getPodImage, getPodRestarts, healthToStatus, isPodReady, phaseToStatus, } from '../api/k8s'; interface ClusterStatusCardProps { cephClusters: CephCluster[]; operatorPods: RookCephPod[]; monPods: RookCephPod[]; osdPods: RookCephPod[]; mgrPods: RookCephPod[]; csiRbdPods: RookCephPod[]; csiCephfsPods: RookCephPod[]; } function PodStatusBadge({ pod }: { pod: RookCephPod }) { const ready = isPodReady(pod); const phase = pod.status?.phase ?? 'Unknown'; return {phase}; } function PodSummaryRow({ pods, label }: { pods: RookCephPod[]; label: string }) { const ready = pods.filter(isPodReady).length; const total = pods.length; const status = total === 0 ? 'error' : ready === total ? 'success' : ready > 0 ? 'warning' : 'error'; return { name: label, value: ( {total === 0 ? 'None found' : `${ready}/${total} ready`} ), }; } export default function ClusterStatusCard({ cephClusters, operatorPods, monPods, osdPods, mgrPods, csiRbdPods, csiCephfsPods, }: ClusterStatusCardProps) { return ( <> {cephClusters.map(cluster => { const health = cluster.status?.ceph?.health; const phase = cluster.status?.phase; const capacity = cluster.status?.ceph?.capacity; const version = cluster.status?.version?.version ?? '—'; const bytesTotal = capacity?.bytesTotal ?? 0; const bytesUsed = capacity?.bytesUsed ?? 0; const bytesAvail = capacity?.bytesAvailable ?? 0; const usedPct = bytesTotal > 0 ? Math.round((bytesUsed / bytesTotal) * 100) : 0; return ( {health ?? 'Unknown'} ), }, { name: 'Phase', value: ( {phase ?? 'Unknown'} ), }, ...(cluster.status?.message ? [{ name: 'Message', value: cluster.status.message }] : []), { name: 'Ceph Version', value: version }, { name: 'Namespace', value: cluster.metadata.namespace ?? '—' }, { name: 'Age', value: formatAge(cluster.metadata.creationTimestamp) }, ]} /> {bytesTotal > 0 && (
80 ? 'var(--mui-palette-error-main, #f44336)' : 'var(--mui-palette-primary-main, #1976d2)', }, { name: 'Free', value: bytesAvail, fill: 'var(--mui-palette-action-disabledBackground, #e0e0e0)', }, ]} total={bytesTotal} />
)}
); })} ); } export function PodDetailRows({ pods, label }: { pods: RookCephPod[]; label: string }) { if (pods.length === 0) { return ( No pods found }, ]} /> ); } return ( {pods.map(pod => ( }, { name: 'Restarts', value: String(getPodRestarts(pod)) }, { name: 'Image', value: getPodImage(pod) }, { name: 'Age', value: formatAge(pod.metadata.creationTimestamp) }, ]} /> ))} ); }