/**
* OverviewPage — main dashboard for the kube-vip plugin.
*
* Shows: deployment status, VIP mode, leader election, service/node counts,
* IP pool summary, and pod health.
*/
import {
Loader,
NameValueTable,
SectionBox,
SectionHeader,
SimpleTable,
StatusLabel,
} from '@kinvolk/headlamp-plugin/lib/CommonComponents';
import React from 'react';
import {
formatAge,
getServiceVIPs,
isControlPlaneNode,
isEgressEnabled,
isKubeVipService,
isPodReady,
phaseToStatus,
} from '../api/k8s';
import { useKubeVipContext } from '../api/KubeVipDataContext';
export default function OverviewPage() {
const {
kubeVipInstalled,
daemonSetStatus,
kubeVipPods,
cloudProviderPods,
loadBalancerServices,
nodes,
leases,
ipPools,
kubeVipConfig,
loading,
error,
refresh,
} = useKubeVipContext();
if (loading) {
return ;
}
const controlPlaneNodes = nodes.filter(isControlPlaneNode);
const readyPods = kubeVipPods.filter(isPodReady);
const kubeVipManaged = loadBalancerServices.filter(isKubeVipService);
const egressEnabled = loadBalancerServices.filter(isEgressEnabled);
// Detect mode from config
const mode =
kubeVipConfig['bgp_enable'] === 'true'
? 'BGP'
: kubeVipConfig['vip_arp'] === 'true'
? 'ARP'
: kubeVipPods.length > 0
? 'Unknown'
: '—';
const cpEnabled = kubeVipConfig['cp_enable'] === 'true';
const svcEnabled = kubeVipConfig['svc_enable'] === 'true';
const controlPlaneVIP = kubeVipConfig['address'] ?? '—';
// Find leader from leases
const cpLease = leases.find(l => l.metadata.name.startsWith('plndr-cp-lock'));
const svcLease = leases.find(l => l.metadata.name.startsWith('plndr-svcs-lock'));
const leaderNode = cpLease?.spec?.holderIdentity ?? svcLease?.spec?.holderIdentity ?? '—';
return (
<>
{!kubeVipInstalled && (
No kube-vip pods found in kube-system
),
},
{
name: 'Install',
value: 'See https://kube-vip.io/docs/installation/',
},
]}
/>
)}
{error && (
{error} }]}
/>
)}
{kubeVipInstalled && (
<>
0 ? 'success' : 'error'}>
{readyPods.length > 0 ? 'Running' : 'Unhealthy'}
),
},
{ name: 'Mode', value: mode },
{ name: 'Control Plane HA', value: cpEnabled ? 'Enabled' : 'Disabled' },
{ name: 'Service LoadBalancer', value: svcEnabled ? 'Enabled' : 'Disabled' },
...(cpEnabled ? [{ name: 'Control Plane VIP', value: controlPlaneVIP }] : []),
{ name: 'Leader', value: leaderNode },
{
name: 'Pods',
value: `${readyPods.length}/${kubeVipPods.length} ready`,
},
...(daemonSetStatus
? [
{
name: 'DaemonSet',
value: `${daemonSetStatus.numberReady ?? 0}/${
daemonSetStatus.desiredNumberScheduled ?? 0
} ready`,
},
]
: []),
...(cloudProviderPods.length > 0
? [
{
name: 'Cloud Provider',
value: (
{cloudProviderPods.length} pod(s)
),
},
]
: []),
]}
/>
0
? [
{
name: 'Egress Enabled',
value: String(egressEnabled.length),
},
]
: []),
{ name: 'IP Pools', value: String(ipPools.length) },
{ name: 'Leader Election Leases', value: String(leases.length) },
]}
/>
{ipPools.length > 0 && (
p.name },
{ label: 'Type', getter: p => p.type.toUpperCase() },
{ label: 'Value', getter: p => p.value },
{
label: 'Scope',
getter: p => (p.scope === 'namespace' ? p.namespace ?? '—' : 'Global'),
},
]}
data={ipPools}
/>
)}
{kubeVipPods.length > 0 && (
p.metadata.name },
{ label: 'Node', getter: p => p.spec?.nodeName ?? '—' },
{
label: 'Status',
getter: p => (
{p.status?.phase ?? 'Unknown'}
),
},
{
label: 'Ready',
getter: p => (isPodReady(p) ? 'Yes' : 'No'),
},
{ label: 'Age', getter: p => formatAge(p.metadata.creationTimestamp) },
]}
data={kubeVipPods}
/>
)}
{loadBalancerServices.length > 0 && (
s.metadata.name },
{ label: 'Namespace', getter: s => s.metadata.namespace ?? '—' },
{ label: 'VIP', getter: s => getServiceVIPs(s).join(', ') || '—' },
{
label: 'Ports',
getter: s =>
s.spec.ports
?.map(
(p: { port: number; protocol?: string }) =>
`${p.port}/${p.protocol ?? 'TCP'}`
)
.join(', ') ?? '—',
},
{ label: 'Age', getter: s => formatAge(s.metadata.creationTimestamp) },
]}
data={loadBalancerServices}
/>
)}
>
)}
>
);
}