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 = (project: string, region: string, routerName: string) =>
17 compute.getRouters({ project, region, router: routerName }).pipe(
18 Effect.as("found" as const),
19 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
20 Effect.repeat({
21 schedule: Schedule.spaced("1 second"),
22 until: (status) => status === "gone",
23 times: 20,
24 }),
25 );
26
27test.provider(
28 "create, update, replace, and delete a router",
29 (stack) =>
30 Effect.gen(function* () {
31 yield* stack.destroy();
32
33 const created = yield* stack.deploy(
34 Effect.gen(function* () {
35 return yield* GCP.Compute.Router("Edge", {
36 network: "default",
37 region: "us-central1",
38 description: "test router",
39 bgp: { asn: 65001, advertiseMode: "DEFAULT" },
40 });
41 }),
42 );
43
44 expect(created.routerName).toEqual(expect.any(String));
45 expect(created.region).toEqual("us-central1");
46 expect(created.description).toEqual("test router");
47 expect(created.encryptedInterconnectRouter).toEqual(false);
48 expect(created.bgp?.asn).toEqual(65001);
49 expect(created.bgp?.advertiseMode).toEqual("DEFAULT");
50 expect(created.network).toEqual(
51 expect.stringContaining("networks/default"),
52 );
53
54 const fetched = yield* compute.getRouters({
55 project: created.project,
56 region: created.region,
57 router: created.routerName,
58 });
59 expect(fetched.name).toEqual(created.routerName);
60 expect(fetched.description).toContain("alchemy-id=");
61 expect(fetched.description).toContain("test router");
62 expect(fetched.bgp?.asn).toEqual(65001);
63 expect(fetched.bgp?.advertiseMode).toEqual("DEFAULT");
64
65 const updated = yield* stack.deploy(
66 Effect.gen(function* () {
67 return yield* GCP.Compute.Router("Edge", {
68 routerName: created.routerName,
69 network: "default",
70 region: "us-central1",
71 description: "updated router",
72 bgp: {
73 asn: 65001,
74 advertiseMode: "CUSTOM",
75 advertisedGroups: ["ALL_SUBNETS"],
76 advertisedIpRanges: [
77 { range: "10.0.0.0/8", description: "rfc1918" },
78 ],
79 keepaliveInterval: 30,
80 },
81 });
82 }),
83 );
84
85 expect(updated.routerName).toEqual(created.routerName);
86 expect(updated.routerId).toEqual(created.routerId);
87 expect(updated.description).toEqual("updated router");
88 expect(updated.bgp?.advertiseMode).toEqual("CUSTOM");
89 expect(updated.bgp?.advertisedGroups).toEqual(["ALL_SUBNETS"]);
90 expect(updated.bgp?.keepaliveInterval).toEqual(30);
91 expect(updated.bgp?.advertisedIpRanges).toEqual([
92 { range: "10.0.0.0/8", description: "rfc1918" },
93 ]);
94
95 const fetchedUpdate = yield* compute.getRouters({
96 project: updated.project,
97 region: updated.region,
98 router: updated.routerName,
99 });
100 expect(fetchedUpdate.description).toContain("updated router");
101 expect(fetchedUpdate.bgp?.advertiseMode).toEqual("CUSTOM");
102 expect(fetchedUpdate.bgp?.advertisedGroups).toEqual(["ALL_SUBNETS"]);
103 expect(fetchedUpdate.bgp?.keepaliveInterval).toEqual(30);
104
105 const replaced = yield* stack.deploy(
106 Effect.gen(function* () {
107 return yield* GCP.Compute.Router("Edge", {
108 routerName: created.routerName,
109 network: "default",
110 region: "us-central1",
111 description: "updated router",
112 encryptedInterconnectRouter: true,
113 bgp: {
114 asn: 65001,
115 advertiseMode: "CUSTOM",
116 advertisedGroups: ["ALL_SUBNETS"],
117 advertisedIpRanges: [
118 { range: "10.0.0.0/8", description: "rfc1918" },
119 ],
120 keepaliveInterval: 30,
121 },
122 });
123 }),
124 );
125
126 expect(replaced.routerName).toEqual(created.routerName);
127 expect(replaced.encryptedInterconnectRouter).toEqual(true);
128 expect(replaced.routerId).not.toEqual(created.routerId);
129
130 const fetchedReplace = yield* compute.getRouters({
131 project: replaced.project,
132 region: replaced.region,
133 router: replaced.routerName,
134 });
135 expect(fetchedReplace.encryptedInterconnectRouter).toEqual(true);
136
137 yield* stack.destroy();
138
139 const gone = yield* waitUntilGone(
140 created.project,
141 created.region,
142 created.routerName,
143 );
144 expect(gone).toEqual("gone");
145 }).pipe(logLevel),
146 { tags: ["provider:gcp", "provider:gcp:compute", "live"], timeout: 180_000 },
147);