feat: native Headlamp integration, TrueNAS API, docs, and CI for v0.2.0

Native Headlamp integrations:
- registerResourceTableColumnsProcessor: add Protocol/Pool/Server columns to
  native StorageClass table and Protocol/Volume Handle to PV table
- registerDetailsViewSection: inject TNS-CSI section into PV detail pages
- registerDetailsViewSection: inject driver role/status into tns-csi Pod pages
- registerDetailsViewHeaderAction: Benchmark shortcut on StorageClass detail
- registerAppBarAction: driver health badge (N/Nc M/Mn, color-coded)
- Trim sidebar from 6 → 4 entries (Overview, Snapshots, Metrics, Benchmark)

TrueNAS API integration:
- src/api/truenas.ts: ConfigStore-backed settings, WebSocket JSON-RPC client
  for pool.query (auth.login_with_api_key + pool.query)
- src/components/TnsCsiSettings.tsx: API key + server override settings UI
  with connection test button
- TnsCsiDataContext: fetch real pool stats (size/allocated/free/status)
- OverviewPage: three-tier pool capacity display (real data → error → metrics
  fallback)

Documentation:
- README, CHANGELOG, CONTRIBUTING, SECURITY
- docs/: architecture, deployment (Helm), getting-started, user-guide,
  troubleshooting

CI:
- .github/workflows/ci.yaml: lint + type-check + test on PR/push
- .github/workflows/release.yaml: workflow_dispatch versioned release

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:37:56 -05:00
parent f2f3c3a87e
commit f1feb5c2f7
30 changed files with 3540 additions and 44 deletions
+71 -35
View File
@@ -1,34 +1,44 @@
/**
* headlamp-tns-csi-plugin — entry point.
*
* Registers sidebar entries, routes, detail view section, and plugin settings
* for the tns-csi CSI driver Headlamp plugin.
* Registers sidebar entries, routes, detail view sections, table column
* processors, header actions, and app bar action for the tns-csi CSI driver.
*/
import {
registerAppBarAction,
registerDetailsViewHeaderAction,
registerDetailsViewSection,
registerPluginSettings,
registerResourceTableColumnsProcessor,
registerRoute,
registerSidebarEntry,
} from '@kinvolk/headlamp-plugin/lib';
import React from 'react';
import { TnsCsiDataProvider } from './api/TnsCsiDataContext';
import AppBarDriverBadge from './components/AppBarDriverBadge';
import TnsCsiSettings from './components/TnsCsiSettings';
import BenchmarkPage from './components/BenchmarkPage';
import DriverPodDetailSection from './components/DriverPodDetailSection';
import { buildPVColumns, buildStorageClassColumns } from './components/integrations/StorageClassColumns';
import StorageClassBenchmarkButton from './components/integrations/StorageClassBenchmarkButton';
import MetricsPage from './components/MetricsPage';
import OverviewPage from './components/OverviewPage';
import PVCDetailSection from './components/PVCDetailSection';
import PVDetailSection from './components/PVDetailSection';
import SnapshotsPage from './components/SnapshotsPage';
import StorageClassesPage from './components/StorageClassesPage';
import VolumesPage from './components/VolumesPage';
// ---------------------------------------------------------------------------
// Sidebar entries
// Sidebar entries (trimmed from 6 to 4 — Storage Classes and Volumes now
// surface via native Headlamp tables with injected columns/sections)
// ---------------------------------------------------------------------------
registerSidebarEntry({
parent: null,
name: 'tns-csi',
label: 'TrueNAS',
label: 'TrueNAS (tns-csi)',
url: '/tns-csi',
icon: 'mdi:database-cog',
});
@@ -41,22 +51,6 @@ registerSidebarEntry({
icon: 'mdi:view-dashboard',
});
registerSidebarEntry({
parent: 'tns-csi',
name: 'tns-csi-storage-classes',
label: 'Storage Classes',
url: '/tns-csi/storage-classes',
icon: 'mdi:database',
});
registerSidebarEntry({
parent: 'tns-csi',
name: 'tns-csi-volumes',
label: 'Volumes',
url: '/tns-csi/volumes',
icon: 'mdi:harddisk',
});
registerSidebarEntry({
parent: 'tns-csi',
name: 'tns-csi-snapshots',
@@ -82,7 +76,7 @@ registerSidebarEntry({
});
// ---------------------------------------------------------------------------
// Routes
// Routes (keep all routes so direct links still work)
// ---------------------------------------------------------------------------
registerRoute({
@@ -97,9 +91,11 @@ registerRoute({
),
});
// Routes for storage-classes and volumes are kept for direct URL access
// but are no longer in the sidebar — native Headlamp tables have tns-csi columns.
registerRoute({
path: '/tns-csi/storage-classes',
sidebar: 'tns-csi-storage-classes',
sidebar: 'tns-csi-overview',
name: 'tns-csi-storage-classes',
exact: true,
component: () => (
@@ -111,7 +107,7 @@ registerRoute({
registerRoute({
path: '/tns-csi/volumes',
sidebar: 'tns-csi-volumes',
sidebar: 'tns-csi-overview',
name: 'tns-csi-volumes',
exact: true,
component: () => (
@@ -158,7 +154,7 @@ registerRoute({
});
// ---------------------------------------------------------------------------
// PVC detail view injection
// Detail view section — PVC pages
// ---------------------------------------------------------------------------
registerDetailsViewSection(({ resource }) => {
@@ -171,19 +167,59 @@ registerDetailsViewSection(({ resource }) => {
);
});
// ---------------------------------------------------------------------------
// Detail view section — PV pages
// ---------------------------------------------------------------------------
registerDetailsViewSection(({ resource }) => {
if (resource?.kind !== 'PersistentVolume') return null;
return <PVDetailSection resource={resource} />;
});
// ---------------------------------------------------------------------------
// Detail view section — Pod pages (tns-csi driver pods only)
// ---------------------------------------------------------------------------
registerDetailsViewSection(({ resource }) => {
if (resource?.kind !== 'Pod') return null;
return <DriverPodDetailSection resource={resource} />;
});
// ---------------------------------------------------------------------------
// Table column processors — native StorageClass and PV tables
// ---------------------------------------------------------------------------
registerResourceTableColumnsProcessor(({ id, columns }) => {
if (id === 'headlamp-storageclasses') {
return [...columns, ...buildStorageClassColumns()];
}
if (id === 'headlamp-persistentvolumes') {
return [...columns, ...buildPVColumns()];
}
return columns;
});
// ---------------------------------------------------------------------------
// Header action — StorageClass detail page Benchmark shortcut
// ---------------------------------------------------------------------------
registerDetailsViewHeaderAction(({ resource }) => {
if (resource?.kind !== 'StorageClass') return null;
return <StorageClassBenchmarkButton resource={resource} />;
});
// ---------------------------------------------------------------------------
// App bar action — driver health badge
// ---------------------------------------------------------------------------
registerAppBarAction(() => (
<TnsCsiDataProvider>
<AppBarDriverBadge />
</TnsCsiDataProvider>
));
// ---------------------------------------------------------------------------
// Plugin settings
// ---------------------------------------------------------------------------
function TnsCsiSettings() {
return (
<div style={{ padding: '16px' }}>
<p style={{ color: 'var(--mui-palette-text-secondary)' }}>
TNS-CSI plugin settings. Configure defaults below.
</p>
{/* Future: default namespace, metrics refresh interval, auto-cleanup setting */}
</div>
);
}
registerPluginSettings('headlamp-tns-csi-plugin', TnsCsiSettings, true);