1import * as AWS from "@/AWS";
2import * as Test from "@/Test/Alchemy";
3import { expect } from "alchemy-test";
4import * as Effect from "effect/Effect";
5
6const { test } = Test.make({ providers: AWS.providers() });
7
8// `GetAmi.execute` (aliased `getAmi`) is the data-source form of the
9// capability: the lookup runs during plan/deploy resolution against the
10// stack's services (GetAmiHttp is registered by AWS.providers()), never
11// inside a deployed runtime. No cloud resources are created — the stack is
12// outputs-only — so this pins the whole invoke path cheaply: Binding.Service
13// execute → EffectExpr resolution → distilled describeImages.
14test.provider(
15 "getAmi resolves images as plan-time Outputs",
16 (stack) =>
17 Effect.gen(function* () {
18 const { image, imageId, fallbackId } = yield* stack.deploy(
19 Effect.gen(function* () {
20 return {
21 // The generic data source: the full image description.
22 image: AWS.EC2.getAmi({
23 owners: ["amazon"],
24 name: ["al2023-ami-2023.*"],
25 }),
26 // The id-only helper built on it.
27 imageId: AWS.EC2.amazonLinux2023(),
28 // The preference-chain helper (flatMap over the data source).
29 fallbackId: AWS.EC2.amazonLinux(),
30 };
31 }),
32 );
33
34 expect(image?.ImageId).toMatch(/^ami-/);
35 expect(image?.CreationDate).toBeTruthy();
36 expect(imageId).toMatch(/^ami-/);
37 // AL2023 exists, so the fallback chain resolves to the same image id.
38 expect(fallbackId).toBe(imageId);
39
40 yield* stack.destroy();
41 }),
42 { tags: ["provider:aws", "provider:aws:ec2", "live"], timeout: 120_000 },
43);