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 region = "us-central1";
17
18const waitUntilGone = (project: string, sslPolicyName: string) =>
19 compute
20 .getRegionSslPolicies({ project, region, sslPolicy: sslPolicyName })
21 .pipe(
22 Effect.as("found" as const),
23 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
24 Effect.repeat({
25 schedule: Schedule.spaced("1 second"),
26 until: (status) => status === "gone",
27 times: 10,
28 }),
29 );
30
31const CUSTOM_FEATURES = [
32 "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
33 "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
34];
35
36test.provider(
37 "create, update, and delete a regional ssl policy",
38 (stack) =>
39 Effect.gen(function* () {
40 yield* stack.destroy();
41
42 const created = yield* stack.deploy(
43 Effect.gen(function* () {
44 return yield* GCP.Compute.RegionSslPolicy("FrontendTls", {
45 region,
46 description: "frontend tls",
47 profile: "MODERN",
48 minTlsVersion: "TLS_1_2",
49 });
50 }),
51 );
52
53 expect(created.sslPolicyName).toEqual(expect.any(String));
54 expect(created.region).toEqual(region);
55 expect(created.profile).toEqual("MODERN");
56 expect(created.minTlsVersion).toEqual("TLS_1_2");
57 expect(created.description).toEqual("frontend tls");
58 expect(created.enabledFeatures.length).toBeGreaterThan(0);
59 expect(created.selfLink).toEqual(expect.any(String));
60
61 const fetched = yield* compute.getRegionSslPolicies({
62 project: created.project,
63 region,
64 sslPolicy: created.sslPolicyName,
65 });
66 expect(fetched.name).toEqual(created.sslPolicyName);
67 expect(fetched.profile).toEqual("MODERN");
68 expect(fetched.minTlsVersion).toEqual("TLS_1_2");
69 expect(fetched.description).toContain("[alchemy ");
70 expect(fetched.description).toContain("frontend tls");
71
72 const listed = yield* compute.listRegionSslPolicies({
73 project: created.project,
74 region,
75 maxResults: 500,
76 });
77 expect(
78 (listed.items ?? []).some(
79 (policy) => policy.name === created.sslPolicyName,
80 ),
81 ).toEqual(true);
82
83 const updated = yield* stack.deploy(
84 Effect.gen(function* () {
85 return yield* GCP.Compute.RegionSslPolicy("FrontendTls", {
86 sslPolicyName: created.sslPolicyName,
87 region,
88 description: "strict tls",
89 profile: "RESTRICTED",
90 minTlsVersion: "TLS_1_2",
91 });
92 }),
93 );
94
95 expect(updated.sslPolicyName).toEqual(created.sslPolicyName);
96 expect(updated.profile).toEqual("RESTRICTED");
97 expect(updated.minTlsVersion).toEqual("TLS_1_2");
98 expect(updated.description).toEqual("strict tls");
99
100 const refetched = yield* compute.getRegionSslPolicies({
101 project: updated.project,
102 region,
103 sslPolicy: updated.sslPolicyName,
104 });
105 expect(refetched.profile).toEqual("RESTRICTED");
106 expect(refetched.minTlsVersion).toEqual("TLS_1_2");
107 expect(refetched.description).toContain("strict tls");
108
109 const customized = yield* stack.deploy(
110 Effect.gen(function* () {
111 return yield* GCP.Compute.RegionSslPolicy("FrontendTls", {
112 sslPolicyName: created.sslPolicyName,
113 region,
114 description: "custom ciphers",
115 profile: "CUSTOM",
116 minTlsVersion: "TLS_1_2",
117 customFeatures: CUSTOM_FEATURES,
118 });
119 }),
120 );
121
122 expect(customized.sslPolicyName).toEqual(created.sslPolicyName);
123 expect(customized.profile).toEqual("CUSTOM");
124 expect(customized.customFeatures.sort()).toEqual(
125 [...CUSTOM_FEATURES].sort(),
126 );
127 expect(customized.description).toEqual("custom ciphers");
128
129 const afterCustom = yield* compute.getRegionSslPolicies({
130 project: customized.project,
131 region,
132 sslPolicy: customized.sslPolicyName,
133 });
134 expect(afterCustom.profile).toEqual("CUSTOM");
135 expect([...(afterCustom.customFeatures ?? [])].sort()).toEqual(
136 [...CUSTOM_FEATURES].sort(),
137 );
138
139 yield* stack.destroy();
140
141 const gone = yield* waitUntilGone(created.project, created.sslPolicyName);
142 expect(gone).toEqual("gone");
143 }).pipe(logLevel),
144 { tags: ["provider:gcp", "provider:gcp:compute", "live"], timeout: 90_000 },
145);