Files
kuber/tests/server/operation-store.test.ts
T
2026-09-03 11:28:30 +07:00

182 lines
6.0 KiB
TypeScript

import { describe, expect, test } from "bun:test";
import {
MemoryOperationStore,
MemoryWorkspaceLeaseProvider,
OperationConflictError,
OperationValidationError,
recoverStaleOperations,
sanitizeOperationResult,
} from "../../server/operation-store";
describe("operation store", () => {
test("deduplicates matching requests and rejects key reuse", async () => {
let uid = 0;
const store = new MemoryOperationStore(undefined, () => `uid-${++uid}`);
const input = {
workspaceId: "demo",
action: "deploy",
idempotencyKey: "request-1",
request: { revision: 2 },
};
const first = await store.create(input);
expect(first.spec).not.toHaveProperty("request");
expect((await store.create(input)).metadata.uid).toBe(first.metadata.uid);
expect(
(await store.create({ ...input, request: { revision: 2 } })).metadata.uid,
).toBe(first.metadata.uid);
expect(
store.create({ ...input, request: { revision: 3 } }),
).rejects.toBeInstanceOf(OperationConflictError);
});
test("hashes object requests canonically and redacts persisted results", async () => {
const store = new MemoryOperationStore();
const operation = await store.create({
workspaceId: "demo",
action: "resources.apply",
idempotencyKey: "canonical",
request: { z: 1, nested: { b: 2, a: 1 } },
});
expect(
(
await store.create({
workspaceId: "demo",
action: "resources.apply",
idempotencyKey: "canonical",
request: { nested: { a: 1, b: 2 }, z: 1 },
})
).metadata.name,
).toBe(operation.metadata.name);
await store.transition(operation.metadata.name, "running");
const completed = await store.transition(
operation.metadata.name,
"succeeded",
{
result: {
kind: "Secret",
data: { password: "encoded" },
metadata: { name: "credentials" },
},
},
);
expect(completed.status.result).toEqual({
kind: "Secret",
data: "[REDACTED]",
metadata: { name: "credentials" },
});
expect(
sanitizeOperationResult({ DATABASE_URL: "postgres://secret" }),
).toEqual({ DATABASE_URL: "[REDACTED]" });
});
test("redacts credential-bearing values while preserving ordinary ones", () => {
expect(
sanitizeOperationResult({
endpoint: "https://alice:[email protected]:5432/mydb",
awsKey: "AKIAIOSFODNN7EXAMPLE",
keyMaterial: "-----BEGIN OPENSSH PRIVATE KEY-----",
registry: "https://registry.example.com/v2/app",
note: "used [email protected] for the AKIA lookup",
uid: "abc-123-def",
}),
).toEqual({
endpoint: "https://[REDACTED]@db.example.com:5432/mydb",
awsKey: "[REDACTED]",
keyMaterial: "[REDACTED]",
registry: "https://registry.example.com/v2/app",
note: "used [email protected] for the AKIA lookup",
uid: "abc-123-def",
});
expect(
sanitizeOperationResult([
"checkout https://[email protected]/org/repo.git",
"AKIAIOSFODNN7EXAMPLE",
]),
).toEqual([
"checkout https://[email protected]/org/repo.git",
"[REDACTED]",
]);
});
test("enforces the operation state machine", async () => {
const store = new MemoryOperationStore();
const operation = await store.create({
workspaceId: "demo",
action: "deploy",
idempotencyKey: "request-2",
});
const running = await store.transition(operation.metadata.name, "running");
expect(running.status.startedAt).toBeDefined();
const succeeded = await store.transition(
operation.metadata.name,
"succeeded",
{ result: { ready: true } },
);
expect(succeeded.metadata.resourceVersion).toBe("3");
expect(
store.transition(operation.metadata.name, "failed", {
error: { code: "late", message: "late" },
}),
).rejects.toBeInstanceOf(OperationConflictError);
const failed = await store.create({
workspaceId: "demo",
action: "delete",
idempotencyKey: "request-3",
});
expect(
store.transition(failed.metadata.name, "failed"),
).rejects.toBeInstanceOf(OperationValidationError);
});
test("provides exclusive, renewable per-workspace leases", async () => {
let now = 0;
const leases = new MemoryWorkspaceLeaseProvider(() => now);
const first = await leases.acquire("demo", "worker-a", 100);
expect(first).toBeDefined();
expect(await leases.acquire("demo", "worker-b", 100)).toBeUndefined();
expect(await first!.renew()).toBe(true);
await first!.release();
expect(await leases.acquire("demo", "worker-b", 100)).toBeDefined();
now = 101;
});
test("startup recovery fails stale pending and running operations", async () => {
const store = new MemoryOperationStore();
const pending = await store.create({
workspaceId: "demo",
action: "deploy",
idempotencyKey: "recover-1",
});
const running = await store.create({
workspaceId: "demo",
action: "stop",
idempotencyKey: "recover-2",
});
await store.transition(running.metadata.name, "running");
const done = await store.create({
workspaceId: "demo",
action: "restart",
idempotencyKey: "recover-3",
});
await store.transition(done.metadata.name, "running");
await store.transition(done.metadata.name, "succeeded", {
result: { ok: true },
});
const recovered = await recoverStaleOperations(store);
expect(recovered).toBe(2);
const after = await store.list();
const byId = new Map(after.map((o) => [o.metadata.name, o]));
expect(byId.get(pending.metadata.name)?.status.state).toBe("failed");
expect(byId.get(running.metadata.name)?.status.state).toBe("failed");
expect(byId.get(pending.metadata.name)?.status.error?.code).toBe(
"OPERATION_INTERRUPTED",
);
expect(byId.get(done.metadata.name)?.status.state).toBe("succeeded");
expect(await recoverStaleOperations(store)).toBe(0);
});
});