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:
2026-02-18 16:55:39 -05:00
commit 25175b65b8
30 changed files with 21588 additions and 0 deletions
+64
View File
@@ -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>
);
}