mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-12 03:36:59 +00:00
feat(scheduler): schedule container restart, stop, and start (#1526)
* feat(scheduler): schedule container restart, stop, and start Add container as a scheduled-task target type so operators can automate lifecycle actions against standalone containers by node and name, with matching UI pickers, validation, execution on local and remote nodes, and tests. * fix(scheduler): stack service matching and container picker hygiene Backfill Service on smartFallback containers so per-service stack restarts work when container_name is set. Match services by compose label and container name in stack routes and scheduled restarts. Exclude Sencho from GET /api/containers lists. Hide the Restart Stack service picker when a stack has only one service. * test(scheduler): scope service checkbox assertion to Services block The create dialog also has a Delete after run checkbox. Count checkboxes only inside the Services section so CI does not include unrelated form controls. * fix(scheduler): narrow closest() result to HTMLElement in schedule test The service-checkbox assertion passed an Element from closest() into within(), which requires an HTMLElement, failing tsc -b in the frontend build and Docker build stages. Use the closest<HTMLElement>() type argument so the value type-checks without an unsafe cast. * fix(scheduler): hide Sencho container on remote node picker lists Remote container lists are proxied from peer Sencho instances, so id-only self filtering missed peers on older builds. Await SelfIdentity init, match ImageID, and drop official saelix/sencho images. Apply the same heuristic in the scheduled-operations UI and when the hub fetches remote containers for scheduled runs. * test(monitor): add missing DatabaseService mocks for scan history cleanup * test(scheduler): add missing markStaleScansAsFailed mock SchedulerService.tick() calls db.markStaleScansAsFailed() to sweep stale vulnerability scans. The scheduler-service test was missing this method in its DatabaseService mock, causing TypeError failures during test initialization. Added mockMarkStaleScansAsFailed to hoisted mocks and DatabaseService mock object, returning safe default of 0 scans marked as failed. * test(compose): add missing FileSystemService mocks for getStackContent/getEnvContent * test(containers-route): mock SelfIdentityService to prevent initialize() crash The excludeSelfContainers() helper calls SelfIdentityService.initialize(), which tries to access DockerController. Without a proper SelfIdentityService mock, the initialize() call fails silently, causing a 500 error on GET /api/containers. Added SelfIdentityService mock with initialize(), isOwnContainer(), and isOwnImage() methods to prevent the crash.
This commit is contained in:
@@ -26,8 +26,8 @@ Open the **Schedules** tab from the top navigation bar. The page opens on the Ti
|
||||
The Timeline plots every firing of every enabled task across a rolling 24-hour window starting from the current minute.
|
||||
|
||||
- **Masthead.** A `NEXT 24 HOURS` kicker, an italic display heading, the window's start and end timestamps in a monospace range, and a right-anchored **Next** pill that reads out the time and task name of the next firing and a relative countdown.
|
||||
- **Five lanes.** Stack lifecycle (label blue), Updates (success green), Security (label purple), Maintenance (warning amber), and Backups (brand cyan). The Stack lifecycle lane holds the five stack-lifecycle actions (Backup Stack Compose Files, Start / Bring Up Stack, Restart Stack, Stop Stack, Take Stack Down); Updates holds per-node and fleet image updates; Security holds vulnerability scans; Maintenance holds node resource prunes; Backups holds fleet snapshots.
|
||||
- **Pills.** One pill per firing within the window, positioned proportionally to the firing's time. Each pill shows the firing time and a target: the stack for stack actions, the selected node for prune and scan, and "Entire fleet" for a fleet snapshot. Hover a pill for the full detail (action, task name, and node). Pills are color-matched to their lane. Click a pill to open the run history sheet for that task.
|
||||
- **Five lanes.** Lifecycle (label blue), Updates (success green), Security (label purple), Maintenance (warning amber), and Backups (brand cyan). The Lifecycle lane holds stack lifecycle actions (Backup Stack Compose Files, Start / Bring Up Stack, Restart Stack, Stop Stack, Take Stack Down) and standalone container actions (Restart Container, Stop Container, Start Container); Updates holds per-node and fleet image updates; Security holds vulnerability scans; Maintenance holds node resource prunes; Backups holds fleet snapshots.
|
||||
- **Pills.** One pill per firing within the window, positioned proportionally to the firing's time. Each pill shows the firing time and a target: the stack for stack actions, the container name for container actions, the selected node for prune and scan, and "Entire fleet" for a fleet snapshot. Hover a pill for the full detail (action, task name, and node). Pills are color-matched to their lane. Click a pill to open the run history sheet for that task.
|
||||
- **Now rail.** A glowing vertical rail at the current minute, anchored to the left of the track at page open and drifting right as time passes (the page recomputes positions periodically).
|
||||
- **Axis.** Six monospace time ticks run along the bottom, evenly spaced through the window.
|
||||
|
||||
@@ -47,7 +47,7 @@ The All tasks toggle swaps the lane track for a sortable table.
|
||||
|---|---|
|
||||
| **Name** | The task name. |
|
||||
| **Action** | A badge labelling the operation (e.g. Restart Stack, Scan Node Images, Create Fleet Snapshot). |
|
||||
| **Target** | The stack the task targets (with a service list in parentheses when restart is scoped to specific services), or the target type for non-stack actions (`system`, `fleet`). |
|
||||
| **Target** | The stack the task targets (with a service list in parentheses when restart is scoped to specific services), the container name for container actions, or the target type for other non-stack actions (`system`, `fleet`). |
|
||||
| **Schedule** | A human-readable description of the cron with the raw expression on a second line. |
|
||||
| **Status** | The last run result: **Success** (green), **Failed** (red), or `Never run` if the task has not fired yet. |
|
||||
| **Next Run** | The timestamp of the next firing, or a dash if the task is disabled or has no upcoming runs. |
|
||||
@@ -68,10 +68,13 @@ The All tasks toggle swaps the lane track for a sortable table.
|
||||
| **Stop Stack** | A specific stack on a specific node | Runs `docker compose stop`. Containers are stopped but preserved. Use for off-hours power saving when you want a fast restart later. |
|
||||
| **Take Stack Down** | A specific stack on a specific node | Runs `docker compose down`. Containers are removed. Use to fully release resources when the stack is not needed for an extended period. |
|
||||
| **Start / Bring Up Stack** | A specific stack on a specific node | Runs `docker compose up -d`. Works for both stopped and removed containers: if they exist they are started, if not they are created from the compose file. |
|
||||
| **Restart Container** | A specific container by name on a specific node | Restarts one container directly through Docker. Use for third-party or standalone containers that are not managed as a Sencho stack. |
|
||||
| **Stop Container** | A specific container by name on a specific node | Stops one container. The container remains on disk for a faster start later. |
|
||||
| **Start Container** | A specific container by name on a specific node | Starts one stopped container by name. |
|
||||
|
||||
## Creating a scheduled task
|
||||
|
||||
Click **New Schedule** in the header. The form opens in a centered modal. The Action picker lists every supported operation, grouped by category: Stack lifecycle, Updates, Security, Maintenance, and Backups.
|
||||
Click **New Schedule** in the header. The form opens in a centered modal. The Action picker lists every supported operation, grouped by category: Lifecycle, Updates, Security, Maintenance, and Backups.
|
||||
|
||||
<Frame>
|
||||
<img src="/images/scheduled-operations/action-picker.png" alt="The New scheduled task modal with the Action combobox expanded. The dropdown groups actions under category headers: Stack lifecycle (Backup Stack Compose Files, Start / Bring Up Stack, Restart Stack, Stop Stack, Take Stack Down), Updates (Auto-update Stack, Auto-update All Stacks on Node), Security (Scan Node Images), Maintenance (Prune Node Resources), and Backups (Create Fleet Snapshot). Below the picker, partly visible, sit a Services row with 'echo' and 'prober' checkboxes, the Cron Expression input, the Enabled toggle, and the Delete after successful run checkbox." />
|
||||
@@ -88,6 +91,7 @@ Common fields:
|
||||
Conditional fields per action:
|
||||
|
||||
- **Stack actions** (Backup Stack Compose Files, Start / Bring Up Stack, Restart Stack, Auto-update Stack, Stop Stack, Take Stack Down) add a **Node** combobox and a **Stack** combobox. Restart Stack additionally renders a **Services** checkbox grid sourced from the stack's compose services on the selected node, so you can scope the restart to a subset instead of restarting the entire stack.
|
||||
- **Container actions** (Restart Container, Stop Container, Start Container) add a **Node** combobox and a **Container** combobox listing every container on that node (running and stopped). The picker shows each container's name, state, and image. When the container is not part of a Sencho stack, helper text explains that the schedule targets the container by node and name.
|
||||
- **Auto-update All Stacks on Node** adds a **Node** combobox. The helper text "Checks every stack on the selected node and updates stacks with newer images" appears above, next to the Runtime change badge.
|
||||
- **Scan Node Images** adds a **Node** combobox listing local nodes only. The helper text "Runs Trivy against images on the selected local node and records the findings" and Read-only badge appear above.
|
||||
- **Prune Node Resources** adds a **Node** combobox listing local nodes only, then a **Prune Targets** group (Containers, Images, Networks, Volumes; all selected by default) and a **Label Filter** input for scoping the prune to resources matching a Docker label.
|
||||
|
||||
+10
-8
@@ -386,13 +386,13 @@ components:
|
||||
type: string
|
||||
target_type:
|
||||
type: string
|
||||
enum: [stack, fleet, system]
|
||||
enum: [stack, fleet, system, container]
|
||||
target_id:
|
||||
type: ["string", "null"]
|
||||
description: Stack name (when target_type is `stack`).
|
||||
description: Stack or container name (when target_type is `stack` or `container`).
|
||||
node_id:
|
||||
type: ["integer", "null"]
|
||||
description: Target node ID (when target_type is `stack`).
|
||||
description: Target node ID (when target_type is `stack` or `container`).
|
||||
action:
|
||||
type: string
|
||||
enum: [restart, snapshot, prune]
|
||||
@@ -2717,7 +2717,8 @@ paths:
|
||||
summary: Create scheduled task
|
||||
description: |
|
||||
Creates a new recurring task. Action-target rules:
|
||||
- `restart` requires `target_type: stack` (with `target_id` and `node_id`)
|
||||
- `restart` requires `target_type: stack` or `target_type: container` (with `target_id` and `node_id`)
|
||||
- `auto_stop` and `auto_start` accept `target_type: stack` or `target_type: container`
|
||||
- `snapshot` requires `target_type: fleet`
|
||||
- `prune` requires `target_type: system`
|
||||
|
||||
@@ -2735,13 +2736,13 @@ paths:
|
||||
example: Nightly restart
|
||||
target_type:
|
||||
type: string
|
||||
enum: [stack, fleet, system]
|
||||
enum: [stack, fleet, system, container]
|
||||
target_id:
|
||||
type: string
|
||||
description: Stack name (required when target_type is `stack`).
|
||||
description: Stack or container name (required when target_type is `stack` or `container`).
|
||||
node_id:
|
||||
type: integer
|
||||
description: Target node ID (required when target_type is `stack`).
|
||||
description: Target node ID (required when target_type is `stack` or `container`).
|
||||
action:
|
||||
type: string
|
||||
enum: [restart, snapshot, prune]
|
||||
@@ -2828,9 +2829,10 @@ paths:
|
||||
type: string
|
||||
target_type:
|
||||
type: string
|
||||
enum: [stack, fleet, system]
|
||||
enum: [stack, fleet, system, container]
|
||||
target_id:
|
||||
type: string
|
||||
description: Stack or container name when target_type is `stack` or `container`.
|
||||
node_id:
|
||||
type: integer
|
||||
action:
|
||||
|
||||
Reference in New Issue
Block a user