Watch
0
0
Fork
You've already forked hyperhive
0

swarm UI: an alerts page, read by the controller with a Viewer Grafana token from bao

swarm-bao-grafana-controller-token, on the host that runs Grafana, logs in
to Grafana's API over its socket as the built-in admin (the password
swarm-bao-grafana-admin minted, #5138) and keeps a `swarm-controller`
service account that is an enabled Viewer. It mints a token for that
account and writes it to bao at
swarm/controller/swarm-controller/grafana/token under Grafana's leaf. A
ten-minute timer runs it again. The unit keeps a stored token Grafana
accepts. If Grafana refuses the stored token with 401, or bao holds
none, the unit deletes every token of the account and mints a new one.
Grafana's grant gains create/read/update on that leaf, and the
controller's gains read.

swarm-controller serves GET /api/alerts from Grafana's
/api/prometheus/grafana/api/v1/alerts. It reads the token from bao,
keeps it in memory, and re-reads bao once on a 401. The HTTP client has
5s connect and 15s request timeouts. Any failure is a 503 that names its
cause. swarm-ui gets an /alerts page listing them, built the same way as
the hives page.

This is option (c) on #5129, the operator's choice.
This commit is contained in:
atlas 2026-10-15 12:26:06 +02:00 • committed by mara
commit 7d09776742
23 changed files with 888 additions and 37 deletions

View file

@ -4,6 +4,7 @@ import { Route, Switch } from "wouter-preact";
import { Shell } from "./shell/Shell.js";
import { AgentsPage } from "./pages/agents/AgentsPage.js";
import { AgentTerminalPage } from "./pages/agents/AgentTerminalPage.js";
import { AlertsPage } from "./pages/AlertsPage.js";
import { ComponentsPage } from "./pages/ComponentsPage.js";
import { JobsPage } from "./pages/JobsPage.js";
import { HivesPage } from "./pages/HivesPage.js";
@ -27,6 +28,7 @@ export function App() {
<Switch>
<Route path="/" component={StartPage} />
<Route path="/hives" component={HivesPage} />
<Route path="/alerts" component={AlertsPage} />
<Route path="/agents" component={AgentsPage} />
<Route path="/agents/:name/terminal" component={AgentTerminalPage} />
<Route