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 { DEFAULT_NETWORK } from "../networkQuota.ts";
9
10const { test } = Test.make({ providers: GCP.providers() });
11
12const logLevel = Effect.provideService(
13 MinimumLogLevel,
14 process.env.DEBUG ? "Debug" : "Info",
15);
16
17const waitUntilGone = (
18 project: string,
19 region: string,
20 vpnGatewayName: string,
21) =>
22 compute.getVpnGateways({ project, region, vpnGateway: vpnGatewayName }).pipe(
23 Effect.as("found" as const),
24 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
25 Effect.repeat({
26 schedule: Schedule.spaced("1 second"),
27 until: (status) => status === "gone",
28 times: 10,
29 }),
30 );
31
32test.provider.skipIf(!!process.env.FAST)(
33 "create, update, and delete an HA VPN gateway",
34 (stack) =>
35 Effect.gen(function* () {
36 yield* stack.destroy();
37
38 const created = yield* stack.deploy(
39 Effect.gen(function* () {
40 const gateway = yield* GCP.Compute.VpnGateway("Gateway", {
41 region: "us-central1",
42 network: DEFAULT_NETWORK,
43 description: "ha vpn",
44 labels: { env: "test" },
45 });
46 return { gateway };
47 }),
48 );
49
50 expect(created.gateway.vpnGatewayName).toEqual(expect.any(String));
51 expect(created.gateway.region).toEqual("us-central1");
52 expect(created.gateway.network).toEqual(
53 expect.stringContaining(`/networks/${DEFAULT_NETWORK}`),
54 );
55 expect(created.gateway.description).toEqual("ha vpn");
56 expect(created.gateway.labels).toMatchObject({ env: "test" });
57 expect(created.gateway.vpnInterfaces.length).toBeGreaterThanOrEqual(2);
58 expect(created.gateway.vpnInterfaces[0]?.ipAddress).toEqual(
59 expect.any(String),
60 );
61
62 const fetched = yield* compute.getVpnGateways({
63 project: created.gateway.project,
64 region: created.gateway.region,
65 vpnGateway: created.gateway.vpnGatewayName,
66 });
67 expect(fetched.name).toEqual(created.gateway.vpnGatewayName);
68 expect(fetched.description).toEqual("ha vpn");
69 expect(fetched.labels?.env).toEqual("test");
70 expect(fetched.labels?.["alchemy-id"]).toEqual(expect.any(String));
71 expect(fetched.network).toEqual(
72 expect.stringContaining(`/networks/${DEFAULT_NETWORK}`),
73 );
74
75 const updated = yield* stack.deploy(
76 Effect.gen(function* () {
77 const gateway = yield* GCP.Compute.VpnGateway("Gateway", {
78 vpnGatewayName: created.gateway.vpnGatewayName,
79 region: "us-central1",
80 network: DEFAULT_NETWORK,
81 description: "ha vpn",
82 labels: { env: "prod", role: "vpn" },
83 });
84 return { gateway };
85 }),
86 );
87
88 expect(updated.gateway.vpnGatewayName).toEqual(
89 created.gateway.vpnGatewayName,
90 );
91 expect(updated.gateway.vpnGatewayId).toEqual(
92 created.gateway.vpnGatewayId,
93 );
94 expect(updated.gateway.labels).toMatchObject({
95 env: "prod",
96 role: "vpn",
97 });
98
99 const fetchedUpdated = yield* compute.getVpnGateways({
100 project: updated.gateway.project,
101 region: updated.gateway.region,
102 vpnGateway: updated.gateway.vpnGatewayName,
103 });
104 expect(fetchedUpdated.labels?.env).toEqual("prod");
105 expect(fetchedUpdated.labels?.role).toEqual("vpn");
106
107 yield* stack.destroy();
108
109 const gone = yield* waitUntilGone(
110 created.gateway.project,
111 created.gateway.region,
112 created.gateway.vpnGatewayName,
113 );
114 expect(gone).toEqual("gone");
115 }).pipe(logLevel),
116 { tags: ["provider:gcp", "provider:gcp:compute", "live"], timeout: 180_000 },
117);