c390addadb
- template machine-metrics (loadavg/nproc, /proc/meminfo, df -B1) non destructif - parseMetrics (TDD) → cpu load/cores, mémoire kB→B + %, filesystems, warnings >=90% - collectMetrics (SSH léger) persiste machine_metrics_latest ; getLatestMetrics (sans SSH) - routes GET /machines/:id/metrics + POST /metrics/collect ; api latestMetrics/collectMetrics - section Hardware : bloc métriques live (CPU/RAM/disques + alertes) + bouton Collecter → comble le gap « Health » de la tâche 3 tsc 0 · 108 tests · build OK. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
92 lines
2.8 KiB
TypeScript
92 lines
2.8 KiB
TypeScript
// server/routes/machines.ts
|
|
import { Hono } from "hono";
|
|
import {
|
|
listMachines, createMachine, deleteMachine, updateMachine, getMachineRow, getCreds, testConnection,
|
|
getMachineHardware,
|
|
type CreateMachineInput, type UpdateMachineInput,
|
|
} from "../services/machines.js";
|
|
import { refreshMachine, getLatestSnapshot } from "../services/refresh.js";
|
|
import { runProbe } from "../services/machineProbe.js";
|
|
import { collectMetrics, getLatestMetrics } from "../services/machineMetrics.js";
|
|
|
|
export const machinesRoutes = new Hono();
|
|
|
|
machinesRoutes.get("/", (c) => c.json(listMachines()));
|
|
|
|
machinesRoutes.post("/", async (c) => {
|
|
const body = (await c.req.json()) as CreateMachineInput;
|
|
try {
|
|
const m = await createMachine(body);
|
|
return c.json(m, 201);
|
|
} catch (err) {
|
|
return c.json({ error: `Connexion échouée: ${(err as Error).message}` }, 400);
|
|
}
|
|
});
|
|
|
|
machinesRoutes.post("/:id/test-connection", async (c) => {
|
|
const m = getMachineRow(c.req.param("id"));
|
|
if (!m) return c.json({ error: "Machine introuvable" }, 404);
|
|
try {
|
|
return c.json(await testConnection(getCreds(m)));
|
|
} catch (err) {
|
|
return c.json({ error: (err as Error).message }, 400);
|
|
}
|
|
});
|
|
|
|
machinesRoutes.get("/:id/snapshot", (c) => {
|
|
const snap = getLatestSnapshot(c.req.param("id"));
|
|
return snap ? c.json(snap) : c.json({ error: "Aucun snapshot" }, 404);
|
|
});
|
|
|
|
machinesRoutes.post("/:id/refresh", async (c) => {
|
|
try {
|
|
return c.json(await refreshMachine(c.req.param("id")));
|
|
} catch (err) {
|
|
return c.json({ error: (err as Error).message }, 400);
|
|
}
|
|
});
|
|
|
|
machinesRoutes.patch("/:id", async (c) => {
|
|
const body = (await c.req.json()) as UpdateMachineInput;
|
|
try {
|
|
return c.json(updateMachine(c.req.param("id"), body));
|
|
} catch (err) {
|
|
return c.json({ error: (err as Error).message }, 400);
|
|
}
|
|
});
|
|
|
|
// Dernières métriques stockées (sans SSH).
|
|
machinesRoutes.get("/:id/metrics", (c) => c.json(getLatestMetrics(c.req.param("id"))));
|
|
|
|
// Collecte fraîche (SSH léger, non destructif).
|
|
machinesRoutes.post("/:id/metrics/collect", async (c) => {
|
|
try {
|
|
return c.json(await collectMetrics(c.req.param("id")));
|
|
} catch (err) {
|
|
return c.json({ error: (err as Error).message }, 400);
|
|
}
|
|
});
|
|
|
|
machinesRoutes.get("/:id/hardware", (c) => {
|
|
try {
|
|
return c.json(getMachineHardware(c.req.param("id")));
|
|
} catch (err) {
|
|
return c.json({ error: (err as Error).message }, 404);
|
|
}
|
|
});
|
|
|
|
// Sonde synchrone (lecture seule) : renvoie faits + proposition de correction.
|
|
machinesRoutes.post("/:id/probe", async (c) => {
|
|
try {
|
|
const o = await runProbe(c.req.param("id"));
|
|
return c.json({ probe: o.probe, proposal: o.proposal, changes: o.changes });
|
|
} catch (err) {
|
|
return c.json({ error: (err as Error).message }, 400);
|
|
}
|
|
});
|
|
|
|
machinesRoutes.delete("/:id", (c) => {
|
|
deleteMachine(c.req.param("id"));
|
|
return c.json({ ok: true });
|
|
});
|