feat: initial release of headlamp-rook-ceph-plugin v0.1.0
Headlamp plugin for Rook-Ceph cluster visibility. Pages: - Overview dashboard: CephCluster health, capacity bar, resource counts (block pools, filesystems, object stores, PVs, PVCs), daemon pod health summary, non-Bound PVC alerts - Block Pools: CephBlockPool table with replication, failure domain, mirroring; slide-in detail panel - Pods: all Rook-Ceph daemon pods grouped by role with ready/total counts Native Headlamp integrations: - StorageClass table: Rook Type, Pool, Cluster ID columns - PV table: Rook Type, Pool columns - PVC detail injection: driver, type, pool, volume handle - PV detail injection: CSI volume attributes - Pod detail injection: Ceph daemon role badge - App bar badge: cluster health (HEALTH_OK/WARN/ERR), color-coded API / architecture: - src/api/k8s.ts: types + filters for ceph.rook.io/v1 CRDs; handles both default rook-ceph.* and custom-namespace provisioner strings - src/api/RookCephDataContext.tsx: shared context provider; fetches CephCluster, CephBlockPool, CephFilesystem, CephObjectStore CRDs plus daemon pods via label selectors - 37 unit tests (vitest + @testing-library/react) - TypeScript strict mode, zero any types - CI + release GitHub Actions workflows Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* AppBarClusterBadge — registerAppBarAction cluster health badge.
|
||||
*
|
||||
* Displays "rook-ceph: HEALTH_OK" in the Headlamp top nav bar.
|
||||
* Color-coded: green=HEALTH_OK, orange=HEALTH_WARN, red=HEALTH_ERR.
|
||||
* Returns null if no CephCluster found (no clutter on unmanaged clusters).
|
||||
*
|
||||
* Wrapped in RookCephDataProvider at registration time (index.tsx).
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useRookCephContext } from '../api/RookCephDataContext';
|
||||
|
||||
function getHealthColor(health: string | undefined): string {
|
||||
switch (health) {
|
||||
case 'HEALTH_OK': return '#4caf50';
|
||||
case 'HEALTH_WARN': return '#ff9800';
|
||||
case 'HEALTH_ERR': return '#f44336';
|
||||
default: return '#9e9e9e';
|
||||
}
|
||||
}
|
||||
|
||||
export default function AppBarClusterBadge() {
|
||||
const { cephClusters, loading } = useRookCephContext();
|
||||
const history = useHistory();
|
||||
|
||||
if (loading || cephClusters.length === 0) return null;
|
||||
|
||||
const primary = cephClusters[0];
|
||||
const health = primary?.status?.ceph?.health;
|
||||
|
||||
const color = getHealthColor(health);
|
||||
const label = health ?? 'Unknown';
|
||||
const ariaLabel = `Rook-Ceph cluster health: ${label}`;
|
||||
|
||||
const handleClick = () => {
|
||||
history.push('/rook-ceph');
|
||||
};
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={handleClick}
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
marginRight: '8px',
|
||||
padding: '4px 12px',
|
||||
borderRadius: '16px',
|
||||
border: 'none',
|
||||
backgroundColor: color,
|
||||
color: 'white',
|
||||
fontSize: '13px',
|
||||
fontWeight: 500,
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
gap: '4px',
|
||||
}}
|
||||
aria-label={ariaLabel}
|
||||
title={ariaLabel}
|
||||
>
|
||||
<span>rook-ceph: {label}</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user