fix: remove unused imports and format source files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
DevContainer User
2026-03-04 01:06:13 +00:00
parent 71abc6792d
commit 3cebde0673
32 changed files with 902 additions and 426 deletions
+6 -2
View File
@@ -21,10 +21,14 @@ vi.mock('@kinvolk/headlamp-plugin/lib', () => ({
},
},
ConfigStore: class {
get() { return {}; }
get() {
return {};
}
set() {}
update() {}
useConfig() { return () => ({}); }
useConfig() {
return () => ({});
}
},
}));
+5 -3
View File
@@ -109,9 +109,9 @@ export function TnsCsiDataProvider({ children }: { children: React.ReactNode })
try {
// CSIDriver
try {
const driver = await ApiProxy.request(
const driver = (await ApiProxy.request(
`/apis/storage.k8s.io/v1/csidrivers/${TNS_CSI_PROVISIONER}`
) as CSIDriver;
)) as CSIDriver;
if (!cancelled) setCsiDriver(driver);
} catch {
if (!cancelled) setCsiDriver(null);
@@ -203,7 +203,9 @@ export function TnsCsiDataProvider({ children }: { children: React.ReactNode })
}
void fetchAsync();
return () => { cancelled = true; };
return () => {
cancelled = true;
};
}, [refreshKey]);
// ---------------------------------------------------------------------------
+6 -5
View File
@@ -28,7 +28,11 @@ function makeSc(name: string, provisioner: string, protocol = 'nfs'): TnsCsiStor
};
}
function makePv(name: string, driver: string, claimRef?: { name: string; namespace: string }): TnsCsiPersistentVolume {
function makePv(
name: string,
driver: string,
claimRef?: { name: string; namespace: string }
): TnsCsiPersistentVolume {
return {
metadata: { name },
spec: {
@@ -106,10 +110,7 @@ describe('isTnsCsiPersistentVolume', () => {
describe('filterTnsCsiPersistentVolumes', () => {
it('filters to only tns-csi PVs', () => {
const items = [
makePv('tns-pv', 'tns.csi.io'),
makePv('other-pv', 'ebs.csi.aws.com'),
];
const items = [makePv('tns-pv', 'tns.csi.io'), makePv('other-pv', 'ebs.csi.aws.com')];
const result = filterTnsCsiPersistentVolumes(items);
expect(result).toHaveLength(1);
expect(result[0]?.metadata.name).toBe('tns-pv');
+6 -10
View File
@@ -165,9 +165,7 @@ export function findBoundPv(
): TnsCsiPersistentVolume | undefined {
const ns = pvc.metadata.namespace ?? '';
const name = pvc.metadata.name;
return tnsPvs.find(
pv => pv.spec.claimRef?.namespace === ns && pv.spec.claimRef?.name === name
);
return tnsPvs.find(pv => pv.spec.claimRef?.namespace === ns && pv.spec.claimRef?.name === name);
}
// ---------------------------------------------------------------------------
@@ -216,15 +214,11 @@ export interface TnsCsiPod extends KubeObject {
}
export function isPodReady(pod: TnsCsiPod): boolean {
return (
pod.status?.conditions?.some(c => c.type === 'Ready' && c.status === 'True') ?? false
);
return pod.status?.conditions?.some(c => c.type === 'Ready' && c.status === 'True') ?? false;
}
export function getPodRestarts(pod: TnsCsiPod): number {
return (
pod.status?.containerStatuses?.reduce((sum, c) => sum + c.restartCount, 0) ?? 0
);
return pod.status?.containerStatuses?.reduce((sum, c) => sum + c.restartCount, 0) ?? 0;
}
export function getPodImage(pod: TnsCsiPod): string {
@@ -267,7 +261,9 @@ export function filterTnsCsiVolumeSnapshots(
tnsCsiSnapshotClassNames: Set<string>
): VolumeSnapshot[] {
return snapshots.filter(
s => s.spec?.volumeSnapshotClassName && tnsCsiSnapshotClassNames.has(s.spec.volumeSnapshotClassName)
s =>
s.spec?.volumeSnapshotClassName &&
tnsCsiSnapshotClassNames.has(s.spec.volumeSnapshotClassName)
);
}
+16 -3
View File
@@ -66,7 +66,12 @@ describe('generatePvcName', () => {
// ---------------------------------------------------------------------------
describe('buildPvcManifest', () => {
const opts = { jobName: 'kbench-test', pvcName: 'kbench-test-pvc', namespace: 'default', storageClass: 'tns-nfs' };
const opts = {
jobName: 'kbench-test',
pvcName: 'kbench-test-pvc',
namespace: 'default',
storageClass: 'tns-nfs',
};
it('produces a valid PVC manifest with correct storage class', () => {
const manifest = buildPvcManifest(opts) as Record<string, unknown>;
@@ -88,7 +93,12 @@ describe('buildPvcManifest', () => {
});
describe('buildJobManifest', () => {
const opts = { jobName: 'kbench-test', pvcName: 'kbench-test-pvc', namespace: 'default', storageClass: 'tns-nfs' };
const opts = {
jobName: 'kbench-test',
pvcName: 'kbench-test-pvc',
namespace: 'default',
storageClass: 'tns-nfs',
};
it('produces a valid Job manifest', () => {
const manifest = buildJobManifest(opts) as Record<string, unknown>;
@@ -109,7 +119,10 @@ describe('buildJobManifest', () => {
});
it('uses custom size and mode when specified', () => {
const manifest = buildJobManifest({ ...opts, size: '10G', mode: 'quick' }) as Record<string, unknown>;
const manifest = buildJobManifest({ ...opts, size: '10G', mode: 'quick' }) as Record<
string,
unknown
>;
const spec = manifest['spec'] as Record<string, unknown>;
const template = spec['template'] as Record<string, unknown>;
const podSpec = template['spec'] as Record<string, unknown>;
+36 -31
View File
@@ -22,7 +22,7 @@ export interface KbenchMetricGroup {
export interface KbenchResult {
iops: KbenchMetricGroup;
bandwidth: KbenchMetricGroup; // KiB/s
latency: KbenchMetricGroup; // nanoseconds
latency: KbenchMetricGroup; // nanoseconds
metadata: KbenchResultMetadata;
}
@@ -35,7 +35,14 @@ export interface KbenchResultMetadata {
namespace: string;
}
export type BenchmarkStatus = 'idle' | 'creating-pvc' | 'waiting-pvc' | 'running' | 'parsing' | 'complete' | 'failed';
export type BenchmarkStatus =
| 'idle'
| 'creating-pvc'
| 'waiting-pvc'
| 'running'
| 'parsing'
| 'complete'
| 'failed';
export type BenchmarkState =
| { status: 'idle' }
@@ -90,8 +97,8 @@ export interface KbenchJobOptions {
pvcName: string;
namespace: string;
storageClass: string;
size?: string; // default "30G"
mode?: string; // default "full"
size?: string; // default "30G"
mode?: string; // default "full"
}
export function buildPvcManifest(opts: KbenchJobOptions): object {
@@ -155,9 +162,7 @@ export function buildJobManifest(opts: KbenchJobOptions): object {
{ name: 'SIZE', value: opts.size ?? '30G' },
{ name: 'CPU_IDLE_PROF', value: 'disabled' },
],
volumeMounts: [
{ name: 'vol', mountPath: '/volume/' },
],
volumeMounts: [{ name: 'vol', mountPath: '/volume/' }],
},
],
restartPolicy: 'Never',
@@ -212,9 +217,9 @@ export async function getJobPhase(
jobName: string,
namespace: string
): Promise<{ phase: JobPhase; job: K8sJob }> {
const job = await ApiProxy.request(
const job = (await ApiProxy.request(
`/apis/batch/v1/namespaces/${namespace}/jobs/${jobName}`
) as K8sJob;
)) as K8sJob;
const status = job.status;
let phase: JobPhase = 'Unknown';
@@ -225,13 +230,10 @@ export async function getJobPhase(
return { phase, job };
}
export async function getPvcPhase(
pvcName: string,
namespace: string
): Promise<string> {
const pvc = await ApiProxy.request(
export async function getPvcPhase(pvcName: string, namespace: string): Promise<string> {
const pvc = (await ApiProxy.request(
`/api/v1/namespaces/${namespace}/persistentvolumeclaims/${pvcName}`
) as { status?: { phase?: string } };
)) as { status?: { phase?: string } };
return pvc.status?.phase ?? 'Unknown';
}
@@ -239,24 +241,23 @@ export async function getPvcPhase(
* Fetches the logs from the kbench pod (via the Job's pod selector).
* Uses the pod label selector to find the pod.
*/
export async function fetchKbenchLogs(
jobName: string,
namespace: string
): Promise<string> {
export async function fetchKbenchLogs(jobName: string, namespace: string): Promise<string> {
// Find pod with label kbench=fio and job-name=<jobName>
const podList = await ApiProxy.request(
`/api/v1/namespaces/${namespace}/pods?labelSelector=${encodeURIComponent(`job-name=${jobName}`)}`
) as { items?: Array<{ metadata?: { name?: string } }> };
const podList = (await ApiProxy.request(
`/api/v1/namespaces/${namespace}/pods?labelSelector=${encodeURIComponent(
`job-name=${jobName}`
)}`
)) as { items?: Array<{ metadata?: { name?: string } }> };
const podName = podList.items?.[0]?.metadata?.name;
if (!podName) {
throw new Error(`No pod found for kbench job "${jobName}"`);
}
const logs = await ApiProxy.request(
const logs = (await ApiProxy.request(
`/api/v1/namespaces/${namespace}/pods/${podName}/log?container=kbench`,
{ isJSON: false }
) as unknown;
)) as unknown;
if (typeof logs !== 'string') {
throw new Error('Pod logs were not returned as text');
@@ -274,10 +275,9 @@ export async function deleteJob(jobName: string, namespace: string): Promise<voi
}
export async function deletePvc(pvcName: string, namespace: string): Promise<void> {
await ApiProxy.request(
`/api/v1/namespaces/${namespace}/persistentvolumeclaims/${pvcName}`,
{ method: 'DELETE' }
);
await ApiProxy.request(`/api/v1/namespaces/${namespace}/persistentvolumeclaims/${pvcName}`, {
method: 'DELETE',
});
}
// ---------------------------------------------------------------------------
@@ -366,7 +366,7 @@ export function parseKbenchLog(logText: string): KbenchResult | null {
bandwidth,
latency,
metadata: {
storageClass: '', // filled in by the caller
storageClass: '', // filled in by the caller
size: '30G',
startedAt: '',
completedAt: new Date().toISOString(),
@@ -388,9 +388,14 @@ export async function listKbenchJobs(namespace: string = ''): Promise<KbenchJobS
? `/apis/batch/v1/namespaces/${namespace}/jobs?labelSelector=${selector}`
: `/apis/batch/v1/jobs?labelSelector=${selector}`;
const list = await ApiProxy.request(path) as {
const list = (await ApiProxy.request(path)) as {
items?: Array<{
metadata?: { name?: string; namespace?: string; annotations?: Record<string, string>; creationTimestamp?: string };
metadata?: {
name?: string;
namespace?: string;
annotations?: Record<string, string>;
creationTimestamp?: string;
};
status?: K8sJobStatus;
}>;
};
+1 -4
View File
@@ -218,10 +218,7 @@ export function sumSamples(samples: MetricSample[]): number {
}
/** Group samples by a label key, summing values per group. */
export function groupByLabel(
samples: MetricSample[],
labelKey: string
): Map<string, number> {
export function groupByLabel(samples: MetricSample[], labelKey: string): Map<string, number> {
const result = new Map<string, number>();
for (const sample of samples) {
const key = sample.labels[labelKey] ?? 'unknown';
+22 -17
View File
@@ -70,10 +70,7 @@ export interface PoolStats {
* @param apiKey - TrueNAS API key
* @returns Array of pool stats
*/
export function fetchTruenasPoolStats(
server: string,
apiKey: string
): Promise<PoolStats[]> {
export function fetchTruenasPoolStats(server: string, apiKey: string): Promise<PoolStats[]> {
return new Promise((resolve, reject) => {
// TrueNAS WebSocket endpoint — supports both SCALE and CORE
const url = `wss://${server}/api/current`;
@@ -99,12 +96,14 @@ export function fetchTruenasPoolStats(
ws.onopen = () => {
phase = 'authenticating';
ws.send(JSON.stringify({
id: msgId++,
msg: 'method',
method: 'auth.login_with_api_key',
params: [apiKey],
}));
ws.send(
JSON.stringify({
id: msgId++,
msg: 'method',
method: 'auth.login_with_api_key',
params: [apiKey],
})
);
};
ws.onmessage = (event: MessageEvent) => {
@@ -124,12 +123,14 @@ export function fetchTruenasPoolStats(
return;
}
phase = 'querying';
ws.send(JSON.stringify({
id: msgId++,
msg: 'method',
method: 'pool.query',
params: [],
}));
ws.send(
JSON.stringify({
id: msgId++,
msg: 'method',
method: 'pool.query',
params: [],
})
);
return;
}
@@ -162,7 +163,11 @@ export function fetchTruenasPoolStats(
ws.onerror = () => {
if (phase !== 'done') {
clearTimeout(timeout);
reject(new Error(`WebSocket error connecting to ${server} — check the server address and that TrueNAS is reachable`));
reject(
new Error(
`WebSocket error connecting to ${server} — check the server address and that TrueNAS is reachable`
)
);
}
};