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 waitUntilGone = (urlMapName: string) =>
18 GcpEnvironment.current.pipe(
19 Effect.flatMap(({ project }) =>
20 compute.getUrlMaps({ project, urlMap: urlMapName }).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 ),
30 );
31
32test.provider(
33 "create, update, and delete a url map",
34 (stack) =>
35 Effect.gen(function* () {
36 const { project } = yield* GcpEnvironment.current;
37 yield* stack.destroy();
38
39 const created = yield* stack.deploy(
40 Effect.gen(function* () {
41 return yield* GCP.Compute.UrlMap("Web", {
42 description: "https redirect",
43 defaultUrlRedirect: {
44 httpsRedirect: true,
45 hostRedirect: "example.com",
46 stripQuery: false,
47 },
48 });
49 }),
50 );
51
52 expect(created.urlMapName).toEqual(expect.any(String));
53 expect(created.description).toEqual("https redirect");
54 expect(created.defaultUrlRedirect?.httpsRedirect).toEqual(true);
55 expect(created.defaultUrlRedirect?.hostRedirect).toEqual("example.com");
56
57 const fetched = yield* compute.getUrlMaps({
58 project,
59 urlMap: created.urlMapName,
60 });
61 expect(fetched.name).toEqual(created.urlMapName);
62 expect(fetched.defaultUrlRedirect?.hostRedirect).toEqual("example.com");
63 expect(fetched.description).toContain("[alchemy ");
64 expect(fetched.description).toContain("https redirect");
65
66 const updated = yield* stack.deploy(
67 Effect.gen(function* () {
68 return yield* GCP.Compute.UrlMap("Web", {
69 urlMapName: created.urlMapName,
70 description: "host rules",
71 defaultUrlRedirect: {
72 httpsRedirect: true,
73 hostRedirect: "example.org",
74 stripQuery: true,
75 },
76 hostRules: [{ hosts: ["example.org"], pathMatcher: "all" }],
77 pathMatchers: [
78 {
79 name: "all",
80 defaultUrlRedirect: {
81 httpsRedirect: true,
82 hostRedirect: "www.example.org",
83 stripQuery: false,
84 },
85 },
86 ],
87 });
88 }),
89 );
90
91 expect(updated.urlMapName).toEqual(created.urlMapName);
92 expect(updated.description).toEqual("host rules");
93 expect(updated.defaultUrlRedirect?.hostRedirect).toEqual("example.org");
94 expect(updated.defaultUrlRedirect?.stripQuery).toEqual(true);
95 expect(updated.hostRules).toEqual(
96 expect.arrayContaining([
97 expect.objectContaining({
98 pathMatcher: "all",
99 hosts: expect.arrayContaining(["example.org"]),
100 }),
101 ]),
102 );
103 expect(updated.pathMatchers).toEqual(
104 expect.arrayContaining([
105 expect.objectContaining({
106 name: "all",
107 defaultUrlRedirect: expect.objectContaining({
108 hostRedirect: "www.example.org",
109 }),
110 }),
111 ]),
112 );
113
114 const refetched = yield* compute.getUrlMaps({
115 project,
116 urlMap: updated.urlMapName,
117 });
118 expect(refetched.defaultUrlRedirect?.hostRedirect).toEqual("example.org");
119 expect(refetched.hostRules?.[0]?.pathMatcher).toEqual("all");
120 expect(refetched.pathMatchers?.[0]?.name).toEqual("all");
121 expect(refetched.description).toContain("host rules");
122
123 yield* stack.destroy();
124
125 const gone = yield* waitUntilGone(created.urlMapName);
126 expect(gone).toEqual("gone");
127 }).pipe(logLevel),
128 { tags: ["provider:gcp", "provider:gcp:compute", "live"], timeout: 90_000 },
129);