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";
8
9const { test } = Test.make({ providers: GCP.providers() });
10
11const logLevel = Effect.provideService(
12 MinimumLogLevel,
13 process.env.DEBUG ? "Debug" : "Info",
14);
15
16const waitUntilGone = (
17 project: string,
18 region: string,
19 networkEndpointGroup: string,
20) =>
21 compute
22 .getRegionNetworkEndpointGroups({
23 project,
24 region,
25 networkEndpointGroup,
26 })
27 .pipe(
28 Effect.as("found" as const),
29 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
30 Effect.repeat({
31 schedule: Schedule.spaced("1 second"),
32 until: (status) => status === "gone",
33 times: 10,
34 }),
35 );
36
37test.provider(
38 "create, replace, and delete a regional network endpoint group",
39 (stack) =>
40 Effect.gen(function* () {
41 yield* stack.destroy();
42
43 const created = yield* stack.deploy(
44 Effect.gen(function* () {
45 return yield* GCP.Compute.RegionNetworkEndpointGroup("Neg", {
46 region: "us-central1",
47 networkEndpointType: "SERVERLESS",
48 cloudRun: { urlMask: "<service>" },
49 description: "serverless neg",
50 });
51 }),
52 );
53
54 expect(created.networkEndpointGroupName).toEqual(expect.any(String));
55 expect(created.region).toEqual("us-central1");
56 expect(created.networkEndpointType).toEqual("SERVERLESS");
57 expect(created.description).toEqual("serverless neg");
58 expect(created.cloudRun?.urlMask).toEqual("<service>");
59
60 const fetched = yield* compute.getRegionNetworkEndpointGroups({
61 project: created.project,
62 region: created.region,
63 networkEndpointGroup: created.networkEndpointGroupName,
64 });
65 expect(fetched.name).toEqual(created.networkEndpointGroupName);
66 expect(fetched.networkEndpointType).toEqual("SERVERLESS");
67 expect(fetched.description).toContain("[alchemy ");
68 expect(fetched.description).toContain("serverless neg");
69 expect(fetched.cloudRun?.urlMask).toEqual("<service>");
70
71 const replaced = yield* stack.deploy(
72 Effect.gen(function* () {
73 return yield* GCP.Compute.RegionNetworkEndpointGroup("Neg", {
74 networkEndpointGroupName: created.networkEndpointGroupName,
75 region: "us-central1",
76 networkEndpointType: "SERVERLESS",
77 cloudRun: { urlMask: "<service>" },
78 description: "run backends",
79 });
80 }),
81 );
82
83 expect(replaced.networkEndpointGroupName).toEqual(
84 created.networkEndpointGroupName,
85 );
86 expect(replaced.networkEndpointType).toEqual("SERVERLESS");
87 expect(replaced.description).toEqual("run backends");
88 expect(replaced.cloudRun?.urlMask).toEqual("<service>");
89
90 const fetchedReplaced = yield* compute.getRegionNetworkEndpointGroups({
91 project: replaced.project,
92 region: replaced.region,
93 networkEndpointGroup: replaced.networkEndpointGroupName,
94 });
95 expect(fetchedReplaced.description).toContain("[alchemy ");
96 expect(fetchedReplaced.description).toContain("run backends");
97 expect(fetchedReplaced.cloudRun?.urlMask).toEqual("<service>");
98
99 yield* stack.destroy();
100
101 const gone = yield* waitUntilGone(
102 created.project,
103 created.region,
104 created.networkEndpointGroupName,
105 );
106 expect(gone).toEqual("gone");
107 }).pipe(logLevel),
108 { tags: ["provider:gcp", "provider:gcp:compute", "live"], timeout: 90_000 },
109);