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, httpsHealthCheck: string) =>
17 compute.getHttpsHealthChecks({ project, httpsHealthCheck }).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: 10,
24 }),
25 );
26
27test.provider(
28 "create, update, replace, and delete an HTTPS health check",
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.HttpsHealthCheck("Api", {
36 description: "frontend probe",
37 port: 443,
38 requestPath: "/health",
39 });
40 }),
41 );
42
43 expect(created.httpsHealthCheckName).toEqual(expect.any(String));
44 expect(created.description).toEqual("frontend probe");
45 expect(created.port).toEqual(443);
46 expect(created.requestPath).toEqual("/health");
47 expect(created.checkIntervalSec).toEqual(5);
48 expect(created.healthyThreshold).toEqual(2);
49
50 const fetched = yield* compute.getHttpsHealthChecks({
51 project: created.project,
52 httpsHealthCheck: created.httpsHealthCheckName,
53 });
54 expect(fetched.name).toEqual(created.httpsHealthCheckName);
55 expect(fetched.port).toEqual(443);
56 expect(fetched.requestPath).toEqual("/health");
57 expect(fetched.description).toContain("[alchemy ");
58 expect(fetched.description).toContain("frontend probe");
59
60 const updated = yield* stack.deploy(
61 Effect.gen(function* () {
62 return yield* GCP.Compute.HttpsHealthCheck("Api", {
63 httpsHealthCheckName: created.httpsHealthCheckName,
64 description: "ready probe",
65 checkIntervalSec: 10,
66 timeoutSec: 5,
67 healthyThreshold: 3,
68 port: 8443,
69 requestPath: "/ready",
70 host: "ready.example",
71 });
72 }),
73 );
74
75 expect(updated.httpsHealthCheckName).toEqual(
76 created.httpsHealthCheckName,
77 );
78 expect(updated.description).toEqual("ready probe");
79 expect(updated.checkIntervalSec).toEqual(10);
80 expect(updated.healthyThreshold).toEqual(3);
81 expect(updated.port).toEqual(8443);
82 expect(updated.requestPath).toEqual("/ready");
83 expect(updated.host).toEqual("ready.example");
84
85 const refetched = yield* compute.getHttpsHealthChecks({
86 project: updated.project,
87 httpsHealthCheck: updated.httpsHealthCheckName,
88 });
89 expect(refetched.requestPath).toEqual("/ready");
90 expect(refetched.checkIntervalSec).toEqual(10);
91 expect(refetched.port).toEqual(8443);
92 expect(refetched.host).toEqual("ready.example");
93
94 const nextName = `r${created.httpsHealthCheckName}`
95 .slice(0, 63)
96 .replace(/-+$/, "x");
97 const replaced = yield* stack.deploy(
98 Effect.gen(function* () {
99 return yield* GCP.Compute.HttpsHealthCheck("Api", {
100 httpsHealthCheckName: nextName,
101 description: "replaced probe",
102 requestPath: "/live",
103 });
104 }),
105 );
106
107 expect(replaced.httpsHealthCheckName).toEqual(nextName);
108 expect(replaced.description).toEqual("replaced probe");
109 expect(replaced.requestPath).toEqual("/live");
110 expect(replaced.port).toEqual(443);
111
112 const afterReplace = yield* compute.getHttpsHealthChecks({
113 project: replaced.project,
114 httpsHealthCheck: replaced.httpsHealthCheckName,
115 });
116 expect(afterReplace.name).toEqual(nextName);
117 expect(afterReplace.requestPath).toEqual("/live");
118
119 const oldGone = yield* waitUntilGone(
120 created.project,
121 created.httpsHealthCheckName,
122 );
123 expect(oldGone).toEqual("gone");
124
125 yield* stack.destroy();
126
127 const gone = yield* waitUntilGone(
128 replaced.project,
129 replaced.httpsHealthCheckName,
130 );
131 expect(gone).toEqual("gone");
132 }).pipe(logLevel),
133 { tags: ["provider:gcp", "provider:gcp:compute", "live"], timeout: 90_000 },
134);