/** * 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} /> )} )} ); }