/** * NodesPage — cluster nodes with kube-vip VIP assignments. * * Shows all nodes with their roles, readiness, kube-vip pod status, * and any VIP labels applied by kube-vip. */ import { Loader, NameValueTable, SectionBox, SectionHeader, SimpleTable, StatusLabel, } from '@kinvolk/headlamp-plugin/lib/CommonComponents'; import React from 'react'; import { formatAge, getNodeInternalIP, getNodeVipLabel, isControlPlaneNode, isNodeReady, phaseToStatus, } from '../api/k8s'; import { useKubeVipContext } from '../api/KubeVipDataContext'; export default function NodesPage() { const { nodes, kubeVipPods, leases, loading, error } = useKubeVipContext(); if (loading) { return ; } if (error) { return ( {error} }]} /> ); } // Build a map of node → kube-vip pod const podByNode = new Map(); for (const pod of kubeVipPods) { if (pod.spec?.nodeName) { podByNode.set(pod.spec.nodeName, pod); } } // Determine leader from leases const leaderIdentities = new Set(); for (const lease of leases) { if (lease.spec?.holderIdentity) { leaderIdentities.add(lease.spec.holderIdentity); } } const controlPlane = nodes.filter(isControlPlaneNode); const workers = nodes.filter(n => !isControlPlaneNode(n)); return ( <> {controlPlane.length > 0 && ( n.metadata.name }, { label: 'IP', getter: n => getNodeInternalIP(n) }, { label: 'Ready', getter: n => ( {isNodeReady(n) ? 'Ready' : 'NotReady'} ), }, { label: 'kube-vip Pod', getter: n => { const pod = podByNode.get(n.metadata.name); if (!pod) return '—'; return ( {pod.status?.phase ?? 'Unknown'} ); }, }, { label: 'Leader', getter: n => leaderIdentities.has(n.metadata.name) ? ( Leader ) : ( '—' ), }, { label: 'VIP Label', getter: n => getNodeVipLabel(n) ?? '—' }, { label: 'Kubelet', getter: n => n.status?.nodeInfo?.kubeletVersion ?? '—' }, { label: 'Age', getter: n => formatAge(n.metadata.creationTimestamp) }, ]} data={controlPlane} /> )} {workers.length > 0 && ( n.metadata.name }, { label: 'IP', getter: n => getNodeInternalIP(n) }, { label: 'Ready', getter: n => ( {isNodeReady(n) ? 'Ready' : 'NotReady'} ), }, { label: 'kube-vip Pod', getter: n => { const pod = podByNode.get(n.metadata.name); if (!pod) return '—'; return ( {pod.status?.phase ?? 'Unknown'} ); }, }, { label: 'Kubelet', getter: n => n.status?.nodeInfo?.kubeletVersion ?? '—' }, { label: 'Age', getter: n => formatAge(n.metadata.creationTimestamp) }, ]} data={workers} /> )} ); }