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

3.1 KiB

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

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:

npm test        # tests across test files
npm run tsc     # must exit 0

Mock pattern for headlamp APIs:

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]) },
    },
  },
}));