/** * `MockCloudExecutor` — an in-memory fake of `CloudExecutor` (../cloud-executor.ts) * for tests. No live AWS, no live docker: every method records its call and * returns/derives a canned result, with enough state (a fake stack registry, a * fake deployment registry, a fake cluster registry) to exercise realistic * scenarios — a changeset that proposes a replacement, a stack that takes a * few polls to go terminal, a CodeDeploy deployment that fails then rolls back, * a cluster that becomes healthy after enough members join. * * Every capability factory in `../*.ts` accepts a `CloudExecutor`, so a test * builds one `MockCloudExecutor` and passes it to every `create*Capability` * under test — never touching the real, `child_process`/`net`-backed * executor in `../cloud-executor.ts`. */ import type { CfnChange, CloudExecutor, EcsServiceState } from "../cloud-executor.js"; import type { Neo4jClusterClient } from "@intentius/chant/components/verbs/cloud-executor"; /** The mock's executor is a superset of the aws `CloudExecutor` plus the agnostic Neo4j client, so it satisfies both aws-leaf and core-agnostic capability factories in the e2e suites. */ type MockExecutor = CloudExecutor & { neo4j: Neo4jClusterClient; }; export interface RecordedCall { client: string; method: string; args: unknown; } /** Scripted behavior for one fake CloudFormation stack. */ export interface FakeStackConfig { /** Changes CloudFormation would propose for the next changeset created against this stack. Default: no changes (no-op update). */ changes?: CfnChange[]; /** Outputs the stack reports once terminal. */ outputs?: Record; /** Terminal status reported after `executeChangeSet` (or from the start, if the stack pre-exists). Default: "UPDATE_COMPLETE". */ terminalStatus?: string; /** True if this is a brand-new stack (no prior stack) — affects `isCreate`. Default: false. */ isCreate?: boolean; /** When true, the next changeset created against this (already-current) stack * reports a FAILED "no changes" status, as real CloudFormation does for an * update with an empty diff — cfn-deploy must treat it as an idempotent no-op * success (#960). */ noChanges?: boolean; } export interface FakeDeploymentConfig { /** Terminal status CodeDeploy reports for this deployment. Default: "Succeeded". */ terminalStatus?: "Succeeded" | "Failed" | "Stopped"; } export interface FakeClusterConfig { /** Number of bolt endpoints (out of however many `cluster` lists) that report healthy. Default: all of them. */ healthyCount?: number; } export interface FakeLambdaConfig { /** Alias -> version this function's alias currently resolves to, before any deploy in the test runs. */ aliasVersions?: Record; /** Force `waitForUpdate` to report a failed code update (simulates a bad image). */ failUpdate?: boolean; } /** Scripted behavior for one fake EMR job run. */ export interface FakeJobRunConfig { /** Terminal state reported once the run "completes". Default: "COMPLETED". */ terminalState?: "COMPLETED" | "FAILED" | "CANCELLED"; } export interface MockCloudExecutorOptions { stacks?: Record; deployments?: Record; clusters?: Record; /** ECS service states keyed by `cluster/service`, evolved by `updateService`/`rollbackService` calls. */ ecsServices?: Record; /** Force every docker/ecr call to fail (simulates a build/push failure). */ failDocker?: boolean; /** Force every `host` (registry-less `load-image-on-host`) call to fail (simulates an unreachable host). */ failHost?: boolean; /** Lambda functions keyed by function name. */ lambdas?: Record; /** Scripted job runs keyed by the run id the test expects (see `MockCloudExecutor.setJobRun` for post-construction control, e.g. before the run id is known). */ jobRuns?: Record; /** Object counts `s3.sync` reports (uploaded always; deleted only when the call passes `delete: true`). */ s3Sync?: { uploaded?: number; deleted?: number; }; /** Canned stdout `host.exec` returns (e.g. a byte count for `copy-to-host`, or command output for `remote-exec`). */ hostExecStdout?: string; /** Result `ecs.waitForTask` reports for a one-off `run-task` (e.g. a migration task). Default: clean exit (`STOPPED`, exit 0). */ ecsTask?: { lastStatus?: string; exitCode?: number; stoppedReason?: string; }; /** Result `lambda.invoke` returns. Default: `{ statusCode: 200, payload: "" }`. */ lambdaInvoke?: { statusCode?: number; payload?: string; functionError?: string; }; } /** An injected `CloudExecutor` plus the call log and stack-status controls tests use to script scenarios and assert on I/O. */ export interface MockCloudExecutor { executor: MockExecutor; calls: RecordedCall[]; /** Change a stack's terminal status/outputs/changes after construction (e.g. to simulate a later poll succeeding). */ setStack(name: string, config: FakeStackConfig): void; /** Change a deployment's terminal status after construction. */ setDeployment(id: string, config: FakeDeploymentConfig): void; /** Change how many cluster members report healthy after construction (simulates a follower catching up). */ setClusterHealth(cluster: string, healthyCount: number): void; /** Change a job run's terminal state after construction (e.g. once its runId is known from a prior `startJobRun` call). */ setJobRun(runId: string, config: FakeJobRunConfig): void; } /** Build a fresh mock `CloudExecutor`. Every method is deterministic and synchronous-fast — no real polling delay. */ export declare function createMockCloudExecutor(options?: MockCloudExecutorOptions): MockCloudExecutor; export {}; //# sourceMappingURL=mock-cloud-executor.d.ts.map