1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import * as networkconnectivity from "@distilled.cloud/gcp/networkconnectivity_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 = (name: string) =>
18 networkconnectivity
19 .getProjectsLocationsGlobalPolicyBasedRoutes({ name })
20 .pipe(
21 Effect.as("found" as const),
22 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
23 Effect.repeat({
24 schedule: Schedule.spaced("1 second"),
25 until: (status) => status === "gone",
26 times: 10,
27 }),
28 );
29
30test.provider.skipIf(!!process.env.FAST)(
31 "create, replace, and delete a policy-based route",
32 (stack) =>
33 Effect.gen(function* () {
34 yield* stack.destroy();
35
36 const created = yield* stack.deploy(
37 Effect.gen(function* () {
38 const route = yield* GCP.NetworkConnectivity.PolicyBasedRoute(
39 "Skip",
40 {
41 network: DEFAULT_NETWORK,
42 filter: {
43 protocolVersion: "IPV4",
44 ipProtocol: "TCP",
45 srcRange: "10.0.0.0/8",
46 destRange: "192.0.2.0/24",
47 },
48 nextHopOtherRoutes: "DEFAULT_ROUTING",
49 virtualMachine: { tags: ["alchemy-pbr"] },
50 description: "pbr a",
51 labels: { env: "test" },
52 },
53 );
54 return { route };
55 }),
56 );
57
58 expect(created.route.name).toContain("/policyBasedRoutes/");
59 expect(created.route.name).toContain("/locations/global/");
60 expect(created.route.policyBasedRouteId).toEqual(expect.any(String));
61 expect(created.route.location).toEqual("global");
62 expect(created.route.network).toContain(`networks/${DEFAULT_NETWORK}`);
63 expect(created.route.filter.protocolVersion).toEqual("IPV4");
64 expect(created.route.filter.ipProtocol?.toUpperCase()).toEqual("TCP");
65 expect(created.route.filter.srcRange).toEqual("10.0.0.0/8");
66 expect(created.route.filter.destRange).toEqual("192.0.2.0/24");
67 expect(created.route.nextHopOtherRoutes).toEqual("DEFAULT_ROUTING");
68 expect(created.route.virtualMachine?.tags).toEqual(["alchemy-pbr"]);
69 expect(created.route.priority).toEqual(1000);
70 expect(created.route.description).toEqual("pbr a");
71 expect(created.route.labels).toMatchObject({ env: "test" });
72 expect(created.route.createTime).toEqual(expect.any(String));
73
74 const fetched =
75 yield* networkconnectivity.getProjectsLocationsGlobalPolicyBasedRoutes({
76 name: created.route.name,
77 });
78 expect(fetched.name).toEqual(created.route.name);
79 expect(fetched.filter?.destRange).toEqual("192.0.2.0/24");
80 expect(fetched.nextHopOtherRoutes).toEqual("DEFAULT_ROUTING");
81 expect(fetched.virtualMachine?.tags).toEqual(["alchemy-pbr"]);
82 expect(fetched.description).toEqual("pbr a");
83 expect(fetched.labels?.env).toEqual("test");
84 expect(
85 Object.keys(fetched.labels ?? {}).some((key) =>
86 key.startsWith("alchemy-"),
87 ),
88 ).toEqual(true);
89
90 const updated = yield* stack.deploy(
91 Effect.gen(function* () {
92 const route = yield* GCP.NetworkConnectivity.PolicyBasedRoute(
93 "Skip",
94 {
95 policyBasedRouteId: created.route.policyBasedRouteId,
96 network: DEFAULT_NETWORK,
97 filter: {
98 protocolVersion: "IPV4",
99 ipProtocol: "TCP",
100 srcRange: "10.0.0.0/8",
101 destRange: "198.51.100.0/24",
102 },
103 nextHopOtherRoutes: "DEFAULT_ROUTING",
104 virtualMachine: { tags: ["alchemy-pbr"] },
105 priority: 900,
106 description: "pbr b",
107 labels: { env: "prod", role: "pbr" },
108 },
109 );
110 return { route };
111 }),
112 );
113
114 expect(updated.route.policyBasedRouteId).toEqual(
115 created.route.policyBasedRouteId,
116 );
117 expect(updated.route.filter.destRange).toEqual("198.51.100.0/24");
118 expect(updated.route.priority).toEqual(900);
119 expect(updated.route.description).toEqual("pbr b");
120 expect(updated.route.labels).toMatchObject({ env: "prod", role: "pbr" });
121
122 const refetched =
123 yield* networkconnectivity.getProjectsLocationsGlobalPolicyBasedRoutes({
124 name: updated.route.name,
125 });
126 expect(refetched.filter?.destRange).toEqual("198.51.100.0/24");
127 expect(refetched.priority).toEqual(900);
128 expect(refetched.description).toEqual("pbr b");
129 expect(refetched.labels?.env).toEqual("prod");
130 expect(refetched.labels?.role).toEqual("pbr");
131
132 yield* stack.destroy();
133
134 const gone = yield* waitUntilGone(created.route.name);
135 expect(gone).toEqual("gone");
136 }).pipe(logLevel),
137 {
138 tags: ["provider:gcp", "provider:gcp:networkconnectivity", "live"],
139 timeout: 600_000,
140 },
141);