feat(canary): allow custom canaries on MazeNET deckies via API
POST /api/v1/canary/tokens grows an optional topology_id field. When present, the server hydrates the topology, validates the named decky is in it, and resolves the docker container via planter.resolve_topology_container — <name>-ssh if the decky exposes ssh, else the topology base container. Absent ⇒ fleet semantics, unchanged. The token row gets a nullable topology_id column (no migration helper per pre-v1 policy). GET /api/v1/canary/tokens accepts ?topology_id= as a filter. DELETE re-resolves the container at revoke time so a redeployed topology is still reachable. 422 when the named decky isn't in the topology; 404 when the topology itself doesn't exist.
This commit is contained in:
@@ -122,6 +122,7 @@ class CanaryMixin:
|
||||
decky_name: Optional[str] = None,
|
||||
state: Optional[str] = None,
|
||||
kind: Optional[str] = None,
|
||||
topology_id: Optional[str] = None,
|
||||
) -> list[dict[str, Any]]:
|
||||
async with self._session() as session:
|
||||
stmt = select(CanaryToken)
|
||||
@@ -131,6 +132,8 @@ class CanaryMixin:
|
||||
stmt = stmt.where(CanaryToken.state == state)
|
||||
if kind is not None:
|
||||
stmt = stmt.where(CanaryToken.kind == kind)
|
||||
if topology_id is not None:
|
||||
stmt = stmt.where(CanaryToken.topology_id == topology_id)
|
||||
stmt = stmt.order_by(desc(CanaryToken.placed_at))
|
||||
result = await session.execute(stmt)
|
||||
return [r.model_dump(mode="json") for r in result.scalars().all()]
|
||||
|
||||
Reference in New Issue
Block a user