feat: host_agent plugin — push-model host resource monitoring #1
Reference in New Issue
Block a user
Delete Branch "feat/host-agent"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Adds the
host_agentRoundtable plugin: a lightweight stdlib-only Python agent that runs on each monitored Linux host, collects CPU / memory / disk / load / uptime from/procevery 30s, and POSTs signed payloads to a bearer-token-authed ingest endpoint. Admin UI handles host registration, token rotation, and widget / alert integration.Spec:
docs/plugins/host-agent-design.mdPlan:
docs/plugins/host-agent-plan.mdWhat's in this PR
Main repo (this branch, 10 commits ahead of main):
docs/plugins/host-agent-design.md— design specdocs/plugins/host-agent-plan.md— 15-task implementation plan + path-1 notedocs/plugins/index.yaml.example— catalog entryroundtable/core/widgets.py—host_resources+host_resource_historywidget registrationsroundtable/alerts/routes.py—host_agententry inMETRIC_CATALOG(9 metrics)tests/plugins/host_agent/— 42 pure-Python unit tests (config parser, collectors, ring buffer, payload builder, agent POST + backoff, metric expander, install.sh template render, stale-agent filter)Plugins repo (
Roundtable-plugins@7468806, already pushed tomain):host_agent/agent.py(370 LoC single-file daemon)host_agent/routes.py— ingest / install.sh / agent.py / widgets / settingshost_agent/scheduler.py— stale-agent checkhost_agent/models.py—HostAgentRegistration(token hash, last_seen, metadata)host_agent/migrations/versions/host_agent_001_initial.pyhost_agent/templates/—install.sh.j2,settings_list.html,widget_table.html,widget_history.htmlhost_agent/plugin.yaml,__init__.pyTest plan
pytest tests/plugins/host_agent— 42/42 passing locallypytest tests/— no regressions beyond pre-existing RuntimeWarnings/plugins/host_agent/install.sh?token=…renders templated systemd installer, passessh -n/plugins/host_agent/agent.pyserves the agent sourcehttp://localhost:5000successfully posts samples every 30splugin_metricspopulated withcpu_pct,mem_used_pct,mem_available_bytes,swap_used_bytes,load_1m/5m/15m,uptime_secs,disk_used_pct_worst, and per-mountdisk_used_pct/disk_used_bytes/disk_total_bytesregistrations.last_seen_at/agent_version/kernel/distro/archupdated on each ingestHost Agent — Resourceswidget renders fleet-glance table with live valuesDeviations from the plan
Documented in
docs/plugins/host-agent-plan.md"Execution note — path 1":db_sessionmakerundertesting=Trueand has no existing DB fixture. Rather than invent one mid-plan (scope creep), HTTP-level route tests were dropped and everything testable was factored into pure functions (config parser, collectors, ring buffer, metric expander, staleness filter, template render). Tasks 7, 9, 11, 13 became manual-verification only — all smoke-tested above.roundtable.core.db.get_sessiondoes not exist. Plan assumed a session helper that isn't in the codebase. Real pattern isasync with current_app.db_sessionmaker() as session:— used throughoutroutes.pyandscheduler.py.from roundtable.auth.middleware import require_rolewith@require_role(UserRole.admin)(matchesroundtable/settings/routes.pyconvention).make_stale_taskrenamed tomake_taskreturning a realScheduledTaskinstead of a bare dict (matchesplugins/docker/scheduler.pyconvention).agent.pyis 370 lines vs. the plan's ~350 target — 20 lines over because the appended code matches the plan verbatim. Not reworked.Known caveats
401 invalid_token, the agent re-buffers the current sample but silently drops whatever was already in the ring buffer from prior failed POSTs. Behavior matches the approved plan text (Task 5, Step 3) but is asymmetric with the generic-failure path. Fine for now; worth revisiting if you want stricter at-least-once semantics.Host/Agent version, rotate/delete buttons need aconfirm()guard, widget header wrap is awkward.🤖 Generated with Claude Code