Files
headlamp-rook-plugin/CLAUDE.md
T
Chris Farhood 25175b65b8 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>
2026-02-18 16:55:39 -05:00

89 lines
3.1 KiB
Markdown

# headlamp-rook-ceph-plugin
Headlamp plugin for Rook-Ceph cluster visibility.
## Project
- **Plugin name**: `headlamp-rook-ceph-plugin`
- **Rook-Ceph API group**: `ceph.rook.io/v1`
- **Default namespace**: `rook-ceph`
- **RBD provisioner**: `rook-ceph.rbd.csi.ceph.com`
- **CephFS provisioner**: `rook-ceph.cephfs.csi.ceph.com`
- **Reference plugin**: `../headlamp-tns-csi-plugin`
## Commands
```bash
npm start # dev server with hot reload
npm run build # production build
npm run package # package for headlamp
npm run tsc # TypeScript type check (no emit)
npm run lint # ESLint
npm test # vitest run
npm run test:watch # vitest watch mode
```
## Architecture
```
src/
├── index.tsx # Plugin entry: registerRoute, registerSidebarEntry, etc.
├── api/
│ ├── k8s.ts # Types + filtering helpers (ceph.rook.io)
│ └── RookCephDataContext.tsx # Shared React context provider
└── components/
├── OverviewPage.tsx
├── BlockPoolsPage.tsx
├── StorageClassesPage.tsx
├── VolumesPage.tsx
├── PodsPage.tsx
├── ClusterStatusCard.tsx
├── AppBarClusterBadge.tsx
├── PVCDetailSection.tsx # Injected into Headlamp PVC detail view
├── PVDetailSection.tsx # Injected into Headlamp PV detail view
├── CephPodDetailSection.tsx # Injected into Headlamp Pod detail view
└── integrations/
└── StorageClassColumns.tsx # Column processors for SC + PV tables
```
## Key constants (src/api/k8s.ts)
- Namespace: `rook-ceph`
- API group: `ceph.rook.io/v1`
- RBD provisioner: `rook-ceph.rbd.csi.ceph.com`
- CephFS provisioner: `rook-ceph.cephfs.csi.ceph.com`
- Custom namespace provisioners: any string ending in `.rbd.csi.ceph.com` or `.cephfs.csi.ceph.com`
- Pod selectors: `app=rook-ceph-operator`, `app=rook-ceph-mon`, `app=rook-ceph-osd`, `app=rook-ceph-mgr`, `app=csi-rbdplugin-provisioner`, `app=csi-cephfsplugin-provisioner`
## Code conventions
- Functional React components only — no class components
- All imports from `@kinvolk/headlamp-plugin/lib` and `@kinvolk/headlamp-plugin/lib/CommonComponents`
- No additional UI libraries (no MUI direct imports, no Ant Design, etc.)
- TypeScript strict mode — no `any`, use `unknown` + type guards at API boundaries
- Context provider (`RookCephDataProvider`) wraps each route component in `index.tsx`
- Tests: vitest + @testing-library/react, mock with `vi.mock('@kinvolk/headlamp-plugin/lib', ...)`
## Testing
All tests must pass before committing:
```bash
npm test # tests across test files
npm run tsc # must exit 0
```
Mock pattern for headlamp APIs:
```typescript
vi.mock('@kinvolk/headlamp-plugin/lib', () => ({
ApiProxy: { request: vi.fn().mockResolvedValue({ items: [] }) },
K8s: {
ResourceClasses: {
StorageClass: { useList: vi.fn(() => [[], null]) },
PersistentVolume: { useList: vi.fn(() => [[], null]) },
PersistentVolumeClaim: { useList: vi.fn(() => [[], null]) },
},
},
}));
```