Implement ACTIVITY-WP-0024 operator automation console
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
Build and Publish Container Image / build-and-push (push) Successful in 36s

Add /ops REST inventory, status, runs, and fail-closed operator-token
mutations (trigger, enable/disable, pause/unpause) with audit trail.
Ship thin HTML UI at /ops/ui, runbook/k8s access docs, and contract tests.
This commit is contained in:
tegwick 2026-07-21 23:51:39 +02:00
parent 81d350de71
commit 71027f0a67
11 changed files with 1494 additions and 20 deletions

View file

@ -353,6 +353,51 @@ async def delete_schedule(client: Client, activity_id: str | UUID) -> None:
pass # Not found — treat as success.
async def pause_schedule(
client: Client,
activity_id: str | UUID,
*,
note: str = "paused via ops console",
onetime: bool = False,
) -> dict:
"""Pause a Temporal Schedule. Returns status dict; missing schedule is an error."""
sid = _onetime_schedule_id(activity_id) if onetime else schedule_id(activity_id)
handle = client.get_schedule_handle(sid)
try:
await handle.pause(note=note)
except ScheduleAlreadyRunningError:
# Race with in-flight action — treat as best-effort success after retry note.
try:
await handle.pause(note=note)
except (RPCError, ScheduleAlreadyRunningError) as exc:
return {"schedule_id": sid, "paused": None, "warning": str(exc)}
except RPCError as exc:
return {"schedule_id": sid, "paused": None, "error": str(exc)}
return {"schedule_id": sid, "paused": True, "note": note}
async def unpause_schedule(
client: Client,
activity_id: str | UUID,
*,
note: str = "unpaused via ops console",
onetime: bool = False,
) -> dict:
"""Unpause a Temporal Schedule. Returns status dict."""
sid = _onetime_schedule_id(activity_id) if onetime else schedule_id(activity_id)
handle = client.get_schedule_handle(sid)
try:
await handle.unpause(note=note)
except ScheduleAlreadyRunningError:
try:
await handle.unpause(note=note)
except (RPCError, ScheduleAlreadyRunningError) as exc:
return {"schedule_id": sid, "paused": None, "warning": str(exc)}
except RPCError as exc:
return {"schedule_id": sid, "paused": None, "error": str(exc)}
return {"schedule_id": sid, "paused": False, "note": note}
async def list_schedules(client: Client) -> list[dict]:
"""Enumerate all activity-core Temporal Schedules.