From 87b59082887902af24ad2bf88ae3d4d4c941411e Mon Sep 17 00:00:00 2001 From: Anso Date: Fri, 3 Apr 2026 01:39:22 -0400 Subject: [PATCH] feat(fleet): add remote node update management (#353) Add the ability to check for outdated nodes and trigger over-the-air updates from Fleet View. Nodes self-update by pulling the latest Docker image and recreating their container via the "last breath" pattern. Backend: - SelfUpdateService: self-container identification via HOSTNAME + Docker Compose labels, triggers pull + force-recreate - CapabilityRegistry: runtime capability disabling via disableCapability() - POST /api/system/update (202 + deferred self-update) - GET /api/fleet/update-status (version comparison across fleet) - POST /api/fleet/nodes/:nodeId/update (single node) - POST /api/fleet/update-all (bulk remote update) - In-memory update tracker with 5-min timeout Frontend: - Node Updates modal with summary stats, search filter, table layout, per-node Update buttons, and bulk Update All - Version badges and update-available indicators on node cards - ReconnectingOverlay for local node updates (polls /api/health) - 5s fast-poll when any node is actively updating - UpdateStatusBadge shared component for consistent badge rendering Requires Skipper (Pro) tier. Nodes must be deployed via Docker Compose with Docker socket access. --- CHANGELOG.md | 6 + backend/package-lock.json | 8 + backend/package.json | 2 + backend/src/index.ts | 213 +++++++- backend/src/services/CapabilityRegistry.ts | 14 + backend/src/services/SelfUpdateService.ts | 87 ++++ docs/docs.json | 7 +- docs/features/remote-updates.mdx | 93 ++++ docs/images/fleet/check-updates-modal.png | Bin 0 -> 32334 bytes docs/images/fleet/fleet-update-available.png | Bin 0 -> 92313 bytes docs/openapi.yaml | 145 ++++++ frontend/src/components/FleetView.tsx | 484 ++++++++++++++++++- frontend/src/lib/capabilities.ts | 1 + 13 files changed, 1039 insertions(+), 21 deletions(-) create mode 100644 backend/src/services/SelfUpdateService.ts create mode 100644 docs/features/remote-updates.mdx create mode 100644 docs/images/fleet/check-updates-modal.png create mode 100644 docs/images/fleet/fleet-update-available.png diff --git a/CHANGELOG.md b/CHANGELOG.md index a5537ef3..8f35e862 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Added + +* **fleet:** remote node update management (Pro tier) — check for outdated nodes and trigger over-the-air updates from Fleet View. Nodes self-update by pulling the latest Docker image and recreating their container. Includes version badges on node cards, per-node and bulk "Update All" actions, real-time progress tracking with 5-second polling, reconnecting overlay for local node updates, and `POST /api/system/update` endpoint for programmatic self-updates. Requires Docker Compose deployment with Docker socket access. + ## [0.32.0](https://github.com/AnsoCode/Sencho/compare/v0.31.0...v0.32.0) (2026-04-03) diff --git a/backend/package-lock.json b/backend/package-lock.json index 48798f1d..db57efd1 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -14,6 +14,7 @@ "@types/dockerode": "^4.0.1", "@types/express": "^5.0.6", "@types/http-proxy": "^1.17.17", + "@types/semver": "^7.7.1", "@types/ws": "^8.18.1", "axios": "^1.13.6", "bcrypt": "^6.0.0", @@ -32,6 +33,7 @@ "ldapts": "^8.1.7", "node-pty": "^1.1.0", "openid-client": "^5.7.1", + "semver": "^7.7.4", "systeminformation": "^5.31.1", "ws": "^8.19.0", "yaml": "^2.8.2", @@ -2204,6 +2206,12 @@ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", "license": "MIT" }, + "node_modules/@types/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", + "license": "MIT" + }, "node_modules/@types/send": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", diff --git a/backend/package.json b/backend/package.json index d7f58a24..51925e09 100644 --- a/backend/package.json +++ b/backend/package.json @@ -38,6 +38,7 @@ "@types/dockerode": "^4.0.1", "@types/express": "^5.0.6", "@types/http-proxy": "^1.17.17", + "@types/semver": "^7.7.1", "@types/ws": "^8.18.1", "axios": "^1.13.6", "bcrypt": "^6.0.0", @@ -56,6 +57,7 @@ "ldapts": "^8.1.7", "node-pty": "^1.1.0", "openid-client": "^5.7.1", + "semver": "^7.7.4", "systeminformation": "^5.31.1", "ws": "^8.19.0", "yaml": "^2.8.2", diff --git a/backend/src/index.ts b/backend/src/index.ts index f41f6f66..2dd9c1e3 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -30,7 +30,9 @@ import { WebhookService } from './services/WebhookService'; import { SSOService } from './services/SSOService'; import { SchedulerService } from './services/SchedulerService'; import { RegistryService } from './services/RegistryService'; -import { CAPABILITIES, getSenchoVersion, fetchRemoteMeta } from './services/CapabilityRegistry'; +import { CAPABILITIES, getSenchoVersion, fetchRemoteMeta, getActiveCapabilities } from './services/CapabilityRegistry'; +import SelfUpdateService from './services/SelfUpdateService'; +import semver from 'semver'; import { CronExpressionParser } from 'cron-parser'; import { isValidStackName, isValidRemoteUrl, isPathWithinBase } from './utils/validation'; import YAML from 'yaml'; @@ -323,7 +325,7 @@ app.get('/api/health', (_req: Request, res: Response): void => { // Public meta endpoint - returns this instance's version and supported capabilities. // No auth required (like /health). Used by remote nodes during connection tests. app.get('/api/meta', (_req: Request, res: Response): void => { - res.json({ version: getSenchoVersion(), capabilities: CAPABILITIES }); + res.json({ version: getSenchoVersion(), capabilities: getActiveCapabilities() }); }); // Auth Routes (no authentication required) @@ -1032,8 +1034,36 @@ app.post('/api/license/validate', async (_req: Request, res: Response): Promise< } }); +// --- Self-Update --- + +/** Respond 202 and trigger the "last breath" self-update after the response flushes. */ +function scheduleLocalUpdate(res: Response, message: string): void { + res.status(202).json({ message }); + res.on('finish', () => { + setTimeout(() => SelfUpdateService.getInstance().triggerUpdate(), 500); + }); +} + +app.post('/api/system/update', (_req: Request, res: Response): void => { + if (!SelfUpdateService.getInstance().isAvailable()) { + res.status(503).json({ error: 'Self-update unavailable. Sencho must be deployed via Docker Compose.' }); + return; + } + scheduleLocalUpdate(res, 'Update initiated. The server will restart shortly.'); +}); + // --- Fleet Overview (local-only, aggregates all nodes) --- +// In-memory tracker for remote node updates (transient — lost on gateway restart) +interface UpdateTracker { + status: 'updating' | 'completed' | 'timeout' | 'failed'; + startedAt: number; + previousVersion: string | null; + error?: string; +} +const updateTracker = new Map(); +const UPDATE_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes + interface FleetNodeOverview { id: number; name: string; @@ -1171,6 +1201,182 @@ app.get('/api/fleet/node/:nodeId/stacks/:stackName/containers', async (req: Requ } }); +// Fleet Update Status — returns version comparison and active update status for all nodes +app.get('/api/fleet/update-status', async (_req: Request, res: Response): Promise => { + if (!requirePro(_req, res)) return; + try { + const db = DatabaseService.getInstance(); + const nodes = db.getNodes(); + const gatewayVersion = getSenchoVersion(); + + const results = await Promise.allSettled( + nodes.map(async (node) => { + const tracker = updateTracker.get(node.id); + + let version: string | null = null; + if (node.type === 'local') { + version = gatewayVersion; + } else if (node.api_url && node.api_token) { + const meta = await fetchRemoteMeta(node.api_url, node.api_token); + version = meta.version; + } + + // For nodes actively updating, check if they've come back with a new version + if (tracker?.status === 'updating') { + if (Date.now() - tracker.startedAt > UPDATE_TIMEOUT_MS) { + updateTracker.set(node.id, { ...tracker, status: 'timeout' }); + } else if (node.type === 'remote' && version && version !== tracker.previousVersion) { + updateTracker.set(node.id, { ...tracker, status: 'completed' }); + } + } + + const currentTracker = updateTracker.get(node.id); + return { + nodeId: node.id, + name: node.name, + type: node.type, + version, + latestVersion: gatewayVersion, + updateAvailable: version === null + ? (node.type === 'remote') // Remote node without /api/meta is pre-capability-negotiation — definitely outdated + : (version !== gatewayVersion && !!semver.valid(version) && semver.lt(version, gatewayVersion)), + updateStatus: currentTracker?.status ?? null, + }; + }) + ); + + const nodeStatuses = results.map((r, i) => { + if (r.status === 'fulfilled') return r.value; + return { + nodeId: nodes[i].id, + name: nodes[i].name, + type: nodes[i].type, + version: null, + latestVersion: gatewayVersion, + updateAvailable: false, + updateStatus: null, + }; + }); + + res.json({ nodes: nodeStatuses }); + } catch (error) { + console.error('[Fleet] Update status error:', error); + res.status(500).json({ error: 'Failed to fetch update status' }); + } +}); + +// Trigger update on a specific node +app.post('/api/fleet/nodes/:nodeId/update', async (req: Request, res: Response): Promise => { + if (!requirePro(req, res)) return; + try { + const nodeId = parseInt(req.params.nodeId as string, 10); + const db = DatabaseService.getInstance(); + const node = db.getNode(nodeId); + if (!node) { + res.status(404).json({ error: 'Node not found' }); + return; + } + + const existing = updateTracker.get(nodeId); + if (existing?.status === 'updating') { + res.status(409).json({ error: 'Update already in progress for this node.' }); + return; + } + + if (node.type === 'local') { + if (!SelfUpdateService.getInstance().isAvailable()) { + res.status(503).json({ error: 'Self-update unavailable on the local node.' }); + return; + } + updateTracker.set(nodeId, { status: 'updating', startedAt: Date.now(), previousVersion: getSenchoVersion() }); + scheduleLocalUpdate(res, 'Update initiated on local node. The server will restart shortly.'); + return; + } + + // Remote node + if (!node.api_url || !node.api_token) { + res.status(503).json({ error: 'Remote node not configured.' }); + return; + } + + // Check remote capabilities + const meta = await fetchRemoteMeta(node.api_url, node.api_token); + if (!meta.capabilities.includes('self-update')) { + res.status(503).json({ error: 'Remote node does not support self-update. It may need to be updated manually first.' }); + return; + } + + // Trigger remote update + const response = await fetch(`${node.api_url.replace(/\/$/, '')}/api/system/update`, { + method: 'POST', + headers: { + Authorization: `Bearer ${node.api_token}`, + 'Content-Type': 'application/json', + }, + signal: AbortSignal.timeout(10000), + }); + + if (!response.ok) { + const err = await response.json().catch(() => ({})); + res.status(502).json({ error: (err as Record)?.error || 'Remote node rejected update request.' }); + return; + } + + updateTracker.set(nodeId, { status: 'updating', startedAt: Date.now(), previousVersion: meta.version }); + res.status(202).json({ message: `Update initiated on ${node.name}.` }); + } catch (error) { + console.error('[Fleet] Node update error:', error); + res.status(500).json({ error: 'Failed to trigger node update.' }); + } +}); + +// Trigger update on all outdated nodes +app.post('/api/fleet/update-all', async (req: Request, res: Response): Promise => { + if (!requirePro(req, res)) return; + try { + const db = DatabaseService.getInstance(); + const nodes = db.getNodes(); + const gatewayVersion = getSenchoVersion(); + + // Filter to eligible candidates, then trigger all in parallel + const candidates = nodes.filter(node => { + if (node.type === 'local') return false; + if (updateTracker.get(node.id)?.status === 'updating') return false; + if (!node.api_url || !node.api_token) return false; + return true; + }); + + const results = await Promise.allSettled(candidates.map(async (node) => { + const meta = await fetchRemoteMeta(node.api_url!, node.api_token!); + if (!meta.version || !semver.valid(meta.version) || !semver.lt(meta.version, gatewayVersion) || !meta.capabilities.includes('self-update')) { + return { name: node.name, triggered: false }; + } + const response = await fetch(`${node.api_url!.replace(/\/$/, '')}/api/system/update`, { + method: 'POST', + headers: { Authorization: `Bearer ${node.api_token}`, 'Content-Type': 'application/json' }, + signal: AbortSignal.timeout(10000), + }); + if (response.ok) { + updateTracker.set(node.id, { status: 'updating', startedAt: Date.now(), previousVersion: meta.version }); + return { name: node.name, triggered: true }; + } + return { name: node.name, triggered: false }; + })); + + const updating: string[] = []; + const skipped = nodes.filter(n => !candidates.includes(n)).map(n => n.name); + for (const r of results) { + const val = r.status === 'fulfilled' ? r.value : { name: 'unknown', triggered: false }; + (val.triggered ? updating : skipped).push(val.name); + } + + res.status(202).json({ updating, skipped }); + } catch (error) { + console.error('[Fleet] Update all error:', error); + res.status(500).json({ error: 'Failed to trigger fleet update.' }); + } +}); + async function fetchLocalNodeOverview(node: Node): Promise { try { const composeDir = path.resolve(NodeRegistry.getInstance().getComposeDir(node.id)); @@ -5262,6 +5468,9 @@ async function startServer() { // Initialize License Service (starts trial on first boot, periodic validation) LicenseService.getInstance().initialize(); + // Detect whether this instance can self-update (Docker Compose container inspection) + await SelfUpdateService.getInstance().initialize(); + // Start Background Watchdog MonitorService.getInstance().start(); diff --git a/backend/src/services/CapabilityRegistry.ts b/backend/src/services/CapabilityRegistry.ts index 53605435..a919144e 100644 --- a/backend/src/services/CapabilityRegistry.ts +++ b/backend/src/services/CapabilityRegistry.ts @@ -27,6 +27,7 @@ export const CAPABILITIES = [ 'api-tokens', 'users', 'registries', + 'self-update', ] as const; export type Capability = (typeof CAPABILITIES)[number]; @@ -41,6 +42,19 @@ export interface RemoteMeta { capabilities: string[]; } +// Runtime capability overrides — services call disableCapability() during init +const disabledCapabilities = new Set(); + +export function disableCapability(c: Capability): void { + disabledCapabilities.add(c); +} + +/** Returns capabilities this instance actually supports at runtime. */ +export function getActiveCapabilities(): readonly string[] { + if (disabledCapabilities.size === 0) return CAPABILITIES; + return CAPABILITIES.filter(c => !disabledCapabilities.has(c)); +} + /** Fetch /api/meta from a remote Sencho instance. Returns empty data on failure. */ export async function fetchRemoteMeta(baseUrl: string, apiToken: string): Promise { try { diff --git a/backend/src/services/SelfUpdateService.ts b/backend/src/services/SelfUpdateService.ts new file mode 100644 index 00000000..904d44e3 --- /dev/null +++ b/backend/src/services/SelfUpdateService.ts @@ -0,0 +1,87 @@ +import { execSync, exec } from 'child_process'; +import DockerController from './DockerController'; +import { disableCapability } from './CapabilityRegistry'; + +interface ComposeContext { + workingDir: string; + configFiles: string; + serviceName: string; +} + +class SelfUpdateService { + private static instance: SelfUpdateService; + private canSelfUpdate = false; + private composeContext: ComposeContext | null = null; + + public static getInstance(): SelfUpdateService { + if (!SelfUpdateService.instance) { + SelfUpdateService.instance = new SelfUpdateService(); + } + return SelfUpdateService.instance; + } + + async initialize(): Promise { + const hostname = process.env.HOSTNAME; + if (!hostname) { + console.log('[SelfUpdate] HOSTNAME not set — self-update unavailable (not running in Docker?)'); + disableCapability('self-update'); + return; + } + + try { + const docker = DockerController.getInstance().getDocker(); + const container = docker.getContainer(hostname); + const info = await container.inspect(); + const labels = info.Config?.Labels ?? {}; + + const workingDir = labels['com.docker.compose.project.working_dir']; + const configFiles = labels['com.docker.compose.project.config_files']; + const serviceName = labels['com.docker.compose.service']; + + if (!workingDir || !configFiles || !serviceName) { + console.log('[SelfUpdate] Container lacks Docker Compose labels — self-update unavailable'); + disableCapability('self-update'); + return; + } + + this.composeContext = { workingDir, configFiles, serviceName }; + this.canSelfUpdate = true; + console.log(`[SelfUpdate] Ready — service="${serviceName}" in ${workingDir}`); + } catch (error) { + console.log('[SelfUpdate] Could not inspect own container — self-update unavailable:', (error as Error).message); + disableCapability('self-update'); + } + } + + isAvailable(): boolean { + return this.canSelfUpdate; + } + + triggerUpdate(): void { + if (!this.composeContext) return; + const { workingDir, configFiles, serviceName } = this.composeContext; + const env = { ...process.env, PATH: process.env.PATH || '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' }; + + console.log(`[SelfUpdate] Pulling latest image for ${serviceName}...`); + try { + execSync(`docker compose -f ${configFiles} pull ${serviceName}`, { + cwd: workingDir, + env, + stdio: 'pipe', + timeout: 300_000, // 5 min max for pull + }); + } catch (error) { + console.error('[SelfUpdate] Pull failed:', (error as Error).message); + return; + } + + console.log(`[SelfUpdate] Recreating container for ${serviceName}... (last breath)`); + exec(`docker compose -f ${configFiles} up -d --force-recreate ${serviceName}`, { + cwd: workingDir, + env, + }); + // Process will be killed by Docker during recreate — no code runs after this + } +} + +export default SelfUpdateService; diff --git a/docs/docs.json b/docs/docs.json index 08b25270..c40ff5a1 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -104,6 +104,7 @@ "features/multi-node", "features/node-compatibility", "features/fleet-view", + "features/remote-updates", "features/stack-labels", "features/alerts-notifications", "features/notification-routing", @@ -149,7 +150,8 @@ "group": "Health & Meta", "pages": [ "GET /api/health", - "GET /api/meta" + "GET /api/meta", + "POST /api/system/update" ] }, { @@ -222,6 +224,9 @@ "GET /api/fleet/overview", "GET /api/fleet/node/{nodeId}/stacks", "GET /api/fleet/node/{nodeId}/stacks/{stackName}/containers", + "GET /api/fleet/update-status", + "POST /api/fleet/nodes/{nodeId}/update", + "POST /api/fleet/update-all", "POST /api/fleet/snapshots", "GET /api/fleet/snapshots", "GET /api/fleet/snapshots/{id}", diff --git a/docs/features/remote-updates.mdx b/docs/features/remote-updates.mdx new file mode 100644 index 00000000..afe442f8 --- /dev/null +++ b/docs/features/remote-updates.mdx @@ -0,0 +1,93 @@ +--- +title: Remote updates +description: Check for outdated nodes and trigger over-the-air updates from the Fleet View. +--- + +Sencho can update remote nodes directly from the dashboard. When the gateway is running a newer version than a remote node, a one-click update pulls the latest image and recreates the container automatically. + + + Remote updates require **Sencho Pro** (Skipper or Admiral tier). + + +## Prerequisites + +Remote updates work when each node meets these conditions: + +- Deployed via **Docker Compose** (the recommended method) +- The Docker socket (`/var/run/docker.sock`) is mounted into the container +- Running **Sencho v0.32.0** or later (the version that introduced the `self-update` capability) + +Nodes deployed with `docker run` or orchestrators like Kubernetes do not support self-update. These nodes will show a "self-update unavailable" message. + +## How it works + +1. The gateway compares each node's version (from `/api/meta`) against its own version. +2. If a node is running an older version, the Fleet View shows an **Update available** badge. +3. Clicking **Update** sends a command to the remote node. +4. The remote node pulls the latest `saelix/sencho` image and recreates its own container. +5. The gateway polls the node until it comes back online with the new version. + +The remote node briefly goes offline during the update (typically 10–30 seconds depending on image pull speed). The Fleet View tracks the progress and shows **Updating**, **Updated**, or **Timed out** status badges. + +## Checking for updates + +Open the **Fleet** tab and click **Check Updates** in the header. This opens the **Node Updates** dialog, which lists every node with its current version and update status. + + + Node Updates dialog showing update status for each node + + +Each node row shows: + +| Element | Meaning | +|---------|---------| +| Version label (e.g. `v0.31.0`) | The node's current Sencho version | +| **Up to date** badge | Node is running the latest version | +| **Update** button | A newer version is available — click to update | +| **Updating** badge | The node is pulling and restarting | +| **Updated** badge | The node came back online with the new version | +| **Timed out** badge | The node did not come back within 5 minutes | + +Nodes running a version too old to report their version will show `pre-X.Y.Z` as the current version. + +## Updating a single node + +Click the **Update** button next to any outdated node in the Node Updates dialog, or click the **Update to vX.Y.Z** button directly on the node card in Fleet View. For remote nodes, the update happens in the background. For the local (gateway) node, a confirmation dialog appears warning about the brief dashboard disconnection. + +## Updating all nodes + +Click **Update All (N)** in the Node Updates dialog to trigger updates on all outdated remote nodes simultaneously. The local node is intentionally excluded from bulk updates — update it separately to avoid losing dashboard connectivity. + +## Local node updates + +When updating the local (gateway) node: + +1. A confirmation dialog explains that the dashboard will briefly disconnect. +2. After confirming, the server pulls the new image and restarts. +3. A reconnecting overlay appears and polls the server every 3 seconds. +4. The page automatically reloads when the server comes back. + +If the server does not return within 5 minutes, a timeout message appears with a manual reload option. + +## Troubleshooting + +### Node shows "self-update unavailable" + +The node is not running inside a Docker Compose-managed container, or the Docker socket is not mounted. Check that your `docker-compose.yml` includes the socket volume mount: + +```yaml +volumes: + - /var/run/docker.sock:/var/run/docker.sock +``` + +### Update times out + +The image pull may be slow on the remote host, or the container failed to restart. SSH into the remote host and check `docker logs sencho` for errors. You can also manually update by running: + +```bash +docker compose pull && docker compose up -d +``` + +### Old node does not show update button + +Nodes running Sencho versions before v0.32.0 do not advertise the `self-update` capability. Update them manually first, then future updates can be triggered from the dashboard. diff --git a/docs/images/fleet/check-updates-modal.png b/docs/images/fleet/check-updates-modal.png new file mode 100644 index 0000000000000000000000000000000000000000..4db5487155e3e3a60a1e35825a1a01d50105fe09 GIT binary patch literal 32334 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%0A=kmkn~V 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 WNL)H}g@y@_kg2QaC_hoO4EP^WDd}tg literal 0 HcmV?d00001 diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 001664fd..055285fe 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -570,6 +570,35 @@ paths: type: string example: ["stacks", "containers", "fleet", "auto-updates", "host-console"] + /api/system/update: + post: + operationId: triggerSelfUpdate + tags: [Health] + summary: Trigger self-update + description: | + Instructs this Sencho instance to pull the latest Docker image and recreate its own container. + Returns 202 immediately; the actual update happens asynchronously after the response is sent. + Requires the instance to be deployed via Docker Compose with the Docker socket mounted. + responses: + "202": + description: Update initiated. + content: + application/json: + schema: + type: object + properties: + message: + type: string + example: "Update initiated. The server will restart shortly." + "401": + $ref: "#/components/responses/Unauthorized" + "503": + description: Self-update not available (not running in Docker Compose). + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + # ── Stacks ────────────────────────────────────────────── /api/stacks: get: @@ -1923,6 +1952,122 @@ paths: schema: $ref: "#/components/schemas/Error" + /api/fleet/update-status: + get: + operationId: getFleetUpdateStatus + tags: [Fleet] + summary: Fleet update status + description: Returns version comparison and active update status for all nodes. Compares each node's version against the gateway's version. + responses: + "200": + description: Update status for all nodes. + content: + application/json: + schema: + type: object + properties: + nodes: + type: array + items: + type: object + properties: + nodeId: + type: integer + name: + type: string + type: + type: string + enum: [local, remote] + version: + type: string + nullable: true + latestVersion: + type: string + updateAvailable: + type: boolean + updateStatus: + type: string + nullable: true + enum: [updating, completed, timeout, failed, null] + "401": + $ref: "#/components/responses/Unauthorized" + "403": + $ref: "#/components/responses/ProRequired" + + /api/fleet/nodes/{nodeId}/update: + post: + operationId: triggerNodeUpdate + tags: [Fleet] + summary: Trigger node update + description: Initiates a self-update on the specified node. For remote nodes, sends the update command via the proxy. For local nodes, triggers the update directly. + parameters: + - name: nodeId + in: path + required: true + schema: + type: integer + responses: + "202": + description: Update initiated. + content: + application/json: + schema: + type: object + properties: + message: + type: string + "401": + $ref: "#/components/responses/Unauthorized" + "403": + $ref: "#/components/responses/ProRequired" + "404": + description: Node not found. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "409": + description: Update already in progress. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + "503": + description: Self-update not available on the target node. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + + /api/fleet/update-all: + post: + operationId: triggerFleetUpdateAll + tags: [Fleet] + summary: Update all outdated nodes + description: Triggers self-update on all remote nodes running an older version than the gateway. Local nodes are excluded from bulk updates. + responses: + "202": + description: Bulk update initiated. + content: + application/json: + schema: + type: object + properties: + updating: + type: array + items: + type: string + description: Names of nodes where update was triggered. + skipped: + type: array + items: + type: string + description: Names of nodes that were skipped. + "401": + $ref: "#/components/responses/Unauthorized" + "403": + $ref: "#/components/responses/ProRequired" + /api/fleet/snapshots: post: operationId: createFleetSnapshot diff --git a/frontend/src/components/FleetView.tsx b/frontend/src/components/FleetView.tsx index 2babc459..211ea22e 100644 --- a/frontend/src/components/FleetView.tsx +++ b/frontend/src/components/FleetView.tsx @@ -1,8 +1,9 @@ -import { useState, useEffect, useCallback, useMemo } from 'react'; +import { useState, useEffect, useCallback, useMemo, useRef } from 'react'; import { Server, Cpu, MemoryStick, HardDrive, RefreshCw, ChevronDown, ChevronRight, Layers, Wifi, WifiOff, Search, ArrowUpDown, AlertTriangle, Box, Activity, - Play, Square, RotateCcw, ExternalLink, Camera, + Play, Square, RotateCcw, ExternalLink, Camera, Download, Loader2, Check, + CircleCheck, CircleAlert, Globe, Monitor, } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; @@ -11,6 +12,13 @@ import { Input } from '@/components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; +import { + AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, + AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, +} from '@/components/ui/alert-dialog'; +import { + Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, +} from '@/components/ui/dialog'; import { Tabs, TabsContent, TabsList, TabsTrigger, TabsHighlight, TabsHighlightItem } from '@/components/ui/tabs'; import { springs } from '@/lib/motion'; import { apiFetch } from '@/lib/api'; @@ -54,6 +62,16 @@ interface StackContainer { Status?: string; } +interface NodeUpdateStatus { + nodeId: number; + name: string; + type: 'local' | 'remote'; + version: string | null; + latestVersion: string; + updateAvailable: boolean; + updateStatus: 'updating' | 'completed' | 'timeout' | 'failed' | null; +} + type SortField = 'name' | 'cpu' | 'memory' | 'containers' | 'status'; type SortDir = 'asc' | 'desc'; type FilterStatus = 'all' | 'online' | 'offline'; @@ -268,7 +286,76 @@ function StackSection({ stackName, nodeId, onNavigate, labelMap }: { ); } -function NodeCard({ node, onNavigate, labelMap }: { node: FleetNode; onNavigate: (nodeId: number, stackName: string) => void; labelMap?: Record }) { +function UpdateStatusBadge({ status }: { status: NodeUpdateStatus['updateStatus'] }) { + if (status === 'updating') return ( + + Updating + + ); + if (status === 'completed') return ( + + Updated + + ); + if (status === 'timeout') return ( + Timed out + ); + if (status === 'failed') return ( + Failed + ); + return null; +} + +function ReconnectingOverlay() { + const [elapsed, setElapsed] = useState(0); + const timedOut = elapsed >= 300; // 5 minutes + + useEffect(() => { + const timer = setInterval(() => setElapsed(s => s + 1), 1000); + return () => clearInterval(timer); + }, []); + + useEffect(() => { + if (timedOut) return; + const poll = setInterval(async () => { + try { + const res = await fetch('/api/health'); + if (res.ok) window.location.reload(); + } catch { /* still down */ } + }, 3000); + return () => clearInterval(poll); + }, [timedOut]); + + return ( +
+
+ {timedOut ? ( + <> + +

Update timed out

+

+ The server has not come back within 5 minutes. Check the Docker host directly. +

+ + + ) : ( + <> + +

Updating Sencho...

+

+ The server is pulling the latest image and restarting. This page will reload automatically. +

+

{elapsed}s elapsed

+ + )} +
+
+ ); +} + +function NodeCard({ node, onNavigate, labelMap, updateStatus, onUpdate, updatingNodeId }: { node: FleetNode; onNavigate: (nodeId: number, stackName: string) => void; labelMap?: Record; updateStatus?: NodeUpdateStatus; onUpdate?: (nodeId: number) => void; updatingNodeId?: number | null }) { const { isPro } = useLicense(); const [expanded, setExpanded] = useState(false); const [stacks, setStacks] = useState(node.stacks); @@ -312,19 +399,30 @@ function NodeCard({ node, onNavigate, labelMap }: { node: FleetNode; onNavigate:

{node.name}

-
- +
+ {isOnline ? ( <> Online ) : ( <> Offline )} - + {node.type} + {updateStatus?.version && ( + + v{updateStatus.version} + + )} + {updateStatus?.updateStatus && } + {updateStatus?.updateAvailable && !updateStatus.updateStatus && ( + + Update available + + )} {isOnline && isCritical(node) && ( - + Critical )} @@ -386,6 +484,25 @@ function NodeCard({ node, onNavigate, labelMap }: { node: FleetNode; onNavigate:
)} + {/* Update button */} + {isOnline && updateStatus?.updateAvailable && !updateStatus.updateStatus && onUpdate && ( +
+ +
+ )} + {/* Offline placeholder */} {!isOnline && (
@@ -454,6 +571,15 @@ export function FleetView({ onNavigateToNode }: FleetViewProps) { const [fleetStackLabelMap, setFleetStackLabelMap] = useState>({}); const [labelFilters, setLabelFilters] = useState>(new Set()); const { isPro } = useLicense(); + const [updateStatuses, setUpdateStatuses] = useState([]); + const [updatingNodeId, setUpdatingNodeId] = useState(null); + const [reconnecting, setReconnecting] = useState(false); + const [localUpdateConfirm, setLocalUpdateConfirm] = useState(null); + const [showUpdateModal, setShowUpdateModal] = useState(false); + const [checkingUpdates, setCheckingUpdates] = useState(false); + const [modalSearch, setModalSearch] = useState(''); + const updateStatusesRef = useRef(updateStatuses); + updateStatusesRef.current = updateStatuses; const updatePrefs = useCallback((update: Partial) => { setPrefs(prev => { @@ -492,10 +618,90 @@ export function FleetView({ onNavigateToNode }: FleetViewProps) { } }, [isPro]); + const fetchUpdateStatus = useCallback(async () => { + if (!isPro) return; + try { + const res = await apiFetch('/fleet/update-status', { localOnly: true }); + if (res.ok) { + const data = await res.json(); + const next: NodeUpdateStatus[] = data.nodes ?? []; + setUpdateStatuses(prev => + JSON.stringify(prev) === JSON.stringify(next) ? prev : next + ); + } + } catch { /* non-critical */ } + }, [isPro]); + + const triggerNodeUpdate = useCallback(async (nodeId: number) => { + const status = updateStatusesRef.current.find(s => s.nodeId === nodeId); + if (status?.type === 'local') { + setLocalUpdateConfirm(nodeId); + return; + } + + setUpdatingNodeId(nodeId); + try { + const res = await apiFetch(`/fleet/nodes/${nodeId}/update`, { method: 'POST', localOnly: true }); + if (res.ok) { + toast.success(`Update initiated on ${status?.name ?? 'node'}.`); + fetchUpdateStatus(); + } else { + const err = await res.json().catch(() => ({})); + toast.error(err?.message || err?.error || err?.data?.error || 'Failed to trigger update.'); + } + } catch (e: unknown) { + toast.error((e as Error)?.message || 'Something went wrong.'); + } finally { + setUpdatingNodeId(null); + } + }, [fetchUpdateStatus]); + + const confirmLocalUpdate = useCallback(async () => { + const nodeId = localUpdateConfirm; + setLocalUpdateConfirm(null); + if (!nodeId) return; + + setUpdatingNodeId(nodeId); + try { + const res = await apiFetch(`/fleet/nodes/${nodeId}/update`, { method: 'POST', localOnly: true }); + if (res.ok) { + setReconnecting(true); + } else { + const err = await res.json().catch(() => ({})); + toast.error(err?.message || err?.error || err?.data?.error || 'Failed to trigger local update.'); + } + } catch (e: unknown) { + toast.error((e as Error)?.message || 'Something went wrong.'); + } finally { + setUpdatingNodeId(null); + } + }, [localUpdateConfirm]); + + const triggerUpdateAll = useCallback(async () => { + try { + const res = await apiFetch('/fleet/update-all', { method: 'POST', localOnly: true }); + if (res.ok) { + const data = await res.json(); + if (data.updating?.length > 0) { + toast.success(`Update initiated on ${data.updating.length} node${data.updating.length > 1 ? 's' : ''}.`); + } else { + toast.success('All nodes are up to date.'); + } + fetchUpdateStatus(); + } else { + const err = await res.json().catch(() => ({})); + toast.error(err?.message || err?.error || err?.data?.error || 'Failed to trigger fleet update.'); + } + } catch (e: unknown) { + toast.error((e as Error)?.message || 'Something went wrong.'); + } + }, [fetchUpdateStatus]); + useEffect(() => { fetchOverview(); fetchLabels(); - }, [fetchOverview, fetchLabels]); + fetchUpdateStatus(); + }, [fetchOverview, fetchLabels, fetchUpdateStatus]); // Pro: auto-refresh every 30s useEffect(() => { @@ -504,6 +710,22 @@ export function FleetView({ onNavigateToNode }: FleetViewProps) { return () => clearInterval(interval); }, [isPro, fetchOverview]); + // Fast poll (5s) when any node is actively updating — uses ref to avoid interval thrashing + const hasUpdatingRef = useRef(false); + useEffect(() => { + hasUpdatingRef.current = updateStatuses.some(s => s.updateStatus === 'updating'); + }, [updateStatuses]); + + useEffect(() => { + const id = setInterval(() => { + if (hasUpdatingRef.current) { + fetchUpdateStatus(); + fetchOverview(); + } + }, 5000); + return () => clearInterval(id); + }, [fetchUpdateStatus, fetchOverview]); + // --- Computed values --- const onlineNodes = useMemo(() => nodes.filter(n => n.status === 'online'), [nodes]); @@ -523,6 +745,16 @@ export function FleetView({ onNavigateToNode }: FleetViewProps) { const totalMemUsed = onlineNodes.reduce((sum, n) => sum + (n.systemStats?.memory.used ?? 0), 0); const totalMemTotal = onlineNodes.reduce((sum, n) => sum + (n.systemStats?.memory.total ?? 0), 0); + const updatableRemoteCount = useMemo( + () => updateStatuses.filter(s => s.updateAvailable && !s.updateStatus && s.type === 'remote').length, + [updateStatuses] + ); + + const updateStatusMap = useMemo( + () => new Map(updateStatuses.map(s => [s.nodeId, s])), + [updateStatuses] + ); + // --- Filtering & Sorting (Pro) --- const processedNodes = useMemo(() => { @@ -596,16 +828,34 @@ export function FleetView({ onNavigateToNode }: FleetViewProps) { {loading ? 'Loading...' : `${onlineCount} of ${nodes.length} nodes online · ${totalContainers} containers · ${totalStacks} stacks`}

- +
+ {isPro && ( + + )} + +
@@ -804,6 +1054,9 @@ export function FleetView({ onNavigateToNode }: FleetViewProps) { node={node} onNavigate={onNavigateToNode} labelMap={fleetStackLabelMap} + updateStatus={updateStatusMap.get(node.id)} + onUpdate={isPro ? triggerNodeUpdate : undefined} + updatingNodeId={updatingNodeId} /> ))}
@@ -863,6 +1116,201 @@ export function FleetView({ onNavigateToNode }: FleetViewProps) { )} + + {/* Reconnecting overlay — shown when local node is updating */} + {reconnecting && } + + {/* Node Updates modal */} + { setShowUpdateModal(open); if (!open) setModalSearch(''); }}> + + + Node Updates + Check and apply updates across your fleet nodes. + + + {checkingUpdates ? ( +
+ + Checking for updates... +
+ ) : updateStatuses.length === 0 ? ( +
+ No nodes found. +
+ ) : (() => { + const upToDate = updateStatuses.filter(s => !s.updateAvailable && !s.updateStatus).length; + const available = updateStatuses.filter(s => s.updateAvailable && !s.updateStatus).length; + const updating = updateStatuses.filter(s => s.updateStatus === 'updating').length; + const failed = updateStatuses.filter(s => s.updateStatus === 'failed' || s.updateStatus === 'timeout').length; + const q = modalSearch.toLowerCase(); + const filtered = q ? updateStatuses.filter(s => s.name.toLowerCase().includes(q) || s.type.includes(q)) : updateStatuses; + + return ( + <> + {/* Summary stats */} +
+
+
{upToDate}
+
+ Up to date +
+
+
+
{available}
+
+ Available +
+
+
+
{updating}
+
+ Updating +
+
+
+
{failed}
+
+ Failed +
+
+
+ + {/* Search + gateway version */} +
+
+ + setModalSearch(e.target.value)} + className="h-8 pl-8 text-xs" + /> +
+
+ Gateway: v{updateStatuses[0]?.latestVersion} +
+
+ + {/* Table header */} +
+ Node + Type + Current + Latest + Status +
+ + {/* Node list */} +
+ {filtered.map(s => ( +
+ {/* Node name */} +
+
+ {s.type === 'local' + ? + : + } +
+ {s.name} +
+ + {/* Type */} + + {s.type} + + + {/* Current version */} + + {s.version ? `v${s.version}` : unknown} + + + {/* Latest version */} + + v{s.latestVersion} + + + {/* Status / Action */} +
+ {s.updateStatus && } + {!s.updateStatus && !s.updateAvailable && ( + + Up to date + + )} + {s.updateAvailable && !s.updateStatus && ( + + )} +
+
+ ))} + {filtered.length === 0 && ( +
+ No nodes match “{modalSearch}” +
+ )} +
+ + {/* Footer */} +
+ + {updatableRemoteCount > 0 && ( + + )} +
+ + ); + })()} +
+
+ + {/* Confirm dialog for local node update */} + { if (!open) setLocalUpdateConfirm(null); }}> + + + Update local node? + + This will pull the latest Sencho image and restart the server. The dashboard will be + briefly disconnected and will automatically reconnect when the update completes. + + + + Cancel + + + Update & Restart + + + + ); } diff --git a/frontend/src/lib/capabilities.ts b/frontend/src/lib/capabilities.ts index 1ecc09eb..21913276 100644 --- a/frontend/src/lib/capabilities.ts +++ b/frontend/src/lib/capabilities.ts @@ -20,6 +20,7 @@ export const CAPABILITIES = [ 'api-tokens', 'users', 'registries', + 'self-update', ] as const; export type Capability = (typeof CAPABILITIES)[number];