feat(web): Remote Updates API — dashboard endpoints for pushing code to workers

Adds /api/v1/swarm-updates/{hosts,push,push-self,rollback} behind
require_admin. Reuses the existing UpdaterClient + tar_working_tree + the
per-host asyncio.gather pattern from api_deploy_swarm.py; tarball is
built exactly once per /push request and fanned out to every selected
worker. /hosts filters out decommissioned hosts and agent-only
enrollments (no updater bundle = not a target).

Connection drops during /update-self are treated as success — the
updater re-execs itself mid-response, so httpx always raises.

Pydantic models live in decnet/web/db/models.py (single source of
truth). 24 tests cover happy paths, rollback, transport failures,
include_self ordering (skip on rolled-back agents), validation, and
RBAC gating.
This commit is contained in:
2026-04-19 01:01:09 -04:00
parent f5a5fec607
commit a266d6b17e
13 changed files with 1041 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
"""Remote Updates — master dashboard's surface for pushing code to workers.
These are *not* the swarm-controller's /swarm routes (those run on a
separate process, auth-free, internal-only). They live on the main web
API, go through ``require_admin``, and are the interface the React
dashboard calls to fan updates out to worker ``decnet updater`` daemons
via ``UpdaterClient``.
Mounted under ``/api/v1/swarm-updates`` by the main api router.
"""
from fastapi import APIRouter
from .api_list_host_releases import router as list_host_releases_router
from .api_push_update import router as push_update_router
from .api_push_update_self import router as push_update_self_router
from .api_rollback_host import router as rollback_host_router
swarm_updates_router = APIRouter(prefix="/swarm-updates")
swarm_updates_router.include_router(list_host_releases_router)
swarm_updates_router.include_router(push_update_router)
swarm_updates_router.include_router(push_update_self_router)
swarm_updates_router.include_router(rollback_host_router)