fix: rename Type -> Protocol with RBD/CephFS values to match tns-csi convention
Both plugins now inject a 'Protocol' column into the shared native tables, so mixed-driver clusters see consistent naming. Rook values: RBD, CephFS. tns-csi values: NFS, NVMe-oF, iSCSI. Removes unused formatStorageType import from the column processor. 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:
@@ -4,10 +4,14 @@
|
|||||||
* Adds Rook-Ceph-specific columns to the native Headlamp StorageClass table
|
* Adds Rook-Ceph-specific columns to the native Headlamp StorageClass table
|
||||||
* ('headlamp-storageclasses') and PV table ('headlamp-persistentvolumes').
|
* ('headlamp-storageclasses') and PV table ('headlamp-persistentvolumes').
|
||||||
* Non-Rook-Ceph rows show '—'.
|
* Non-Rook-Ceph rows show '—'.
|
||||||
|
*
|
||||||
|
* Column names (Protocol, Pool) are intentionally shared with the tns-csi
|
||||||
|
* column processor so both plugins contribute to the same logical columns
|
||||||
|
* on a mixed-driver cluster.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { formatStorageType, isRookCephProvisioner } from '../../api/k8s';
|
import { isRookCephProvisioner } from '../../api/k8s';
|
||||||
|
|
||||||
/** Safely read a nested field from either a KubeObject instance or plain object. */
|
/** Safely read a nested field from either a KubeObject instance or plain object. */
|
||||||
function getField(item: unknown, ...path: string[]): unknown {
|
function getField(item: unknown, ...path: string[]): unknown {
|
||||||
@@ -36,23 +40,26 @@ function isRookPvRow(item: unknown): boolean {
|
|||||||
return typeof driver === 'string' && isRookCephProvisioner(driver);
|
return typeof driver === 'string' && isRookCephProvisioner(driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function rookProtocol(s: string | undefined): string {
|
||||||
|
if (!s) return '—';
|
||||||
|
if (s.includes('.rbd.')) return 'RBD';
|
||||||
|
if (s.includes('.cephfs.')) return 'CephFS';
|
||||||
|
return '—';
|
||||||
|
}
|
||||||
|
|
||||||
export function buildStorageClassColumns() {
|
export function buildStorageClassColumns() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: 'Type',
|
label: 'Protocol',
|
||||||
getValue: (item: unknown) => {
|
getValue: (item: unknown) => {
|
||||||
if (!isRookRow(item)) return null;
|
if (!isRookRow(item)) return null;
|
||||||
const provisioner = getField(item, 'provisioner') as string | undefined;
|
const provisioner = getField(item, 'provisioner') as string | undefined;
|
||||||
if (!provisioner) return null;
|
return rookProtocol(provisioner);
|
||||||
const type = provisioner.includes('.rbd.') ? 'rbd' : provisioner.includes('.cephfs.') ? 'cephfs' : 'unknown';
|
|
||||||
return formatStorageType(type as 'rbd' | 'cephfs' | 'unknown');
|
|
||||||
},
|
},
|
||||||
render: (item: unknown) => {
|
render: (item: unknown) => {
|
||||||
if (!isRookRow(item)) return <span>—</span>;
|
if (!isRookRow(item)) return <span>—</span>;
|
||||||
const provisioner = getField(item, 'provisioner') as string | undefined;
|
const provisioner = getField(item, 'provisioner') as string | undefined;
|
||||||
if (!provisioner) return <span>—</span>;
|
return <span>{rookProtocol(provisioner)}</span>;
|
||||||
const type = provisioner.includes('.rbd.') ? 'rbd' : provisioner.includes('.cephfs.') ? 'cephfs' : 'unknown';
|
|
||||||
return <span style={{ color: '#1976d2', fontWeight: 500 }}>{formatStorageType(type as 'rbd' | 'cephfs' | 'unknown')}</span>;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -71,7 +78,6 @@ export function buildStorageClassColumns() {
|
|||||||
if (!isRookRow(item)) return <span>—</span>;
|
if (!isRookRow(item)) return <span>—</span>;
|
||||||
const clusterID = getField(item, 'parameters', 'clusterID') as string | undefined;
|
const clusterID = getField(item, 'parameters', 'clusterID') as string | undefined;
|
||||||
if (!clusterID) return <span>—</span>;
|
if (!clusterID) return <span>—</span>;
|
||||||
// Truncate long cluster IDs
|
|
||||||
return <span title={clusterID}>{clusterID.length > 16 ? `${clusterID.slice(0, 16)}…` : clusterID}</span>;
|
return <span title={clusterID}>{clusterID.length > 16 ? `${clusterID.slice(0, 16)}…` : clusterID}</span>;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -81,20 +87,16 @@ export function buildStorageClassColumns() {
|
|||||||
export function buildPVColumns() {
|
export function buildPVColumns() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
label: 'Type',
|
label: 'Protocol',
|
||||||
getValue: (item: unknown) => {
|
getValue: (item: unknown) => {
|
||||||
if (!isRookPvRow(item)) return null;
|
if (!isRookPvRow(item)) return null;
|
||||||
const driver = getField(item, 'spec', 'csi', 'driver') as string | undefined;
|
const driver = getField(item, 'spec', 'csi', 'driver') as string | undefined;
|
||||||
if (!driver) return null;
|
return rookProtocol(driver);
|
||||||
const type = driver.includes('.rbd.') ? 'rbd' : driver.includes('.cephfs.') ? 'cephfs' : 'unknown';
|
|
||||||
return formatStorageType(type as 'rbd' | 'cephfs' | 'unknown');
|
|
||||||
},
|
},
|
||||||
render: (item: unknown) => {
|
render: (item: unknown) => {
|
||||||
if (!isRookPvRow(item)) return <span>—</span>;
|
if (!isRookPvRow(item)) return <span>—</span>;
|
||||||
const driver = getField(item, 'spec', 'csi', 'driver') as string | undefined;
|
const driver = getField(item, 'spec', 'csi', 'driver') as string | undefined;
|
||||||
if (!driver) return <span>—</span>;
|
return <span>{rookProtocol(driver)}</span>;
|
||||||
const type = driver.includes('.rbd.') ? 'rbd' : driver.includes('.cephfs.') ? 'cephfs' : 'unknown';
|
|
||||||
return <span style={{ color: '#1976d2', fontWeight: 500 }}>{formatStorageType(type as 'rbd' | 'cephfs' | 'unknown')}</span>;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user