f1feb5c2f7
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>
74 lines
2.1 KiB
TypeScript
74 lines
2.1 KiB
TypeScript
/**
|
|
* StorageClassBenchmarkButton — registerDetailsViewHeaderAction for StorageClass pages.
|
|
*
|
|
* Adds a "Benchmark" button to the detail page header of tns-csi StorageClasses.
|
|
* Navigates to /tns-csi/benchmark so the user can run a FIO benchmark
|
|
* against that storage class.
|
|
*/
|
|
|
|
import React from 'react';
|
|
import { useHistory } from 'react-router-dom';
|
|
import { TNS_CSI_PROVISIONER } from '../../api/k8s';
|
|
|
|
interface StorageClassBenchmarkButtonProps {
|
|
resource: {
|
|
provisioner?: string;
|
|
metadata?: { name?: string };
|
|
// KubeObject instance — provisioner may be a direct getter or under jsonData
|
|
jsonData?: {
|
|
provisioner?: string;
|
|
metadata?: { name?: string };
|
|
};
|
|
};
|
|
}
|
|
|
|
export default function StorageClassBenchmarkButton({ resource }: StorageClassBenchmarkButtonProps) {
|
|
const history = useHistory();
|
|
|
|
// provisioner is one of the fields Headlamp's StorageClass class exposes as a getter,
|
|
// so it's accessible directly. jsonData fallback for safety.
|
|
const provisioner =
|
|
resource?.provisioner ??
|
|
resource?.jsonData?.provisioner;
|
|
|
|
if (provisioner !== TNS_CSI_PROVISIONER) {
|
|
return null;
|
|
}
|
|
|
|
const scName =
|
|
resource?.metadata?.name ??
|
|
resource?.jsonData?.metadata?.name ??
|
|
'';
|
|
|
|
const handleClick = () => {
|
|
// Navigate to benchmark page; user selects the SC in the benchmark form.
|
|
// Pass the SC name via hash so BenchmarkPage can pre-select it if desired.
|
|
history.push(`/tns-csi/benchmark#${scName}`);
|
|
};
|
|
|
|
return (
|
|
<button
|
|
onClick={handleClick}
|
|
style={{
|
|
cursor: 'pointer',
|
|
padding: '6px 16px',
|
|
borderRadius: '4px',
|
|
border: '1px solid currentColor',
|
|
backgroundColor: 'transparent',
|
|
color: 'inherit',
|
|
fontSize: '0.875rem',
|
|
fontWeight: 500,
|
|
display: 'inline-flex',
|
|
alignItems: 'center',
|
|
gap: '6px',
|
|
opacity: 0.85,
|
|
}}
|
|
aria-label={`Run benchmark on ${scName}`}
|
|
title={`Run FIO benchmark on storage class ${scName}`}
|
|
>
|
|
<span>⚡</span>
|
|
<span>Benchmark</span>
|
|
</button>
|
|
);
|
|
}
|