quality / commitlint (push) Skipped
quality / changes (push) Successful in 11s
quality / docker-check (push) Skipped
CD / update-wiki (push) Successful in 5s
quality / web (push) Successful in 1m11s
quality / api (push) Successful in 1m1s
CD / quality (push) Successful in 2m30s
CD / publish (push) Successful in 2m4s
Сервис up, если жив хотя бы один IP. Failover показывает Down по FQDN и журнал add/remove A-записей. Co-authored-by: Cursor <[email protected]>
113 lines
3.4 KiB
TypeScript
113 lines
3.4 KiB
TypeScript
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<ReturnType<typeof buildApp>>) {
|
|
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"]);
|
|
});
|
|
});
|