[PR #24] [MERGED] Add fleet web dashboard (L2): FastAPI app + fleet-dashboard entrypoint #24

Closed
opened 2026-06-11 16:01:44 +08:00 by ivenator1 · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/ivenator1/proxmox-management/pull/24
Author: @ivenator1
Created: 6/11/2026
Status: Merged
Merged: 6/11/2026
Merged by: @ivenator1

Base: testingHead: claude/remote-testing-branch-track-3m06yk


📝 Commits (2)

  • 6e5f239 fix: defer lock dir mkdir to acquire time; bypass lock in cli/wrapper tests
  • 1ccf562 Add fleet web dashboard (L2): FastAPI app, fleet-dashboard entrypoint

📊 Changes

24 files changed (+1417 additions, -10 deletions)

View changed files

📝 CLAUDE.md (+25 -1)
📝 README.md (+1 -0)
📝 docs/FEATURE_ROADMAP.md (+8 -4)
📝 proxmox_fleet/lock.py (+4 -3)
proxmox_fleet/web/__init__.py (+8 -0)
proxmox_fleet/web/app.py (+299 -0)
proxmox_fleet/web/main.py (+53 -0)
proxmox_fleet/web/runs.py (+221 -0)
proxmox_fleet/web/static/PICO-LICENSE.md (+21 -0)
proxmox_fleet/web/static/pico.classless.min.css (+4 -0)
proxmox_fleet/web/templates/base.html (+37 -0)
proxmox_fleet/web/templates/console.html (+34 -0)
proxmox_fleet/web/templates/history.html (+32 -0)
proxmox_fleet/web/templates/host.html (+33 -0)
proxmox_fleet/web/templates/index.html (+48 -0)
proxmox_fleet/web/templates/pending.html (+81 -0)
proxmox_fleet/web/templates/run_detail.html (+39 -0)
proxmox_fleet/web/templates/trigger.html (+56 -0)
📝 pyproject.toml (+14 -0)
📝 tests/requirements.txt (+4 -0)

...and 4 more files

📄 Description

Completes the final item on docs/FEATURE_ROADMAP.md — the L2 web dashboard. This branch also carries the L2 groundwork from the planning branch (--scan, the fleet-wide run lock, the history/pending readers) that the dashboard builds on.

What's new

proxmox_fleet/web/ behind a new pip install -e '.[web]' extra (fastapi + uvicorn + python-multipart), console entrypoint fleet-dashboard (binds dashboard_host:dashboard_port from vars.yml, default 0.0.0.0:8421).

  • Five server-rendered pages (vendored classless Pico.css v2.1.1, MIT — offline, no JS build step): overview, pending updates (PatchMon-style, from --scan snapshots, incl. community-script app current→latest), run history with run-over-run deltas, per-run detail (record tables + stored briefing), per-host drill-down across runs, and the run trigger. All data is read from fleet_history_dir via the existing history.py/scan.py readers — the dashboard never reaches the fleet.
  • Run trigger (POST /runs, bearer dashboard_token via header or form field; empty token = open): launches python -u -m proxmox_fleet.cli <flags> detached (start_new_session) with stdout to dashboard-runs/<id>.log + a JSON meta record, so a dashboard restart never kills a mid-flight run; orphaned metas are finalized on read. Live output streams via SSE by re-tailing the log.
  • Single-flight, double-checked: RunManager.start() probes the shared fleet run lock plus its own children, and the CLI child re-acquires the same lock.py flock — dashboard, cron, and shell runs can never overlap.
  • Trigger argv is composed only from validated tokens (build_run_args()): --limit/--phases fields are tokenized against [A-Za-z0-9._-]+ and phase names validated; nothing user-supplied is passed raw.

Tests / verification

  • tests/unit/test_web.py — 31 tests: fastapi.testclient against fixture history/pending dirs, auth (header/form/none), arg validation incl. shell-metacharacter rejection, RunManager with stub subprocess commands (rc capture, overlap refusal, lock refusal, orphan finalization), and an end-to-end trigger → console → SSE roundtrip. Skipped wholesale when fastapi isn't installed.
  • Full suite: 800 passed; mypy, ruff, bandit (-ll), yamllint all clean; wheel build verified to include templates/static.
  • Live smoke test: all pages 200, static CSS served, unauthenticated trigger → 401.

Docs: CLAUDE.md (commands, file map, dashboard section), README feature bullet, vars.yml.example dashboard block, roadmap marked complete.

https://claude.ai/code/session_01R3JXwt4bmaKMkpGq5xn8Sd


Generated by Claude Code


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/ivenator1/proxmox-management/pull/24 **Author:** [@ivenator1](https://github.com/ivenator1) **Created:** 6/11/2026 **Status:** ✅ Merged **Merged:** 6/11/2026 **Merged by:** [@ivenator1](https://github.com/ivenator1) **Base:** `testing` ← **Head:** `claude/remote-testing-branch-track-3m06yk` --- ### 📝 Commits (2) - [`6e5f239`](https://github.com/ivenator1/proxmox-management/commit/6e5f239d529452acccf408d0bb2d24ede2cbf0a7) fix: defer lock dir mkdir to acquire time; bypass lock in cli/wrapper tests - [`1ccf562`](https://github.com/ivenator1/proxmox-management/commit/1ccf562f4798573ad9fd6dd705be94f941891951) Add fleet web dashboard (L2): FastAPI app, fleet-dashboard entrypoint ### 📊 Changes **24 files changed** (+1417 additions, -10 deletions) <details> <summary>View changed files</summary> 📝 `CLAUDE.md` (+25 -1) 📝 `README.md` (+1 -0) 📝 `docs/FEATURE_ROADMAP.md` (+8 -4) 📝 `proxmox_fleet/lock.py` (+4 -3) ➕ `proxmox_fleet/web/__init__.py` (+8 -0) ➕ `proxmox_fleet/web/app.py` (+299 -0) ➕ `proxmox_fleet/web/main.py` (+53 -0) ➕ `proxmox_fleet/web/runs.py` (+221 -0) ➕ `proxmox_fleet/web/static/PICO-LICENSE.md` (+21 -0) ➕ `proxmox_fleet/web/static/pico.classless.min.css` (+4 -0) ➕ `proxmox_fleet/web/templates/base.html` (+37 -0) ➕ `proxmox_fleet/web/templates/console.html` (+34 -0) ➕ `proxmox_fleet/web/templates/history.html` (+32 -0) ➕ `proxmox_fleet/web/templates/host.html` (+33 -0) ➕ `proxmox_fleet/web/templates/index.html` (+48 -0) ➕ `proxmox_fleet/web/templates/pending.html` (+81 -0) ➕ `proxmox_fleet/web/templates/run_detail.html` (+39 -0) ➕ `proxmox_fleet/web/templates/trigger.html` (+56 -0) 📝 `pyproject.toml` (+14 -0) 📝 `tests/requirements.txt` (+4 -0) _...and 4 more files_ </details> ### 📄 Description Completes the final item on `docs/FEATURE_ROADMAP.md` — the L2 web dashboard. This branch also carries the L2 groundwork from the planning branch (`--scan`, the fleet-wide run lock, the history/pending readers) that the dashboard builds on. ## What's new **`proxmox_fleet/web/` behind a new `pip install -e '.[web]'` extra** (fastapi + uvicorn + python-multipart), console entrypoint `fleet-dashboard` (binds `dashboard_host:dashboard_port` from vars.yml, default `0.0.0.0:8421`). - **Five server-rendered pages** (vendored classless Pico.css v2.1.1, MIT — offline, no JS build step): overview, pending updates (PatchMon-style, from `--scan` snapshots, incl. community-script app current→latest), run history with run-over-run deltas, per-run detail (record tables + stored briefing), per-host drill-down across runs, and the run trigger. All data is read from `fleet_history_dir` via the existing `history.py`/`scan.py` readers — the dashboard never reaches the fleet. - **Run trigger** (`POST /runs`, bearer `dashboard_token` via header or form field; empty token = open): launches `python -u -m proxmox_fleet.cli <flags>` detached (`start_new_session`) with stdout to `dashboard-runs/<id>.log` + a JSON meta record, so a dashboard restart never kills a mid-flight run; orphaned metas are finalized on read. Live output streams via SSE by re-tailing the log. - **Single-flight, double-checked**: `RunManager.start()` probes the shared fleet run lock plus its own children, and the CLI child re-acquires the same `lock.py` flock — dashboard, cron, and shell runs can never overlap. - **Trigger argv is composed only from validated tokens** (`build_run_args()`): `--limit`/`--phases` fields are tokenized against `[A-Za-z0-9._-]+` and phase names validated; nothing user-supplied is passed raw. ## Tests / verification - `tests/unit/test_web.py` — 31 tests: fastapi.testclient against fixture history/pending dirs, auth (header/form/none), arg validation incl. shell-metacharacter rejection, RunManager with stub subprocess commands (rc capture, overlap refusal, lock refusal, orphan finalization), and an end-to-end trigger → console → SSE roundtrip. Skipped wholesale when fastapi isn't installed. - Full suite: 800 passed; mypy, ruff, bandit (`-ll`), yamllint all clean; wheel build verified to include templates/static. - Live smoke test: all pages 200, static CSS served, unauthenticated trigger → 401. Docs: CLAUDE.md (commands, file map, dashboard section), README feature bullet, `vars.yml.example` dashboard block, roadmap marked complete. https://claude.ai/code/session_01R3JXwt4bmaKMkpGq5xn8Sd --- _Generated by [Claude Code](https://claude.ai/code/session_01R3JXwt4bmaKMkpGq5xn8Sd)_ --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
ivenator1 changed title from [PR #24] Add fleet web dashboard (L2): FastAPI app + fleet-dashboard entrypoint to [PR #24] [MERGED] Add fleet web dashboard (L2): FastAPI app + fleet-dashboard entrypoint 2026-06-11 19:02:02 +08:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
ivenator1/proxmox-management#24
No description provided.