test: cover runner token lifecycle
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import { assert, assertEquals, assertRejects } from "jsr:@std/assert@^1.0.0";
|
import { assert, assertEquals, assertRejects } from "jsr:@std/assert@^1.0.0";
|
||||||
|
|
||||||
|
import { RunnerAdmin } from "../../../uptime.link/ts_api/classes/runner-admin.ts";
|
||||||
import { RunnerCoordinator } from "../../../uptime.link/ts_api/classes/runner-coordinator.ts";
|
import { RunnerCoordinator } from "../../../uptime.link/ts_api/classes/runner-coordinator.ts";
|
||||||
import { RunnerFileStore } from "../../../uptime.link/ts_api/classes/runner-file-store.ts";
|
import { RunnerFileStore } from "../../../uptime.link/ts_api/classes/runner-file-store.ts";
|
||||||
import {
|
import {
|
||||||
@@ -64,9 +65,15 @@ const main = async () => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const coordinator = new RunnerCoordinator({
|
const coordinator = new RunnerCoordinator();
|
||||||
runners: [{ runnerId, token: runnerToken, labels: ["scenario:basic"] }],
|
const admin = new RunnerAdmin(coordinator);
|
||||||
|
const registration = admin.registerRunner({
|
||||||
|
runnerId,
|
||||||
|
token: runnerToken,
|
||||||
|
labels: ["scenario:basic"],
|
||||||
});
|
});
|
||||||
|
assertEquals(registration.runner.runnerId, runnerId);
|
||||||
|
assertEquals(registration.token, runnerToken);
|
||||||
const scheduler = new RunnerScheduler(coordinator, { now: () => 1000 });
|
const scheduler = new RunnerScheduler(coordinator, { now: () => 1000 });
|
||||||
const scheduleResult = scheduler.scheduleDueChecks(
|
const scheduleResult = scheduler.scheduleDueChecks(
|
||||||
createRunnerSchedulesFromMonitors(monitors),
|
createRunnerSchedulesFromMonitors(monitors),
|
||||||
@@ -132,6 +139,12 @@ const main = async () => {
|
|||||||
pollIntervalMs: 1000,
|
pollIntervalMs: 1000,
|
||||||
});
|
});
|
||||||
await assertRejects(() => unauthorizedRunner.runOnce(), Error, "401");
|
await assertRejects(() => unauthorizedRunner.runOnce(), Error, "401");
|
||||||
|
await assertRunnerTokenLifecycle(
|
||||||
|
admin,
|
||||||
|
coordinator,
|
||||||
|
coordinatorServer.url,
|
||||||
|
runner,
|
||||||
|
);
|
||||||
|
|
||||||
console.log(`[${scenarioName}] Passed`);
|
console.log(`[${scenarioName}] Passed`);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -212,26 +225,54 @@ function assertMonitorStatusDerivation(
|
|||||||
assertEquals(ingestor.getMonitorState("manual-degraded")?.status, "degraded");
|
assertEquals(ingestor.getMonitorState("manual-degraded")?.status, "degraded");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function assertRunnerTokenLifecycle(
|
||||||
|
adminArg: RunnerAdmin,
|
||||||
|
coordinatorArg: RunnerCoordinator,
|
||||||
|
instanceUrlArg: string,
|
||||||
|
staleRunnerArg: UptimeRunner,
|
||||||
|
): Promise<void> {
|
||||||
|
const rotated = adminArg.rotateRunnerToken(runnerId, "rotated-token");
|
||||||
|
assertEquals(rotated.token, "rotated-token");
|
||||||
|
assertEquals(adminArg.listRunners()[0].tokenPreview, "rotate...oken");
|
||||||
|
|
||||||
|
coordinatorArg.enqueueCheck({
|
||||||
|
id: "post-rotate-assumption",
|
||||||
|
type: "assumption",
|
||||||
|
assumedStatus: "ok",
|
||||||
|
metadata: {
|
||||||
|
monitorId: "post-rotate",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await assertRejects(() => staleRunnerArg.runOnce(), Error, "401");
|
||||||
|
|
||||||
|
const rotatedRunner = new UptimeRunner({
|
||||||
|
instanceUrl: instanceUrlArg,
|
||||||
|
runnerId,
|
||||||
|
token: rotated.token,
|
||||||
|
});
|
||||||
|
const rotatedResult = await rotatedRunner.runOnce();
|
||||||
|
assertEquals(rotatedResult.results.length, 1);
|
||||||
|
assertEquals(rotatedResult.results[0].status, "ok");
|
||||||
|
|
||||||
|
adminArg.disableRunner(runnerId);
|
||||||
|
assertEquals(adminArg.listRunners()[0].enabled, false);
|
||||||
|
await assertRejects(() => rotatedRunner.runOnce(), Error, "401");
|
||||||
|
|
||||||
|
adminArg.enableRunner(runnerId);
|
||||||
|
adminArg.setRunnerLabels(runnerId, ["scenario:basic", "role:external"]);
|
||||||
|
assertEquals(
|
||||||
|
adminArg.listRunners()[0].labels.includes("role:external"),
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async function assertSnapshotPersistence(
|
async function assertSnapshotPersistence(
|
||||||
coordinatorArg: RunnerCoordinator,
|
coordinatorArg: RunnerCoordinator,
|
||||||
targetUrlArg: string,
|
targetUrlArg: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const snapshotPath = await Deno.makeTempFile();
|
const snapshotPath = await Deno.makeTempFile();
|
||||||
const store = new RunnerFileStore({
|
const store = RunnerFileStore.fromDenoPath(snapshotPath);
|
||||||
readTextFile: async () => {
|
|
||||||
try {
|
|
||||||
return await Deno.readTextFile(snapshotPath);
|
|
||||||
} catch (error) {
|
|
||||||
if (error instanceof Deno.errors.NotFound) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
writeTextFile: async (contentArg) => {
|
|
||||||
await Deno.writeTextFile(snapshotPath, contentArg);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await store.save(coordinatorArg.getSnapshot());
|
await store.save(coordinatorArg.getSnapshot());
|
||||||
|
|||||||
Reference in New Issue
Block a user