phase: 10_dev_direct_dial
**Phase 10 final pass — repo green; live criteria blocked off-repo.**
- Verified: `gateway` runs `dashboards-agent` (active/enabled, `10.1.1.27:9120` → `/health` 200, `/snapshot` 401 no-token / 200 bearer on-host, token matches `/etc/dashboards-agent.token`); `driveripper`/`deskwork` inactive, `sudo -n` → "a password is required", `:9120` empty.
- New measurement (transient runtime rule on gateway `firewall-cmd --add-port=9120/tcp`, **reverted** — runtime+permanent port lists verified back to the original set, no rich rules): laptop still gets no SYN through, while `:22`/`:80` on the same address answer in ms ⇒ the block is the lab gateway `10.2.0.1` port filter, not this app/host firewall/agent. No other live change made (no sudoers, no upsd, no UPS command).
- Tests/lint (exact): `bash .agents/validate.sh` → **EXIT 0** — `uv run pytest --cov --cov-fail-under=94` **793 passed, 11 skipped, coverage 98.33 %**; `ruff check src tests agent` clean; `pyright` 0 errors; `node --check` clean; hygiene clean; `uv pip list --outdated` empty (bumped fastapi 0.143.3→0.143.5, `uv.lock` only).
- `uv run pytest -m live --live` (`.env.dev` sourced): **4 passed, 1 skipped, 6 failed** — all six are `:9120`/`:3051` connect timeouts; zero parse/contract failures.
- Dev server restarted on current code: engines `ok`; 3×`host` + 3×`disks` + `nut` `DOWN` with real reasons (designed degradation, stub rows intact, no credential leakage).
- Completion criteria: screenshots ✓ (`data/logs/phase10-{index,system,disks,llm,ups}-live.png`); tunnel-vocabulary grep ✓ outside `.agents/` history (PLAN.md locked line, phase overviews, past reports; fixtures/`uv.lock` hits are digit substrings — `tests/test_deploy_scripts.py` guards operational files); no page-payload change ✓ (contract tests). **Not met, operator-side:** agents on all three hosts, `LIST UPS` from the laptop, `dev-server.sh status` all-ok, live suite green.
- Fixed in this pass: `sources/nut.py` unreachable-upsd message no longer prints a bare `(TimeoutError: )` (now `(timed out after 4s)` / `(ConnectionRefusedError: …)`), pinned by a new test + extended refused-port test.
- Docs: README verified consistent (every env var in `config.py` documented, routes/flags/`--with-llm`/pager sizes checked) — no changes needed. AGENTS.md fixed 4 inconsistencies: per-host sudo reality (gateway grants `NOPASSWD ALL`, which is why it installed without `agent-sudoers`; driveripper scoped; deskwork unrelated), the now-proven firewall finding, `/system` table typo ("agent per host"), gap-4 DB/WAL sizes + test count. `.env.example` `upsd.users` sample now one `instcmds` per line (it contradicted README and the in-app copy). `.env.dev` (gitignored) comment corrected to match the evidence.
- Flagged, untouched (locked): `.agents/PLAN.md` L92–95 still says upsd is "forwarded to `127.0.0.1:3494` in dev" — false after this phase; evidence + exact operator commands appended to `data/logs/NOTES-verify.md` §11.
- Next pending phase: `11_admin_login`.
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
**Phase 10 final pass — repo green; live criteria blocked off-repo.**
|
||||
|
||||
- Verified: `gateway` runs `dashboards-agent` (active/enabled, `10.1.1.27:9120` → `/health` 200, `/snapshot` 401 no-token / 200 bearer on-host, token matches `/etc/dashboards-agent.token`); `driveripper`/`deskwork` inactive, `sudo -n` → "a password is required", `:9120` empty.
|
||||
- New measurement (transient runtime rule on gateway `firewall-cmd --add-port=9120/tcp`, **reverted** — runtime+permanent port lists verified back to the original set, no rich rules): laptop still gets no SYN through, while `:22`/`:80` on the same address answer in ms ⇒ the block is the lab gateway `10.2.0.1` port filter, not this app/host firewall/agent. No other live change made (no sudoers, no upsd, no UPS command).
|
||||
- Tests/lint (exact): `bash .agents/validate.sh` → **EXIT 0** — `uv run pytest --cov --cov-fail-under=94` **793 passed, 11 skipped, coverage 98.33 %**; `ruff check src tests agent` clean; `pyright` 0 errors; `node --check` clean; hygiene clean; `uv pip list --outdated` empty (bumped fastapi 0.143.3→0.143.5, `uv.lock` only).
|
||||
- `uv run pytest -m live --live` (`.env.dev` sourced): **4 passed, 1 skipped, 6 failed** — all six are `:9120`/`:3051` connect timeouts; zero parse/contract failures.
|
||||
- Dev server restarted on current code: engines `ok`; 3×`host` + 3×`disks` + `nut` `DOWN` with real reasons (designed degradation, stub rows intact, no credential leakage).
|
||||
- Completion criteria: screenshots ✓ (`data/logs/phase10-{index,system,disks,llm,ups}-live.png`); tunnel-vocabulary grep ✓ outside `.agents/` history (PLAN.md locked line, phase overviews, past reports; fixtures/`uv.lock` hits are digit substrings — `tests/test_deploy_scripts.py` guards operational files); no page-payload change ✓ (contract tests). **Not met, operator-side:** agents on all three hosts, `LIST UPS` from the laptop, `dev-server.sh status` all-ok, live suite green.
|
||||
- Fixed in this pass: `sources/nut.py` unreachable-upsd message no longer prints a bare `(TimeoutError: )` (now `(timed out after 4s)` / `(ConnectionRefusedError: …)`), pinned by a new test + extended refused-port test.
|
||||
- Docs: README verified consistent (every env var in `config.py` documented, routes/flags/`--with-llm`/pager sizes checked) — no changes needed. AGENTS.md fixed 4 inconsistencies: per-host sudo reality (gateway grants `NOPASSWD ALL`, which is why it installed without `agent-sudoers`; driveripper scoped; deskwork unrelated), the now-proven firewall finding, `/system` table typo ("agent per host"), gap-4 DB/WAL sizes + test count. `.env.example` `upsd.users` sample now one `instcmds` per line (it contradicted README and the in-app copy). `.env.dev` (gitignored) comment corrected to match the evidence.
|
||||
- Flagged, untouched (locked): `.agents/PLAN.md` L92–95 still says upsd is "forwarded to `127.0.0.1:3494` in dev" — false after this phase; evidence + exact operator commands appended to `data/logs/NOTES-verify.md` §11.
|
||||
- Next pending phase: `11_admin_login`.
|
||||
@@ -0,0 +1 @@
|
||||
ok
|
||||
@@ -0,0 +1,52 @@
|
||||
== uv run pytest --cov (hermetic: no network, live tests skip) ==
|
||||
........................................................................ [ 8%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 26%]
|
||||
........................................................................ [ 35%]
|
||||
........................................................................ [ 44%]
|
||||
........................................................................ [ 53%]
|
||||
..................................sssssssssss........................... [ 62%]
|
||||
........................................................................ [ 71%]
|
||||
........................................................................ [ 80%]
|
||||
........................................................................ [ 89%]
|
||||
........................................................................ [ 98%]
|
||||
............ [100%]
|
||||
=============================== warnings summary ===============================
|
||||
.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1
|
||||
/var/home/ducoterra/Projects/Personal/dashboards/.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
|
||||
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
|
||||
================================ tests coverage ================================
|
||||
_______________ coverage: platform linux, python 3.14.4-final-0 ________________
|
||||
|
||||
Name Stmts Miss Cover Missing
|
||||
------------------------------------------------------------------
|
||||
src/dashboards/__init__.py 3 0 100%
|
||||
src/dashboards/__main__.py 14 1 93% 28
|
||||
src/dashboards/alerts.py 176 0 100%
|
||||
src/dashboards/api.py 221 0 100%
|
||||
src/dashboards/app.py 101 0 100%
|
||||
src/dashboards/collectors.py 155 5 97% 141-142, 146-147, 164
|
||||
src/dashboards/config.py 115 0 100%
|
||||
src/dashboards/debug.py 14 0 100%
|
||||
src/dashboards/poller.py 165 3 98% 192-194, 279
|
||||
src/dashboards/prom.py 105 5 95% 107, 144, 158, 161, 164
|
||||
src/dashboards/rates.py 37 1 97% 51
|
||||
src/dashboards/severity.py 49 0 100%
|
||||
src/dashboards/sources/__init__.py 0 0 100%
|
||||
src/dashboards/sources/disks.py 130 0 100%
|
||||
src/dashboards/sources/host.py 199 1 99% 147
|
||||
src/dashboards/sources/llm.py 150 1 99% 228
|
||||
src/dashboards/sources/nut.py 390 20 95% 137, 151, 157, 169, 175, 187, 195, 208, 279-280, 282, 498, 510, 545, 578, 582, 639-640, 645, 657
|
||||
src/dashboards/sources/nut_sim.py 134 0 100%
|
||||
src/dashboards/store.py 178 2 99% 250-251
|
||||
------------------------------------------------------------------
|
||||
TOTAL 2336 39 98%
|
||||
Required test coverage of 94% reached. Total coverage: 98.33%
|
||||
793 passed, 11 skipped, 1 warning in 59.94s
|
||||
== uv run ruff check src tests agent ==
|
||||
All checks passed!
|
||||
== uv run pyright ==
|
||||
0 errors, 0 warnings, 0 informations
|
||||
== node --check src/dashboards/web/static/*.js ==
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
**Implemented**
|
||||
- `deploy/agent-sudoers` (new, nut-sudoers house style): WHY block, canonical staging path `/home/ops/agent-install`, the single rule `ops ALL=(root) NOPASSWD: /home/ops/agent-install/deploy/install-agent.sh`, two-stage check-first install (`visudo -cf` → `install -m 0440 -o root -g root /etc/sudoers.d/dashboards-agent` → re-check), a "make the grant mean something" `chown -R root:root` note, and a "deliberately NOT granted" block (visudo/sh/tee, other `systemctl`, the token file, user*/groupmod, `upscmd`/`upsrw`).
|
||||
- `deploy/install-agent.sh`: added resolved `SCRIPT_PATH` (realpath + fallback) and `SUDOERS_SOURCE`; `need_root`'s non-root path now prints the exact NOPASSWD line **for its own resolved path**, the two install steps, the pointer to `deploy/agent-sudoers`, and a copy-pasteable re-run command; exit code 1 and root behaviour unchanged (call sites now pass flags so the hint is absolute). Header help names the grant; dropped the stale "ssh tunnel in" parenthetical and marked `--status` as not needing root.
|
||||
- `tests/test_deploy_scripts.py` (new, 16 tests): grant file is exactly one rule at the canonical path, sections/boundaries present, `visudo -cf` passes; installer exits 1 with empty stdout, prints a line identical to the file apart from the path (relative and absolute invocations), names the two-stage install, `--help` points at the file; `bash -n` over `deploy/*.sh` + `scripts/*.sh`.
|
||||
- `data/logs/NOTES-sudoers.md` (+ `phase10-*` artifacts, gitignored): the real diff — identical apart from the path (path-normalised diff is empty).
|
||||
|
||||
**Verification**
|
||||
- `visudo -cf deploy/agent-sudoers` → parsed OK; `bash -n deploy/install-agent.sh` → clean.
|
||||
- `bash deploy/install-agent.sh --bind 127.0.0.1` (as uid 1000) → exit 1, prints `ops ALL=(root) NOPASSWD: /var/home/.../deploy/install-agent.sh`.
|
||||
- `bash .agents/validate.sh` → rc 0: `785 passed, 11 skipped`, coverage **98.33 %** (gate 94 %), ruff clean, pyright 0 errors, `node --check` clean, hygiene clean.
|
||||
|
||||
**Docs**: no doc impact — README.md/AGENTS.md deliberately untouched (task 05 owns the dev-workflow rewrite). Noted in the NOTES file that AGENTS.md's "769 passed" is now 785 so the final pass refreshes it.
|
||||
|
||||
**Decisions/deviations**: grant names `ops` literally (only the path is substituted, so the printed line matches the canonical one); `--token` documented as the one flag never used (installer mints + prints once); added an honest note that the grant is only a boundary once the staged copy is root-owned. **No live-infrastructure changes** — the sudoers line needs root and is the phase's stated user precondition; nothing was touched on the fleet.
|
||||
|
||||
**Next pending task**: `10_dev_direct_dial/02_install_agents_on_fleet.md` (blocked on the user adding the `deploy/agent-sudoers` line as root on each host; task 02 must stop cleanly with instructions if it is missing).
|
||||
+1
@@ -0,0 +1 @@
|
||||
ok
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
== uv run pytest --cov (hermetic: no network, live tests skip) ==
|
||||
........................................................................ [ 9%]
|
||||
........................................................................ [ 18%]
|
||||
........................................................................ [ 27%]
|
||||
........................................................................ [ 36%]
|
||||
........................................................................ [ 45%]
|
||||
........................................................................ [ 54%]
|
||||
...........................sssssssssss.................................. [ 63%]
|
||||
........................................................................ [ 72%]
|
||||
........................................................................ [ 81%]
|
||||
........................................................................ [ 90%]
|
||||
........................................................................ [ 99%]
|
||||
.... [100%]
|
||||
=============================== warnings summary ===============================
|
||||
.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1
|
||||
/var/home/ducoterra/Projects/Personal/dashboards/.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
|
||||
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
|
||||
================================ tests coverage ================================
|
||||
_______________ coverage: platform linux, python 3.14.4-final-0 ________________
|
||||
|
||||
Name Stmts Miss Cover Missing
|
||||
------------------------------------------------------------------
|
||||
src/dashboards/__init__.py 3 0 100%
|
||||
src/dashboards/__main__.py 14 1 93% 28
|
||||
src/dashboards/alerts.py 176 0 100%
|
||||
src/dashboards/api.py 221 0 100%
|
||||
src/dashboards/app.py 101 0 100%
|
||||
src/dashboards/collectors.py 155 5 97% 141-142, 146-147, 164
|
||||
src/dashboards/config.py 115 0 100%
|
||||
src/dashboards/debug.py 14 0 100%
|
||||
src/dashboards/poller.py 165 3 98% 192-194, 279
|
||||
src/dashboards/prom.py 105 5 95% 107, 144, 158, 161, 164
|
||||
src/dashboards/rates.py 37 1 97% 51
|
||||
src/dashboards/severity.py 49 0 100%
|
||||
src/dashboards/sources/__init__.py 0 0 100%
|
||||
src/dashboards/sources/disks.py 130 0 100%
|
||||
src/dashboards/sources/host.py 199 1 99% 147
|
||||
src/dashboards/sources/llm.py 150 1 99% 228
|
||||
src/dashboards/sources/nut.py 389 20 95% 128, 142, 148, 160, 166, 178, 186, 199, 270-271, 273, 489, 501, 536, 569, 573, 630-631, 636, 648
|
||||
src/dashboards/sources/nut_sim.py 134 0 100%
|
||||
src/dashboards/store.py 178 2 99% 250-251
|
||||
------------------------------------------------------------------
|
||||
TOTAL 2335 39 98%
|
||||
Required test coverage of 94% reached. Total coverage: 98.33%
|
||||
785 passed, 11 skipped, 1 warning in 58.73s
|
||||
== uv run ruff check src tests agent ==
|
||||
All checks passed!
|
||||
== uv run pyright ==
|
||||
0 errors, 0 warnings, 0 informations
|
||||
== node --check src/dashboards/web/static/*.js ==
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
**Implemented**
|
||||
- Tunnels stopped; ad-hoc agents gone on all three hosts (`:9120` empty everywhere); `deploy/`+`agent/` staged at the canonical `~/agent-install/` on all three (task file's `rsync deploy/ agent/` trailing slashes would have flattened the tree — used `rsync -a --delete deploy agent`).
|
||||
- **Fixed 2 defects that made `deploy/install-agent.sh` unable to install on any host**, found by the first live run: the install body was a bash function named `install`, so `install -d` recursed forever (1 700 repeats, nothing installed); and `DevicePolicy=strict` without `/dev/null` kills the unit at spawn (`status=208/STDIN`, systemd 257 — proven with two transient `systemd-run` probes). Plus a latent third: token file `0600 root:root` is unreadable by the service that opens the path itself → now `0640 root:dashboards-agent`.
|
||||
- **gateway: INSTALLED** — `dashboards-agent` active + enabled, bound `10.1.1.27:9120`, `/health` ok, `/snapshot` 401 without / 200 with bearer; deployed unit matches the repo template; token captured into `.env.dev` (0600, gitignored), not in NOTES.
|
||||
- **driveripper + deskwork: BLOCKED** — precondition unmet (`/etc/sudoers.d/dashboards-agent` absent, `sudo -n … --status` → "a password is required"). Stopped cleanly; exact `visudo`/`install` lines + the one `firewall-cmd` line per host are in `data/logs/NOTES-agent-install.md`. **No sudoers or firewall edit was attempted.**
|
||||
- Laptop-side reach is blocked on **all three** hosts' firewalld (9120/tcp closed; control: gateway:80 answers 301) — recorded with both the bare-port and `/21`-scoped rich-rule commands, not guessed.
|
||||
|
||||
**Tests / lint / coverage**
|
||||
- `uv run pytest` → **792 passed, 11 skipped**; `uv run pytest --cov --cov-fail-under=94` → **98.33%**; `uv run ruff check src tests agent` → passed; `uv run pyright` → 0 errors; `node --check` all page scripts ok; `bash -n` all scripts ok.
|
||||
- New in `tests/test_deploy_scripts.py`: install body run end-to-end in a `tmp_path` sandbox (paths rewritten, root boundary stubbed) asserting it returns, lands the agent, writes `DeviceAllow=/dev/null`, prints the token once, leaves it `0640`; plus a static "no shell function named after a coreutil" check.
|
||||
|
||||
**Docs**: README (`0640 root:dashboards-agent`, device-policy rationale, `deploy/agent-sudoers` pointer); AGENTS.md (deployment paragraph, fleet SMART paragraph — gateway's installed agent now answers `smartctl_available: false` — and a transport mid-transition note pointing at NOTES; task 05 still owns the full direct-dial rewrite).
|
||||
|
||||
**Deviations / notes**
|
||||
- `uv run pytest -m live --live` currently fails 6 — all transport (dead loopback tunnel ports + stopped `3494` forward), the state the phase expects for blocked hosts; green after the grant + task 04/06. Dev server is up and reports those sources red with real reasons.
|
||||
- Next pending: **re-run task 02 for driveripper/deskwork after the user adds the sudoers grant**, then `.agents/phases/todo/10_dev_direct_dial/03_upsd_acl_for_laptop.md`.
|
||||
+1
@@ -0,0 +1 @@
|
||||
ok
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
== uv run pytest --cov (hermetic: no network, live tests skip) ==
|
||||
........................................................................ [ 8%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 26%]
|
||||
........................................................................ [ 35%]
|
||||
........................................................................ [ 44%]
|
||||
........................................................................ [ 53%]
|
||||
..................................sssssssssss........................... [ 62%]
|
||||
........................................................................ [ 71%]
|
||||
........................................................................ [ 80%]
|
||||
........................................................................ [ 89%]
|
||||
........................................................................ [ 98%]
|
||||
........... [100%]
|
||||
=============================== warnings summary ===============================
|
||||
.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1
|
||||
/var/home/ducoterra/Projects/Personal/dashboards/.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
|
||||
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
|
||||
================================ tests coverage ================================
|
||||
_______________ coverage: platform linux, python 3.14.4-final-0 ________________
|
||||
|
||||
Name Stmts Miss Cover Missing
|
||||
------------------------------------------------------------------
|
||||
src/dashboards/__init__.py 3 0 100%
|
||||
src/dashboards/__main__.py 14 1 93% 28
|
||||
src/dashboards/alerts.py 176 0 100%
|
||||
src/dashboards/api.py 221 0 100%
|
||||
src/dashboards/app.py 101 0 100%
|
||||
src/dashboards/collectors.py 155 5 97% 141-142, 146-147, 164
|
||||
src/dashboards/config.py 115 0 100%
|
||||
src/dashboards/debug.py 14 0 100%
|
||||
src/dashboards/poller.py 165 3 98% 192-194, 279
|
||||
src/dashboards/prom.py 105 5 95% 107, 144, 158, 161, 164
|
||||
src/dashboards/rates.py 37 1 97% 51
|
||||
src/dashboards/severity.py 49 0 100%
|
||||
src/dashboards/sources/__init__.py 0 0 100%
|
||||
src/dashboards/sources/disks.py 130 0 100%
|
||||
src/dashboards/sources/host.py 199 1 99% 147
|
||||
src/dashboards/sources/llm.py 150 1 99% 228
|
||||
src/dashboards/sources/nut.py 389 20 95% 128, 142, 148, 160, 166, 178, 186, 199, 270-271, 273, 489, 501, 536, 569, 573, 630-631, 636, 648
|
||||
src/dashboards/sources/nut_sim.py 134 0 100%
|
||||
src/dashboards/store.py 178 2 99% 250-251
|
||||
------------------------------------------------------------------
|
||||
TOTAL 2335 39 98%
|
||||
Required test coverage of 94% reached. Total coverage: 98.33%
|
||||
792 passed, 11 skipped, 1 warning in 59.37s
|
||||
== uv run ruff check src tests agent ==
|
||||
All checks passed!
|
||||
== uv run pyright ==
|
||||
0 errors, 0 warnings, 0 informations
|
||||
== node --check src/dashboards/web/static/*.js ==
|
||||
@@ -0,0 +1,13 @@
|
||||
**Task 03 outcome: repo/records side complete and green; the prescribed live write was proven a no-op and the laptop leg is blocked off-host (details below).**
|
||||
|
||||
- Read-first done: `data/logs/upsd.conf.before` (369 B, `LISTEN 0.0.0.0/:: 3051`, no ACL lines); live file re-read + `diff` → **identical**; `upsd.users`/all `/etc/ups` mtimes unchanged; `nut-server` still `active`, `NRestarts=0`, `upsc … ups.status` = `OL` on both UPSes.
|
||||
- Ranges derived: hosts `10.1.0.0/21` (`bridge0 10.1.0.126/21`), laptop `10.2.1.113` in `10.2.0.0/22` (ssh source + `ip -o addr`); v6 `…:101::/64` vs `…:102::/64`.
|
||||
- **Did not append the two `ACL` lines — they enforce nothing on this upstream.** `nut-2.8.5-9.fc43` is built `--without-wrap`; `man 5 upsd.conf` has no ACL section; sandboxed `NUT_CONFPATH` runs (live service untouched) show upsd logging `ACL in upsd.conf is no longer supported - switch to LISTEN` per line and then starting anyway → a config that claims restriction, logs an error against itself on every restart, and changes no packet. On 2.8 the mechanism is `LISTEN` + firewall, both already correct here.
|
||||
- Firewall (task step 5): `firewalld` running, `FedoraServer` on `bridge0/enp3s0`, **`3051/tcp` already allowed** (runtime + permanent), no rich/direct rules → nothing to add; the optional `--remove-port` + 2 rich-rule scoping is recorded verbatim but deliberately not applied (no reachable behaviour changes, deny path unverifiable from here, prod + `upsmon` dial loopback).
|
||||
- **BLOCKER (operator, off-fleet):** from the laptop, `nc 10.1.0.126 3051` (v4 and v6) times out and **no SYN ever arrives** — proven by a 0.5 s `ss -tan sport = :3051` loop during 4 attempts (only pre-existing `[::1]` sessions) beside control probes where the same laptop's payload to `:1234` landed in an `ncat` log and `:8004` RST in 10 ms. The drop is the lab gateway `10.2.0.1` (`d8:b3:70:85:53:e6`, UniFi) between `10.2.0.0/22` and `10.1.0.0/21`: it forwards 22/1234/8000-8004, drops 1235/3051/3493/5901. No `ops` sudo on a fleet host touches it.
|
||||
- Objective half already true: from `deskwork` (host range) `printf 'LIST UPS\n' | nc 10.1.0.126 3051` → `BEGIN LIST UPS … END LIST UPS`.
|
||||
- All evidence, the operator's exact one rule (UniFi LAN→LAN allow 3051/tcp from `10.2.0.0/22` to `10.1.0.126`), the three interim options, and the two premise corrections are in `data/logs/NOTES-upsd-acl.md`. No Python changes, so no new tests were applicable.
|
||||
- Gate: `bash .agents/validate.sh` → **exit 0** (`uv run pytest --cov --cov-fail-under=94` → **792 passed, 11 skipped, 98.33%**; `ruff check src tests agent` passed; `pyright` 0 errors; `node --check` ok; hygiene gates ok); `uv pip list --outdated` empty; dev server still up (sources red with real reasons — task 02's in-between state, untouched).
|
||||
- Docs: **AGENTS.md** (NUT paragraph: 2.8 has no `ACL`, restriction is firewall-only, non-local reads are the norm, host range reaches 3051 / laptop range does not; transport bullet now points at `NOTES-upsd-acl.md`) and **README.md** (Battery-test section: `ACL`/`ACCEPT`/`REJECT` removed upstream, don't scope by client in `upsd.conf`).
|
||||
- Completion criteria met: no `upsd.users` write, nut-server healthy/unrestarted, suite green, docs accurate. **Not met, and not achievable from this repo:** "diff shows exactly the two ACL lines" (would enforce nothing) and "laptop `nc` answers `BEGIN LIST UPS`" (gateway port filter). Task 04 should keep `NUT_HOST` pending that operator rule; the derived ranges are ready in the NOTES file.
|
||||
- Next pending: operator rule on gateway `10.2.0.1` (+ task 02's still-missing sudoers grant on driveripper/deskwork), then `.agents/phases/todo/10_dev_direct_dial/04_env_dev_direct_dial.md`.
|
||||
+1
@@ -0,0 +1 @@
|
||||
ok
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
== uv run pytest --cov (hermetic: no network, live tests skip) ==
|
||||
........................................................................ [ 8%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 26%]
|
||||
........................................................................ [ 35%]
|
||||
........................................................................ [ 44%]
|
||||
........................................................................ [ 53%]
|
||||
..................................sssssssssss........................... [ 62%]
|
||||
........................................................................ [ 71%]
|
||||
........................................................................ [ 80%]
|
||||
........................................................................ [ 89%]
|
||||
........................................................................ [ 98%]
|
||||
........... [100%]
|
||||
=============================== warnings summary ===============================
|
||||
.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1
|
||||
/var/home/ducoterra/Projects/Personal/dashboards/.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
|
||||
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
|
||||
================================ tests coverage ================================
|
||||
_______________ coverage: platform linux, python 3.14.4-final-0 ________________
|
||||
|
||||
Name Stmts Miss Cover Missing
|
||||
------------------------------------------------------------------
|
||||
src/dashboards/__init__.py 3 0 100%
|
||||
src/dashboards/__main__.py 14 1 93% 28
|
||||
src/dashboards/alerts.py 176 0 100%
|
||||
src/dashboards/api.py 221 0 100%
|
||||
src/dashboards/app.py 101 0 100%
|
||||
src/dashboards/collectors.py 155 5 97% 141-142, 146-147, 164
|
||||
src/dashboards/config.py 115 0 100%
|
||||
src/dashboards/debug.py 14 0 100%
|
||||
src/dashboards/poller.py 165 3 98% 192-194, 279
|
||||
src/dashboards/prom.py 105 5 95% 107, 144, 158, 161, 164
|
||||
src/dashboards/rates.py 37 1 97% 51
|
||||
src/dashboards/severity.py 49 0 100%
|
||||
src/dashboards/sources/__init__.py 0 0 100%
|
||||
src/dashboards/sources/disks.py 130 0 100%
|
||||
src/dashboards/sources/host.py 199 1 99% 147
|
||||
src/dashboards/sources/llm.py 150 1 99% 228
|
||||
src/dashboards/sources/nut.py 389 20 95% 128, 142, 148, 160, 166, 178, 186, 199, 270-271, 273, 489, 501, 536, 569, 573, 630-631, 636, 648
|
||||
src/dashboards/sources/nut_sim.py 134 0 100%
|
||||
src/dashboards/store.py 178 2 99% 250-251
|
||||
------------------------------------------------------------------
|
||||
TOTAL 2335 39 98%
|
||||
Required test coverage of 94% reached. Total coverage: 98.33%
|
||||
792 passed, 11 skipped, 1 warning in 59.63s
|
||||
== uv run ruff check src tests agent ==
|
||||
All checks passed!
|
||||
== uv run pyright ==
|
||||
0 errors, 0 warnings, 0 informations
|
||||
== node --check src/dashboards/web/static/*.js ==
|
||||
@@ -0,0 +1,19 @@
|
||||
**Implemented**
|
||||
- `./scripts/dev-tunnels.sh stop` (no-op; already down), laptop has nothing on 9121/9122/9123/3494.
|
||||
- `.env.dev` rewritten direct-shaped, mode `0600` kept: `HOST_TARGETS="driveripper=http://10.1.0.126:9120 deskwork=http://10.1.0.51:9120 gateway=http://<token>@10.1.1.27:9120"`, `NUT_HOST=10.1.0.126`/`NUT_PORT=3051`, `DASH_PORT=8090` explicit, no `DEV_TUNNELS`/`DEV_FORWARDS`, comments naming where the upsd access rules actually live and why a laptop-IP change is the operator's gateway rule, not this file.
|
||||
- Verified the gateway credential against the live service without printing it (sha256 equal to `/etc/dashboards-agent.token`; agent answers 401 without bearer / 200 with it, host-side) and `NUT_PASSWORD` against `[dashboards]` in the live `upsd.users` (`instcmds = all` — corrected the file's stale "battery-test only" comment).
|
||||
- Restarted the dev server; `/api/config` redacts userinfo, `/api/system/snapshot` keeps all three hosts as `unreachable` stubs (`hosts_total 3 / hosts_live 0`), `/api/summary` alerts name the 4 dead sources, `/api/events` shows only the 7 switchover `unreachable` transitions. Token-hits = 0 across all 7 API surfaces.
|
||||
- Evidence + the 3 remaining operator actions: `data/logs/NOTES-env-dev-direct-dial.md` (+ correction appended to `NOTES-agent-install.md`).
|
||||
|
||||
**Tests / lint / coverage**
|
||||
- `bash .agents/validate.sh` → exit 0: `uv run pytest --cov --cov-fail-under=94` **792 passed, 11 skipped, coverage 98.33%**; `ruff check src tests agent` clean; `pyright` 0 errors; `node --check` clean. `uv pip list --outdated` empty.
|
||||
- `uv run pytest -m live --live` (with `.env.dev` sourced): 11 live tests, **5 pass (both engines), 6 fail on transport only** — 3 × `ConnectTimeout` to the `:9120`s, 3 × `cannot reach upsd at 10.1.0.126:3051`. Task 06 owns making these green.
|
||||
|
||||
**Docs** — README + AGENTS updated only where this change falsified them: tunnel-based dev quickstart → direct dial (`install-agent.sh` + userinfo tokens + `NUT_PORT=3051`); removed the now-false "`dev-tunnels.sh start` … temporary way to see live data" fallback; `DEV_FORWARDS="3494:…"` fleet fact → direct dial; NUT "bind upsd" advice no longer points at a forward; hermetic count 769 → 792. `git grep dev-tunnels|DEV_TUNNELS|DEV_FORWARDS|9121|9122|9123|3494` now matches neither file. Task 05's file list (`.env.dev.example`, `scripts/dev-tunnels.sh`, `capture-fixtures.sh`, live-suite strings, `ups_contract.py`, `alerts.py` docstring, `test_config.py`, `.env.example`) left untouched.
|
||||
|
||||
**Decisions / deviations**
|
||||
- **No live changes to any host, firewall or service.** `driveripper`/`deskwork` stay BLOCKED (root-only sudoers grant missing — re-checked: `sudo -n … --status` still `a password is required`); gateway's `9120/tcp` stays closed. Opening it means a firewall edit on the lab router whose benefit is unverifiable from here (its policy is port-selective and drops 3051/3493 today, so 9120 may be dropped too), and tasks 02/03 both explicitly left firewall policy to the operator. No `NUT_SIMULATE`, no tunnel fallback — the reds are real, with the reason.
|
||||
- Kept `driveripper`/`deskwork` in `HOST_TARGETS` **without** tokens (none exist) so the fleet still shows them as unreachable stubs instead of losing machines.
|
||||
- Current live result, stated plainly: engines `ok`; every `system`/`disks`/`ups` source `DOWN` with a real reason — nothing that was healthy before the switchover regressed. `.env.dev.example` is still tunnel-shaped (task 05), so the README `cp` line currently points at a file awaiting that rewrite.
|
||||
|
||||
**Next pending task:** `.agents/phases/todo/10_dev_direct_dial/05_retire_tunnels_update_scripts.md`
|
||||
+1
@@ -0,0 +1 @@
|
||||
ok
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
== uv run pytest --cov (hermetic: no network, live tests skip) ==
|
||||
........................................................................ [ 8%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 26%]
|
||||
........................................................................ [ 35%]
|
||||
........................................................................ [ 44%]
|
||||
........................................................................ [ 53%]
|
||||
..................................sssssssssss........................... [ 62%]
|
||||
........................................................................ [ 71%]
|
||||
........................................................................ [ 80%]
|
||||
........................................................................ [ 89%]
|
||||
........................................................................ [ 98%]
|
||||
........... [100%]
|
||||
=============================== warnings summary ===============================
|
||||
.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1
|
||||
/var/home/ducoterra/Projects/Personal/dashboards/.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
|
||||
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
|
||||
================================ tests coverage ================================
|
||||
_______________ coverage: platform linux, python 3.14.4-final-0 ________________
|
||||
|
||||
Name Stmts Miss Cover Missing
|
||||
------------------------------------------------------------------
|
||||
src/dashboards/__init__.py 3 0 100%
|
||||
src/dashboards/__main__.py 14 1 93% 28
|
||||
src/dashboards/alerts.py 176 0 100%
|
||||
src/dashboards/api.py 221 0 100%
|
||||
src/dashboards/app.py 101 0 100%
|
||||
src/dashboards/collectors.py 155 5 97% 141-142, 146-147, 164
|
||||
src/dashboards/config.py 115 0 100%
|
||||
src/dashboards/debug.py 14 0 100%
|
||||
src/dashboards/poller.py 165 3 98% 192-194, 279
|
||||
src/dashboards/prom.py 105 5 95% 107, 144, 158, 161, 164
|
||||
src/dashboards/rates.py 37 1 97% 51
|
||||
src/dashboards/severity.py 49 0 100%
|
||||
src/dashboards/sources/__init__.py 0 0 100%
|
||||
src/dashboards/sources/disks.py 130 0 100%
|
||||
src/dashboards/sources/host.py 199 1 99% 147
|
||||
src/dashboards/sources/llm.py 150 1 99% 228
|
||||
src/dashboards/sources/nut.py 389 20 95% 128, 142, 148, 160, 166, 178, 186, 199, 270-271, 273, 489, 501, 536, 569, 573, 630-631, 636, 648
|
||||
src/dashboards/sources/nut_sim.py 134 0 100%
|
||||
src/dashboards/store.py 178 2 99% 250-251
|
||||
------------------------------------------------------------------
|
||||
TOTAL 2335 39 98%
|
||||
Required test coverage of 94% reached. Total coverage: 98.33%
|
||||
792 passed, 11 skipped, 1 warning in 54.19s
|
||||
== uv run ruff check src tests agent ==
|
||||
All checks passed!
|
||||
== uv run pyright ==
|
||||
0 errors, 0 warnings, 0 informations
|
||||
== node --check src/dashboards/web/static/*.js ==
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
All green. Final report:
|
||||
|
||||
**Implemented**
|
||||
- Deleted `scripts/dev-tunnels.sh` (working-tree `D`; harness stages) + removed its generated `data/tunnels/` leftovers.
|
||||
- `scripts/capture-fixtures.sh`: sources `.env.dev` first, derives agents by parsing `HOST_TARGETS` (`name=url`, space/comma, userinfo token used as-is, `/snapshot` appended); skip note when unset; failure lines name the host, never the token; all tunnel hints gone.
|
||||
- `tests/test_live_fleet.py` docstring → direct-dial loop; skips now `HOST_TARGETS is unset` / `no host agent answered`; `ups_contract.py`, `alerts.py` docstring, `test_config.py`, `test_alerts.py`, `test_api.py`, `test_disks_source.py` strings moved to the `:9120` direct shape; stale `tunnel-check` gone from `dev-server.sh` header.
|
||||
- `.env.dev.example` rewritten direct-shaped (installer + `agent-sudoers` flow, userinfo tokens, `NUT_HOST`/`NUT_PORT=3051`, port-discovery + firewall notes, RFC 2606 hosts, never-commit warning); verified it parses through the app's own `parse_targets` (3 targets, headers set, redacted display URLs).
|
||||
- New guards in `tests/test_deploy_scripts.py`: script stays deleted + no tunnel name/port in any operational file (scripts/deploy/src/agent/web/tests `.py`/README/AGENTS/example envs; fixtures & `.agents/` history excluded by design).
|
||||
- **Deviation (rule 7 / task-03 findings):** `.env.example`'s "third option" is written as *bind LAN + firewall-scope the dashboard's source ranges*, not "ACL in `upsd.conf`" — NUT 2.8.5 has no `ACL` directive (logs "switch to LISTEN", enforces nothing); same truth README already carries.
|
||||
|
||||
**Verification** — `bash .agents/validate.sh` → **EXIT 0**: `uv run pytest --cov --cov-fail-under=94` **792 passed, 11 skipped, 98.33 %**; `ruff` clean; `pyright` 0 errors; `node --check` clean. `bash -n` clean on both edited scripts; `uv pip list --outdated` empty; dev server restarted (`/api/health` sane: engines ok, hosts `DOWN` with real reasons — unchanged task-04 state; no live infra touched).
|
||||
|
||||
**Docs** — AGENTS.md transport bullet rewritten ("dev is the prod topology, repo-wide", systemd-agent-via-grant + firewall-scoped upsd); README was already direct-shaped by task 04, verified consistent.
|
||||
|
||||
**Grep criterion** — matches remain only in `.agents/` history (incl. locked `PLAN.md:94` "3494" — flagged for the final pass, untouched; `todo/11_admin_login/00_phase.md` names the vars only to forbid restoring them), `tests/fixtures/` verbatim captures, and `uv.lock` hashes.
|
||||
|
||||
**Next pending task:** `.agents/phases/todo/10_dev_direct_dial/06_verify_direct_dial_live.md`.
|
||||
+1
@@ -0,0 +1 @@
|
||||
ok
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
== uv run pytest --cov (hermetic: no network, live tests skip) ==
|
||||
........................................................................ [ 8%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 26%]
|
||||
........................................................................ [ 35%]
|
||||
........................................................................ [ 44%]
|
||||
........................................................................ [ 53%]
|
||||
..................................sssssssssss........................... [ 62%]
|
||||
........................................................................ [ 71%]
|
||||
........................................................................ [ 80%]
|
||||
........................................................................ [ 89%]
|
||||
........................................................................ [ 98%]
|
||||
........... [100%]
|
||||
=============================== warnings summary ===============================
|
||||
.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1
|
||||
/var/home/ducoterra/Projects/Personal/dashboards/.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
|
||||
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
|
||||
================================ tests coverage ================================
|
||||
_______________ coverage: platform linux, python 3.14.4-final-0 ________________
|
||||
|
||||
Name Stmts Miss Cover Missing
|
||||
------------------------------------------------------------------
|
||||
src/dashboards/__init__.py 3 0 100%
|
||||
src/dashboards/__main__.py 14 1 93% 28
|
||||
src/dashboards/alerts.py 176 0 100%
|
||||
src/dashboards/api.py 221 0 100%
|
||||
src/dashboards/app.py 101 0 100%
|
||||
src/dashboards/collectors.py 155 5 97% 141-142, 146-147, 164
|
||||
src/dashboards/config.py 115 0 100%
|
||||
src/dashboards/debug.py 14 0 100%
|
||||
src/dashboards/poller.py 165 3 98% 192-194, 279
|
||||
src/dashboards/prom.py 105 5 95% 107, 144, 158, 161, 164
|
||||
src/dashboards/rates.py 37 1 97% 51
|
||||
src/dashboards/severity.py 49 0 100%
|
||||
src/dashboards/sources/__init__.py 0 0 100%
|
||||
src/dashboards/sources/disks.py 130 0 100%
|
||||
src/dashboards/sources/host.py 199 1 99% 147
|
||||
src/dashboards/sources/llm.py 150 1 99% 228
|
||||
src/dashboards/sources/nut.py 389 20 95% 128, 142, 148, 160, 166, 178, 186, 199, 270-271, 273, 489, 501, 536, 569, 573, 630-631, 636, 648
|
||||
src/dashboards/sources/nut_sim.py 134 0 100%
|
||||
src/dashboards/store.py 178 2 99% 250-251
|
||||
------------------------------------------------------------------
|
||||
TOTAL 2335 39 98%
|
||||
Required test coverage of 94% reached. Total coverage: 98.33%
|
||||
792 passed, 11 skipped, 1 warning in 59.97s
|
||||
== uv run ruff check src tests agent ==
|
||||
All checks passed!
|
||||
== uv run pyright ==
|
||||
0 errors, 0 warnings, 0 informations
|
||||
== node --check src/dashboards/web/static/*.js ==
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
**Implemented (task 06 — verify direct-dial live)**
|
||||
- Restarted the dev server on direct dial and recorded `/api/health`: `llm:gufo`/`llm:vllm` **ok** with live data; 3 `host:*` + 3 `disks:*` + `nut` DOWN with their real reasons (identical to the task-02/03/04 blockers); 0 `store-error`/`database is locked` lines; credential sweep proves the gateway bearer token appears in **no** API response.
|
||||
- Proved no tunnel port exists: `ss -ltn | grep -E ':(9121|9122|9123|3494)\s'` → empty; `git grep` for the tunnel names/ports → nothing outside `.agents/` (only digit substrings in `uv.lock` hashes and one SMART raw counter).
|
||||
- Prod-side proof (read-only, no writes): gateway's installed unit `active`, `10.1.1.27:9120` `/health` 200 / `/snapshot` 401-no-token / 200-with-token; that live snapshot through the **production** parsers passes `assert_card_contract` and yields the documented `/disks` degradation (`vda`, `smart: null`, `smartctl_available: false`); upsd answers `LIST UPS` for both UPSes from loopback **and from deskwork**.
|
||||
- Browser verification (visible Chromium): `data/logs/phase10-{index,system,disks,llm,ups}-live.png` — `/llm` fully live (fleet 2/2, KV bars, slot grid, TTFT/TPOT, history charts); `/ups` honest "none reporting", **no SIMULATED badge**.
|
||||
- Wrote `data/logs/NOTES-verify.md` (health table, live-suite tally, probe evidence localising the block to the lab gateway's port allow-list, the 3 operator actions, and the **PLAN.md L92–95 staleness flag** — "forwarded to `127.0.0.1:3494` in dev" is now false; file untouched).
|
||||
|
||||
**Tests/lint/coverage** — `bash .agents/validate.sh` → **EXIT 0**: `uv run pytest --cov --cov-fail-under=94` → **792 passed, 11 skipped, 98.33 %** (gate 94); `ruff check src tests agent` clean; `pyright` **0 errors**; `node --check` clean; `uv pip list --outdated` empty.
|
||||
|
||||
**Deviation / stopped short (live-infra)** — `uv run pytest -m live --live` is **4 passed, 1 skipped, 6 failed**; all six failures are connect timeouts to `:9120`/`:3051`, none a parse or contract. Making them green needs root on driveripper/deskwork (sudoers grant), host `9120/tcp`, and a rule on the lab gateway `10.2.0.1` — none reachable by `ops` sudo, and the laptop-side probes show the gateway drops even host-allowed ports (e.g. 3478), so opening gateway's `9120` has unknown payoff for at most 2 of 7 red sources. I therefore made **no live change** (no firewall, service, config write or UPS command) and left the reversible one-line experiment + exact operator commands in §7–§8 of the notes. `test_every_host_agent_answers_and_parses` is deliberately not turned into a skip — it is the reachability signal this phase exists to produce.
|
||||
|
||||
**Docs** — `AGENTS.md`: fleet bullet now also points at `data/logs/NOTES-verify.md` as the direct-dial verification record (re-verified facts unchanged). No README change needed (already direct-shaped; grep-clean).
|
||||
|
||||
**Next pending task** — `.agents/phases/todo/11_admin_login/01_auth_primitives.md` (phase 10's tasks are all complete).
|
||||
+1
@@ -0,0 +1 @@
|
||||
ok
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
== uv run pytest --cov (hermetic: no network, live tests skip) ==
|
||||
........................................................................ [ 8%]
|
||||
........................................................................ [ 17%]
|
||||
........................................................................ [ 26%]
|
||||
........................................................................ [ 35%]
|
||||
........................................................................ [ 44%]
|
||||
........................................................................ [ 53%]
|
||||
..................................sssssssssss........................... [ 62%]
|
||||
........................................................................ [ 71%]
|
||||
........................................................................ [ 80%]
|
||||
........................................................................ [ 89%]
|
||||
........................................................................ [ 98%]
|
||||
........... [100%]
|
||||
=============================== warnings summary ===============================
|
||||
.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1
|
||||
/var/home/ducoterra/Projects/Personal/dashboards/.venv/lib64/python3.14/site-packages/fastapi/testclient.py:1: StarletteDeprecationWarning: Using `httpx` with `starlette.testclient` is deprecated; install `httpx2` instead.
|
||||
from starlette.testclient import TestClient as TestClient # noqa
|
||||
|
||||
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
|
||||
================================ tests coverage ================================
|
||||
_______________ coverage: platform linux, python 3.14.4-final-0 ________________
|
||||
|
||||
Name Stmts Miss Cover Missing
|
||||
------------------------------------------------------------------
|
||||
src/dashboards/__init__.py 3 0 100%
|
||||
src/dashboards/__main__.py 14 1 93% 28
|
||||
src/dashboards/alerts.py 176 0 100%
|
||||
src/dashboards/api.py 221 0 100%
|
||||
src/dashboards/app.py 101 0 100%
|
||||
src/dashboards/collectors.py 155 5 97% 141-142, 146-147, 164
|
||||
src/dashboards/config.py 115 0 100%
|
||||
src/dashboards/debug.py 14 0 100%
|
||||
src/dashboards/poller.py 165 3 98% 192-194, 279
|
||||
src/dashboards/prom.py 105 5 95% 107, 144, 158, 161, 164
|
||||
src/dashboards/rates.py 37 1 97% 51
|
||||
src/dashboards/severity.py 49 0 100%
|
||||
src/dashboards/sources/__init__.py 0 0 100%
|
||||
src/dashboards/sources/disks.py 130 0 100%
|
||||
src/dashboards/sources/host.py 199 1 99% 147
|
||||
src/dashboards/sources/llm.py 150 1 99% 228
|
||||
src/dashboards/sources/nut.py 389 20 95% 128, 142, 148, 160, 166, 178, 186, 199, 270-271, 273, 489, 501, 536, 569, 573, 630-631, 636, 648
|
||||
src/dashboards/sources/nut_sim.py 134 0 100%
|
||||
src/dashboards/store.py 178 2 99% 250-251
|
||||
------------------------------------------------------------------
|
||||
TOTAL 2335 39 98%
|
||||
Required test coverage of 94% reached. Total coverage: 98.33%
|
||||
792 passed, 11 skipped, 1 warning in 59.49s
|
||||
== uv run ruff check src tests agent ==
|
||||
All checks passed!
|
||||
== uv run pyright ==
|
||||
0 errors, 0 warnings, 0 informations
|
||||
== node --check src/dashboards/web/static/*.js ==
|
||||
Reference in New Issue
Block a user