1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import * as compute from "@distilled.cloud/gcp/compute_v1";
4import { expect } from "alchemy-test";
5import * as Effect from "effect/Effect";
6import { MinimumLogLevel } from "effect/References";
7import * as Schedule from "effect/Schedule";
8import { GcpEnvironment } from "@/GCP/Environment";
9
10const { test } = Test.make({ providers: GCP.providers() });
11
12const logLevel = Effect.provideService(
13 MinimumLogLevel,
14 process.env.DEBUG ? "Debug" : "Info",
15);
16
17const runLifecycle =
18 !!process.env.GCP_TEST_COMPUTE_INTERCONNECT && !process.env.FAST;
19
20const waitUntilGone = (interconnectAttachmentGroup: string) =>
21 GcpEnvironment.current.pipe(
22 Effect.flatMap(({ project }) =>
23 compute
24 .getInterconnectAttachmentGroups({
25 project,
26 interconnectAttachmentGroup,
27 })
28 .pipe(
29 Effect.as("found" as const),
30 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
31 Effect.repeat({
32 schedule: Schedule.spaced("1 second"),
33 until: (status) => status === "gone",
34 times: 10,
35 }),
36 ),
37 ),
38 );
39
40test.provider(
41 "getInterconnectAttachmentGroups on a missing group fails with NotFound",
42 (stack) =>
43 Effect.gen(function* () {
44 const { project } = yield* GcpEnvironment.current;
45 yield* stack.destroy();
46
47 const error = yield* Effect.flip(
48 compute.getInterconnectAttachmentGroups({
49 project,
50 interconnectAttachmentGroup: "alchemy-missing-iag",
51 }),
52 );
53 expect(error._tag).toBe("NotFound");
54
55 yield* stack.destroy();
56 }).pipe(logLevel),
57 { tags: ["provider:gcp", "provider:gcp:compute", "live"], timeout: 90_000 },
58);
59
60test.provider.skipIf(!runLifecycle)(
61 "create, update, and delete an interconnect attachment group",
62 (stack) =>
63 Effect.gen(function* () {
64 yield* stack.destroy();
65
66 const created = yield* stack.deploy(
67 Effect.gen(function* () {
68 return yield* GCP.Compute.InterconnectAttachmentGroup("Vlans", {
69 description: "dev vlan attachments",
70 intent: { availabilitySla: "NO_SLA" },
71 });
72 }),
73 );
74
75 expect(created.interconnectAttachmentGroupName).toEqual(
76 expect.any(String),
77 );
78 expect(created.description).toEqual("dev vlan attachments");
79
80 const fetched = yield* compute.getInterconnectAttachmentGroups({
81 project: created.project,
82 interconnectAttachmentGroup: created.interconnectAttachmentGroupName,
83 });
84 expect(fetched.name).toEqual(created.interconnectAttachmentGroupName);
85 expect(fetched.description).toContain("[alchemy ");
86
87 const updated = yield* stack.deploy(
88 Effect.gen(function* () {
89 return yield* GCP.Compute.InterconnectAttachmentGroup("Vlans", {
90 interconnectAttachmentGroupName:
91 created.interconnectAttachmentGroupName,
92 description: "updated vlan attachments",
93 intent: { availabilitySla: "NO_SLA" },
94 });
95 }),
96 );
97 expect(updated.description).toEqual("updated vlan attachments");
98
99 yield* stack.destroy();
100 const gone = yield* waitUntilGone(
101 created.interconnectAttachmentGroupName,
102 );
103 expect(gone).toEqual("gone");
104 }).pipe(logLevel),
105 { tags: ["provider:gcp", "provider:gcp:compute", "live"], timeout: 90_000 },
106);