Files
monlet/web/tests/mock-server.mjs

267 lines
6.8 KiB
JavaScript

import { createServer } from "node:http";
const PORT = Number(process.env.MOCK_PORT ?? 8765);
const now = new Date().toISOString();
const eventItems = [
{
event_id: "00000000-0000-7000-8000-000000000001",
agent_id: "agent-1",
check_id: "disk",
observed_at: now,
received_at: now,
status: "ok",
exit_code: 0,
duration_ms: 12,
output: "disk ok",
output_truncated: false,
notifications_enabled: true,
},
{
event_id: "00000000-0000-7000-8000-000000000002",
agent_id: "agent-1",
check_id: "load",
observed_at: now,
received_at: now,
status: "warning",
exit_code: 1,
duration_ms: 34,
output: "load high",
output_truncated: false,
notifications_enabled: true,
},
{
event_id: "00000000-0000-7000-8000-000000000003",
agent_id: "agent-2",
check_id: "agent_liveness",
observed_at: now,
received_at: now,
status: "critical",
exit_code: 2,
duration_ms: 0,
output: "agent is dead",
output_truncated: false,
notifications_enabled: true,
},
...Array.from({ length: 12 }, (_, i) => ({
event_id: `00000000-0000-7000-8000-0000000001${String(i).padStart(2, "0")}`,
agent_id: "agent-1",
check_id: "disk",
observed_at: now,
received_at: now,
status: "ok",
exit_code: 0,
duration_ms: 10 + i,
output: `disk extra ${i + 1}`,
output_truncated: false,
notifications_enabled: true,
})),
];
const fixtures = {
"/api/v1/health": { status: "ok" },
"/api/v1/system-summary": {
agents_online: 1,
agents_offline: 1,
checks_ok: 2,
checks_warning: 1,
checks_critical: 1,
checks_unknown: 0,
open_incidents: 2,
generated_at: now,
},
"/api/v1/agents": {
items: [
{
agent_id: "agent-1",
hostname: "host-1",
status: "alive",
admission_state: "accepted",
key_fingerprint: "1111111111111111",
last_seen_at: now,
features: { push: true, metrics: false },
labels: { env: "dev", monlet_agent_version: "0.1.0" },
},
{
agent_id: "agent-2",
hostname: "host-2",
status: "dead",
admission_state: "accepted",
key_fingerprint: "2222222222222222",
last_seen_at: now,
features: { push: true, metrics: false },
labels: {},
},
],
next_cursor: null,
},
"/api/v1/agents/agent-1": {
agent_id: "agent-1",
hostname: "host-1",
status: "alive",
admission_state: "accepted",
key_fingerprint: "1111111111111111",
last_seen_at: now,
features: { push: true, metrics: false },
labels: { env: "dev", monlet_agent_version: "0.1.0" },
},
"/api/v1/checks": {
items: [
{
agent_id: "agent-1",
check_id: "disk",
status: "ok",
exit_code: 0,
last_observed_at: now,
incident_key: "agent-1:disk",
summary: "disk ok",
},
{
agent_id: "agent-1",
check_id: "load",
status: "warning",
exit_code: 1,
last_observed_at: now,
incident_key: "agent-1:load",
summary: "load high",
},
{
agent_id: "agent-1",
check_id: "agent_liveness",
status: "ok",
exit_code: 0,
last_observed_at: now,
incident_key: "agent:agent-1:liveness",
summary: "agent is alive",
},
{
agent_id: "agent-2",
check_id: "agent_liveness",
status: "critical",
exit_code: 2,
last_observed_at: now,
incident_key: "agent:agent-2:liveness",
summary: "agent is dead",
},
],
next_cursor: null,
},
"/api/v1/incidents": {
items: [
{
id: "00000000-0000-0000-0000-000000000001",
incident_key: "agent-1:load",
state: "open",
severity: "warning",
agent_id: "agent-1",
check_id: "load",
opened_at: now,
summary: "load high",
},
{
id: "00000000-0000-0000-0000-000000000003",
incident_key: "agent:agent-2:liveness",
state: "open",
severity: "critical",
agent_id: "agent-2",
check_id: "agent_liveness",
opened_at: now,
summary: "agent is dead",
},
{
id: "00000000-0000-0000-0000-000000000004",
incident_key: "agent-2:disk",
state: "resolved",
severity: "critical",
agent_id: "agent-2",
check_id: "disk",
opened_at: now,
resolved_at: now,
summary: "disk recovered",
},
],
next_cursor: null,
},
"/api/v1/events/query": {
items: eventItems,
next_cursor: "10",
},
"/api/v1/notifiers/outbox": {
items: [
{
id: "00000000-0000-0000-0000-000000000002",
notifier: "debug",
state: "sent",
incident_id: "00000000-0000-0000-0000-000000000001",
event_type: "firing",
attempts: 1,
next_attempt_at: null,
last_error: null,
updated_at: now,
},
],
next_cursor: null,
},
};
const server = createServer((req, res) => {
const url = new URL(req.url ?? "/", `http://x`);
let body = fixtures[url.pathname];
if (url.pathname === "/api/v1/checks" && body) {
const agentId = url.searchParams.get("agent_id");
if (agentId) {
body = {
...body,
items: body.items.filter((item) => item.agent_id === agentId),
next_cursor: null,
};
}
}
if (url.pathname === "/api/v1/events/query" && body) {
const agentId = url.searchParams.get("agent_id");
const checkId = url.searchParams.get("check_id");
const items = body.items.filter((item) => {
if (agentId && item.agent_id !== agentId) return false;
if (checkId && item.check_id !== checkId) return false;
return true;
});
body = paginate(body, items, url);
}
if (url.pathname === "/api/v1/incidents" && body) {
const state = url.searchParams.get("state");
if (state) {
body = {
...body,
items: body.items.filter((item) => item.state === state),
next_cursor: null,
};
}
}
res.setHeader("Content-Type", "application/json");
if (!body) {
res.statusCode = 404;
res.end(
JSON.stringify({ error: { code: "not_found", message: "not in fixtures", request_id: "mock" } }),
);
return;
}
res.end(JSON.stringify(body));
});
server.listen(PORT, "127.0.0.1", () => {
console.log(`mock server on ${PORT}`);
});
function paginate(body, items, url) {
const limit = Number(url.searchParams.get("limit") ?? 100);
const start = Number(url.searchParams.get("cursor") ?? 0);
const safeLimit = Number.isFinite(limit) && limit > 0 ? limit : 100;
const safeStart = Number.isFinite(start) && start > 0 ? start : 0;
const next = safeStart + safeLimit;
return {
...body,
items: items.slice(safeStart, next),
next_cursor: next < items.length ? String(next) : null,
};
}