import { describe, expect, it } from "vitest"; import { createMemoryDb, repos, runMigrations } from "@cfdm/db"; import { buildApp } from "../src/app.js"; import { loadConfig } from "../src/config.js"; import { failoverARecordDiff } from "../src/services/service-config-service.js"; async function authHeaders(app: Awaited>) { const config = loadConfig(); const res = await app.inject({ method: "POST", url: "/api/v1/auth/login", payload: { username: config.adminUsername, password: "admin" }, }); expect(res.statusCode).toBe(200); const { token } = res.json() as { token: string }; return { authorization: `Bearer ${token}` }; } describe("failoverARecordDiff", () => { it("diffs added and removed A contents", () => { expect( failoverARecordDiff( ["130.49.213.153", "93.115.203.183"], ["93.115.203.183"], ), ).toEqual({ added: [], removed: ["130.49.213.153"], }); expect(failoverARecordDiff(["10.0.0.1"], ["10.0.0.1", "10.0.0.2"])).toEqual({ added: ["10.0.0.2"], removed: [], }); }); }); describe("GET /services/:id/failover-log", () => { it("returns add/remove rows for the service", async () => { const app = await buildApp({ config: { ...loadConfig(), staticDir: null }, memory: true, }); const headers = await authHeaders(app); const domain = repos.createDomain(app.db, null, "rkns.top", "zone-1"); const service = repos.createService(app.db, "MSK Hip", "msk-hip"); const binding = repos.insertBinding(app.db, domain.id, service.id, "gt", null); repos.insertFailoverLog(app.db, { serviceId: service.id, bindingId: binding.id, fqdn: "gt.rkns.top", entries: [ { ip: "130.49.213.153", action: "removed" }, { ip: "93.115.203.183", action: "added" }, ], }); const res = await app.inject({ method: "GET", url: `/api/v1/services/${service.id}/failover-log`, headers, }); expect(res.statusCode).toBe(200); const body = res.json() as { items: Array<{ ip: string; fqdn: string; action: string }>; }; expect(body.items).toEqual( expect.arrayContaining([ expect.objectContaining({ ip: "130.49.213.153", fqdn: "gt.rkns.top", action: "removed", }), expect.objectContaining({ ip: "93.115.203.183", fqdn: "gt.rkns.top", action: "added", }), ]), ); await app.close(); }); }); describe("failover_log table", () => { it("lists newest first", () => { const { db, sqlite } = createMemoryDb(); runMigrations(sqlite); const domain = repos.createDomain(db, null, "example.com", "zone-1"); const service = repos.createService(db, "Panel", "panel"); const binding = repos.insertBinding(db, domain.id, service.id, "panel", null); repos.insertFailoverLog(db, { serviceId: service.id, bindingId: binding.id, fqdn: "panel.example.com", entries: [{ ip: "1.1.1.1", action: "removed" }], }); repos.insertFailoverLog(db, { serviceId: service.id, bindingId: binding.id, fqdn: "panel.example.com", entries: [{ ip: "1.1.1.1", action: "added" }], }); const rows = repos.listFailoverLogForService(db, service.id); expect(rows.map((row) => row.action)).toEqual(["added", "removed"]); }); });