Compare commits

...

4 Commits

Author SHA1 Message Date
github-actions[bot] 4468396e52 chore: release v0.1.3 2026-02-19 12:06:38 +00:00
github-actions[bot] ead81a51a9 chore: release v0.1.1 2026-02-19 12:05:27 +00:00
Chris Farhood 8e0b95ed64 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>
2026-02-19 06:53:54 -05:00
Chris Farhood e54caa7be4 fix: rename 'Rook Type' -> 'Type' and 'Cluster ID' -> 'Cluster' in column processors
Cleaner column headers that don't redundantly prefix with 'Rook'.

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-19 06:48:08 -05:00
3 changed files with 23 additions and 21 deletions
+3 -3
View File
@@ -1,4 +1,4 @@
version: "0.1.2"
version: "0.1.3"
name: headlamp-rook-ceph-plugin
displayName: Rook-Ceph Plugin
createdAt: "2026-02-18T00:00:00Z"
@@ -23,7 +23,7 @@ maintainers:
provider:
name: privilegedescalation
annotations:
headlamp/plugin/archive-url: "https://github.com/privilegedescalation/headlamp-rook-ceph-plugin/releases/download/v0.1.2/headlamp-rook-ceph-plugin-0.1.2.tar.gz"
headlamp/plugin/archive-checksum: "sha256:c74aef8dd3e67b66bd20ce4845d324ee351b3bb560b43a4a5fff26f31b3d73e1"
headlamp/plugin/archive-url: "https://github.com/privilegedescalation/headlamp-rook-ceph-plugin/releases/download/v0.1.3/headlamp-rook-ceph-plugin-0.1.3.tar.gz"
headlamp/plugin/archive-checksum: "sha256:01611912597b4739ca62cd1f4ae0dd42755bb8e3541dafa5dedbfdcf1202072e"
headlamp/plugin/distro-compat: ""
headlamp/plugin/version-compat: ">=0.20"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "headlamp-rook-ceph-plugin",
"version": "0.1.2",
"version": "0.1.3",
"description": "Headlamp plugin for Rook-Ceph cluster visibility and CSI driver monitoring",
"repository": {
"type": "git",
@@ -4,10 +4,14 @@
* Adds Rook-Ceph-specific columns to the native Headlamp StorageClass table
* ('headlamp-storageclasses') and PV table ('headlamp-persistentvolumes').
* 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 { formatStorageType, isRookCephProvisioner } from '../../api/k8s';
import { isRookCephProvisioner } from '../../api/k8s';
/** Safely read a nested field from either a KubeObject instance or plain object. */
function getField(item: unknown, ...path: string[]): unknown {
@@ -36,23 +40,26 @@ function isRookPvRow(item: unknown): boolean {
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() {
return [
{
label: 'Rook Type',
label: 'Protocol',
getValue: (item: unknown) => {
if (!isRookRow(item)) return null;
const provisioner = getField(item, 'provisioner') as string | undefined;
if (!provisioner) return null;
const type = provisioner.includes('.rbd.') ? 'rbd' : provisioner.includes('.cephfs.') ? 'cephfs' : 'unknown';
return formatStorageType(type as 'rbd' | 'cephfs' | 'unknown');
return rookProtocol(provisioner);
},
render: (item: unknown) => {
if (!isRookRow(item)) return <span></span>;
const provisioner = getField(item, 'provisioner') as string | undefined;
if (!provisioner) return <span></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>;
return <span>{rookProtocol(provisioner)}</span>;
},
},
{
@@ -65,13 +72,12 @@ export function buildStorageClassColumns() {
},
},
{
label: 'Cluster ID',
label: 'Cluster',
getValue: (item: unknown) => getField(item, 'parameters', 'clusterID') as string | null ?? null,
render: (item: unknown) => {
if (!isRookRow(item)) return <span></span>;
const clusterID = getField(item, 'parameters', 'clusterID') as string | undefined;
if (!clusterID) return <span></span>;
// Truncate long cluster IDs
return <span title={clusterID}>{clusterID.length > 16 ? `${clusterID.slice(0, 16)}` : clusterID}</span>;
},
},
@@ -81,20 +87,16 @@ export function buildStorageClassColumns() {
export function buildPVColumns() {
return [
{
label: 'Rook Type',
label: 'Protocol',
getValue: (item: unknown) => {
if (!isRookPvRow(item)) return null;
const driver = getField(item, 'spec', 'csi', 'driver') as string | undefined;
if (!driver) return null;
const type = driver.includes('.rbd.') ? 'rbd' : driver.includes('.cephfs.') ? 'cephfs' : 'unknown';
return formatStorageType(type as 'rbd' | 'cephfs' | 'unknown');
return rookProtocol(driver);
},
render: (item: unknown) => {
if (!isRookPvRow(item)) return <span></span>;
const driver = getField(item, 'spec', 'csi', 'driver') as string | undefined;
if (!driver) return <span></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>;
return <span>{rookProtocol(driver)}</span>;
},
},
{