1import * as AWS from "@/AWS";
2import { FargateProfile } from "@/AWS/EKS";
3import * as Provider from "@/Provider";
4import * as Test from "@/Test/Alchemy";
5import * as eks from "@distilled.cloud/aws/eks";
6import { expect } from "alchemy-test";
7import * as Effect from "effect/Effect";
8
9const { test } = Test.make({ providers: AWS.providers() });
10
11// Ungated typed-error probe: `describeFargateProfile` against a cluster that
12// does not exist must surface the `ResourceNotFoundException` tag that the
13// provider's read/reconcile/delete paths catch. Proves the distilled error
14// union without needing a ~10-minute EKS cluster.
15test.provider(
16 "describeFargateProfile on a nonexistent cluster fails with ResourceNotFoundException",
17 () =>
18 Effect.gen(function* () {
19 const error = yield* Effect.flip(
20 eks.describeFargateProfile({
21 clusterName: "alchemy-nonexistent-cluster-probe",
22 fargateProfileName: "alchemy-nonexistent-profile-probe",
23 }),
24 );
25 expect(error._tag).toBe("ResourceNotFoundException");
26 }),
27 { tags: ["provider:aws", "provider:aws:eks", "live"] },
28);
29
30// Ungated `list()` probe: enumerates every cluster, lists each cluster's Fargate
31// profiles, then hydrates each via `describeFargateProfile`. Returns `[]` in a
32// clean account/region, otherwise a well-formed array of full FargateProfile
33// Attributes. Proves the enumeration wiring compiles and runs live.
34test.provider(
35 "list returns a well-formed array of Fargate profiles",
36 (stack) =>
37 Effect.gen(function* () {
38 yield* stack.destroy();
39
40 const provider = yield* Provider.findProvider(FargateProfile);
41 const all = yield* provider.list();
42
43 expect(Array.isArray(all)).toBe(true);
44 for (const profile of all) {
45 expect(typeof profile.fargateProfileArn).toBe("string");
46 expect(typeof profile.fargateProfileName).toBe("string");
47 expect(typeof profile.clusterName).toBe("string");
48 expect(typeof profile.podExecutionRoleArn).toBe("string");
49 expect(Array.isArray(profile.subnets)).toBe(true);
50 expect(Array.isArray(profile.selectors)).toBe(true);
51 }
52 }),
53 { tags: ["provider:aws", "provider:aws:eks", "live"] },
54);
55
56// Full deploy lifecycle. Gate behind a pre-existing cluster supplied via
57// AWS_TEST_EKS_CLUSTER (+ the Fargate pod execution role ARN and PRIVATE subnet
58// IDs — Fargate pods reject public subnets). Deploys a Fargate profile, waits
59// for ACTIVE, then tears down and asserts it is gone.
60test.provider.skipIf(!process.env.AWS_TEST_EKS_CLUSTER)(
61 "creates and deletes a Fargate profile",
62 (stack) =>
63 Effect.gen(function* () {
64 yield* stack.destroy();
65
66 const clusterName = process.env.AWS_TEST_EKS_CLUSTER!;
67 const podExecutionRoleArn = process.env.AWS_TEST_EKS_FARGATE_ROLE_ARN!;
68 const subnets = (process.env.AWS_TEST_EKS_PRIVATE_SUBNETS ?? "")
69 .split(",")
70 .map((s) => s.trim())
71 .filter(Boolean);
72
73 const created = yield* stack.deploy(
74 Effect.gen(function* () {
75 return yield* FargateProfile("TestFargateProfile", {
76 clusterName,
77 podExecutionRoleArn,
78 subnets,
79 selectors: [{ namespace: "alchemy-fargate-test" }],
80 });
81 }),
82 );
83 expect(created.status).toBe("ACTIVE");
84 expect(created.selectors[0]?.namespace).toBe("alchemy-fargate-test");
85
86 yield* stack.destroy();
87
88 const gone = yield* eks
89 .describeFargateProfile({
90 clusterName,
91 fargateProfileName: created.fargateProfileName,
92 })
93 .pipe(
94 Effect.map(() => false),
95 Effect.catchTag("ResourceNotFoundException", () =>
96 Effect.succeed(true),
97 ),
98 );
99 expect(gone).toBe(true);
100 }),
101 { tags: ["provider:aws", "provider:aws:eks", "live"], timeout: 900_000 },
102);