export function printSection(title, lines = []) { process.stdout.write(`\n${title}\n`); process.stdout.write(`${'-'.repeat(title.length)}\n`); for (const line of lines) { process.stdout.write(`${line}\n`); } } export function formatStatusSummary(status) { if (!status) { return [ 'Site: unknown', 'Node IP: unknown', 'Connectivity: unknown', 'Selected release: unknown', ]; } const lines = [ `Site: ${status.siteId}`, `Node IP: ${status.nodeIp || 'unknown'}`, `Connectivity: ${status.connectivityMode}`, `Selected release: ${status.release.selectedReleaseVersion || 'unknown'}`, ]; if (status.canonical?.rollup?.state) { lines.push(`Rollup: ${status.canonical.rollup.state}`); } return lines; } export function formatStatusReport(status) { if (!status) { return { summary: [ 'Site: unknown', 'Node IP: unknown', 'Connectivity: unknown', 'Top blocker: status unavailable', 'Blocker detail: Unable to collect appliance status yet.', 'Next action: Verify site selection and cluster connectivity, then refresh status.', ], host: [ 'Status: unknown', 'Detail: Talos status not collected', ], cluster: [ 'API reachable: false', 'Status: unavailable', ], flux: [ 'Flux status: unavailable', 'Helm status: unavailable', ], workloads: [ 'Workload status: unavailable', ], release: [ 'Selected release: unknown', 'App URL: unknown', 'Release app version: unknown', 'Release branch: unknown', 'Desired server image: unknown', 'Actual server image: unknown', ], paths: [ 'Config dir: unknown', 'kubeconfig: unknown', 'talosconfig: unknown', ], }; } return { summary: [ `Site: ${status.siteId}`, `Node IP: ${status.nodeIp || 'unknown'}`, `Connectivity: ${status.connectivityMode}`, ...(status.canonical?.rollup?.state ? [`Rollup: ${status.canonical.rollup.state}`] : []), ...(status.canonical?.rollup?.message ? [`Rollup detail: ${status.canonical.rollup.message}`] : []), `Top blocker: ${status.topBlocker.layer}`, `Blocker detail: ${status.topBlocker.reason}`, `Next action: ${status.topBlocker.nextAction}`, ], host: [ `Status: ${status.host.status}`, `Detail: ${status.host.details || 'n/a'}`, ], cluster: [ `API reachable: ${status.cluster.apiReachable}`, `Status: ${status.cluster.status}`, ...status.cluster.nodeReadiness.map((node) => `Node ${node.name}: ${node.ready ? 'Ready' : 'NotReady'} ${node.message || ''}`.trim(), ), ], flux: [ `Flux status: ${status.flux.status}`, `Helm status: ${status.flux.helmStatus}`, ...status.flux.sources.map((entry) => `Flux source ${entry.name}: ${entry.status}`), ...status.flux.kustomizations.map((entry) => `Kustomization ${entry.name}: ${entry.status}`), ...status.flux.helmReleases.map((entry) => `HelmRelease ${entry.name}: ${entry.status}`), ], workloads: [ `Workload status: ${status.workloads.status}`, ...(status.canonical?.tiers ? [ `Tier platform: ${status.canonical.tiers.platform.ready ? 'ready' : 'not-ready'}`, `Tier core: ${status.canonical.tiers.core.ready ? 'ready' : 'not-ready'}`, `Tier bootstrap: ${status.canonical.tiers.bootstrap.ready ? 'ready' : 'not-ready'}`, `Tier login: ${status.canonical.tiers.login.ready ? 'ready' : 'not-ready'}`, `Tier background: ${status.canonical.tiers.background.ready ? 'ready' : 'not-ready'}`, `Tier fullHealth: ${status.canonical.tiers.fullHealth.ready ? 'ready' : 'not-ready'}`, ] : []), ...status.workloads.components.map((entry) => `${entry.name}: ${entry.status} (${entry.ready})${entry.message ? ` - ${entry.message}` : ''}`, ), ], release: [ `Selected channel: ${status.release.selectedChannel || 'none'}`, `Selected release: ${status.release.selectedReleaseVersion || 'unknown'}`, `App URL: ${status.release.appUrl || 'unknown'}`, `Release app version: ${status.release.appVersion || 'unknown'}`, `Release manifest: ${status.release.manifestDigest || 'unknown'}`, `Desired server image: ${status.release.desiredImages?.serverImage || 'unknown'}`, `Actual server image: ${status.release.actualImages?.serverImage || 'unknown'}`, ...(status.release.imageDrift?.detected ? ['Release drift: desired and actual alga-core images differ'] : []), ], paths: [ `Config dir: ${status.configPaths.configDir}`, `kubeconfig: ${status.configPaths.kubeconfig}`, `talosconfig: ${status.configPaths.talosconfig}`, ], }; }