Files
legion_kk/tests/unit/materialization-watcher.test.ts
self 7ddfd51139 feat: add Legion operator config
Create legion-config.jsonc beside local state and route its DNS TTL, recursive resolver, and ACME directory settings through runtime services.
2026-07-03 19:14:48 +02:00

140 lines
3.8 KiB
TypeScript

import assert from "node:assert/strict"
import test from "node:test"
import { watchMaterialization } from "../../src/main/ops/materialization-watcher"
import type {
ResourceReconcileOutcome,
ResourceSupervisor
} from "../../src/main/resources/base/supervisor"
import type {
ResourceActorSnapshot,
ResourceActorType
} from "../../src/main/resources/base/snapshots"
import { defaultLegionOperatorConfig } from "../../src/main/operator-config"
import type { StoredState } from "../../src/shared/app"
const testOperatorConfig = defaultLegionOperatorConfig()
function createState(): StoredState {
return {
scheme: {
servers: [{ id: "node-a", provider: "hetzner", flavor: "cluster" }],
domains: [],
dnsZones: [{ id: "zone-1", zoneName: "example.test", provider: "ovh", records: [] }],
dnsHosts: []
},
trackedServers: [],
clusterMembership: []
} as unknown as StoredState
}
function resourceSnapshot(input: {
actorType: ResourceActorType
kind: ResourceActorSnapshot["kind"]
id: string
healthy: boolean
}): ResourceActorSnapshot {
return {
key: `${input.actorType}:${input.id}`,
actorType: input.actorType,
kind: input.kind,
id: input.id,
label: input.id,
state: input.healthy ? "healthy" : "absent",
health: input.healthy ? "healthy" : "planned",
desired: { present: true },
runtime: { present: input.healthy },
actual: { present: input.healthy }
}
}
test("watchMaterialization converges servers before touching DNS zones", async () => {
const calls: Array<ResourceActorType[] | undefined> = []
const deferred: ResourceActorType[][] = []
let serverHealthy = false
let dnsZoneHealthy = false
const supervisor = {
syncFromState() {
return undefined
},
async withReactiveEntityReconciliationDeferred(
types: ResourceActorType[],
callback: () => Promise<void>
) {
deferred.push(types)
await callback()
},
async reconcileAll(
_runContext: unknown,
actorTypes?: ResourceActorType[]
): Promise<ResourceReconcileOutcome[]> {
calls.push(actorTypes)
if (!actorTypes || actorTypes.includes("node")) {
serverHealthy = true
}
if (!actorTypes || actorTypes.includes("dns-zone")) {
dnsZoneHealthy = true
}
return [
...(actorTypes?.includes("node") || !actorTypes
? [
{
type: "node" as const,
id: "node-a",
label: "node-a",
status: "healthy" as const
}
]
: []),
...(actorTypes?.includes("dns-zone") || !actorTypes
? [
{
type: "dns-zone" as const,
id: "zone-1",
label: "zone-1",
status: "healthy" as const
}
]
: [])
]
},
getSnapshot() {
return {
servers: [
resourceSnapshot({
actorType: "node",
kind: "server",
id: "node-a",
healthy: serverHealthy
})
],
domains: [],
dnsZones: [
resourceSnapshot({
actorType: "dns-zone",
kind: "dns-zone",
id: "zone-1",
healthy: dnsZoneHealthy
})
],
firewalls: []
}
}
} as unknown as ResourceSupervisor
const result = await watchMaterialization({
previousState: createState(),
getState: createState,
resourceSupervisor: supervisor,
logger: {} as never,
appendLog: async () => undefined,
dnsRecordTtlSeconds: testOperatorConfig.dns.recordTtlSeconds
})
assert.deepEqual(deferred, [["dns-zone"]])
assert.deepEqual(calls, [["node", "firewall"], undefined])
assert.deepEqual(result.failures, [])
})