Show empty-state text on empty table panels
A table panel with no rows rendered its column headers over an empty body. On a live PC Details page that made Network Interfaces and Listening Ports look like cards that had failed to load, when the real answer was that the agent had not reported any yet. List panels already honoured panel.empty; table panels did not. Also records the simulation-suite requirement uncovered when rolling containers: the pytest suite builds its schema from the models, so an unapplied migration is invisible to it while every query against the affected table 500s in the running image.
This commit is contained in:
@@ -423,6 +423,52 @@ would be the behaviour the removed comment falsely claimed.
|
||||
|
||||
---
|
||||
|
||||
## Simulation suite - required check (from a real dev-environment failure)
|
||||
|
||||
The suite must assert that CODE AND SCHEMA ARE NEVER SERVED OUT OF STEP, and
|
||||
must do it by bringing the image UP, not by building a schema from the models.
|
||||
|
||||
Observed 2026-09-05 in dev, after rolling containers for the Phase 3/4 UI work:
|
||||
every query against `endpointstates` returned 500 with
|
||||
|
||||
(1054, "Unknown column 'endpointstates.diskhealthjson' in 'field list'")
|
||||
|
||||
The Phase 2 migrations (endpoints 0014, 0015) were written and committed WITH
|
||||
their models, correctly. They had simply never been applied to that database.
|
||||
`flask plugin upgrade-all` fixed it in one command.
|
||||
|
||||
Why nothing caught it:
|
||||
|
||||
- The pytest suite builds its schema from the models, so model and schema are
|
||||
by construction in step. This class of fault is INVISIBLE to it. A green test
|
||||
run says nothing about whether a deployed database has the columns.
|
||||
- Nothing in the startup path checks. `create_app()` and `wsgi.py` do no
|
||||
migration-state validation, so the container reports HEALTHY while every
|
||||
query against the affected table 500s. The health check passes because it
|
||||
does not touch the table.
|
||||
- `flask db preflight` exists but is manual and pre-migration; it is not a
|
||||
guard on serving traffic.
|
||||
|
||||
The failure is also SILENT IN THE UI in a way that misdirects: a panel whose
|
||||
endpoint 500s is dropped from `populatedGroups`, so its whole TAB disappears
|
||||
from PC Details. The visible symptom was a missing "Service/Process Monitors"
|
||||
tab, which reads as a UI regression in the tab-vocabulary code and sends you
|
||||
to entirely the wrong file. Nothing on the page mentions the database.
|
||||
|
||||
So the suite needs, at minimum:
|
||||
|
||||
1. A start-up case that runs the real image against a database deliberately
|
||||
left one migration behind, and asserts the mismatch is reported LOUDLY -
|
||||
not a healthy container serving 500s.
|
||||
2. Coverage that the documented order (`flask db upgrade`, then
|
||||
`flask plugin upgrade-all`, THEN serve) is what the container actually does.
|
||||
3. A UI-level assertion that a 500ing panel endpoint does not silently remove a
|
||||
tab with no explanation on screen.
|
||||
|
||||
Worth considering separately from the suite: a startup guard that refuses to
|
||||
serve, or at least logs at ERROR, when a model references a column the database
|
||||
does not have. Cheap here, expensive on a fleet rollout.
|
||||
|
||||
## Open questions - answer before the relevant phase
|
||||
|
||||
1. ~~LAPS~~ - RESOLVED: not a feature request. The user was illustrating why the
|
||||
|
||||
Reference in New Issue
Block a user