1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import * as networksecurity from "@distilled.cloud/gcp/networksecurity_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 = (name: string) =>
18 networksecurity
19 .getProjectsLocationsGatewaySecurityPoliciesRules({ 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(
31 "getProjectsLocationsGatewaySecurityPoliciesRules on a missing rule fails with a typed tag",
32 (stack) =>
33 Effect.gen(function* () {
34 yield* stack.destroy();
35
36 const { project } = yield* GcpEnvironment.current;
37 const error = yield* Effect.flip(
38 networksecurity.getProjectsLocationsGatewaySecurityPoliciesRules({
39 name: `projects/${project}/locations/us-central1/gatewaySecurityPolicies/alchemy-missing/rules/missing`,
40 }),
41 );
42 expect(error._tag).toEqual("NotFound");
43
44 yield* stack.destroy();
45 }).pipe(logLevel),
46 {
47 tags: ["provider:gcp", "provider:gcp:networksecurity", "live"],
48 timeout: 90_000,
49 },
50);
51
52test.provider(
53 "create, update, and delete a gateway security policy rule",
54 (stack) =>
55 Effect.gen(function* () {
56 yield* stack.destroy();
57
58 const created = yield* stack.deploy(
59 Effect.gen(function* () {
60 const policy = yield* GCP.NetworkSecurity.GatewaySecurityPolicy(
61 "Swp",
62 {
63 location: "us-central1",
64 description: "rule parent",
65 },
66 );
67 const rule = yield* GCP.NetworkSecurity.GatewaySecurityPoliciesRule(
68 "Allow",
69 {
70 gatewaySecurityPolicy: policy.name,
71 location: "us-central1",
72 basicProfile: "ALLOW",
73 priority: 1000,
74 enabled: true,
75 sessionMatcher: "true",
76 description: "allow all a",
77 },
78 );
79 return { policy, rule };
80 }),
81 );
82
83 expect(created.rule.name).toContain("/rules/");
84 expect(created.rule.gatewaySecurityPolicy).toEqual(created.policy.name);
85 expect(created.rule.basicProfile).toEqual("ALLOW");
86 expect(created.rule.priority).toEqual(1000);
87 expect(created.rule.enabled).toEqual(true);
88 expect(created.rule.sessionMatcher).toEqual("true");
89 expect(created.rule.description).toEqual("allow all a");
90
91 const fetched =
92 yield* networksecurity.getProjectsLocationsGatewaySecurityPoliciesRules(
93 {
94 name: created.rule.name,
95 },
96 );
97 expect(fetched.name).toEqual(created.rule.name);
98 expect(fetched.basicProfile).toEqual("ALLOW");
99 expect(fetched.priority).toEqual(1000);
100 expect(fetched.description).toContain("alchemy-id=");
101 expect(fetched.description).toContain("allow all a");
102
103 const updated = yield* stack.deploy(
104 Effect.gen(function* () {
105 const policy = yield* GCP.NetworkSecurity.GatewaySecurityPolicy(
106 "Swp",
107 {
108 gatewaySecurityPolicyId: created.policy.gatewaySecurityPolicyId,
109 location: "us-central1",
110 description: "rule parent",
111 },
112 );
113 const rule = yield* GCP.NetworkSecurity.GatewaySecurityPoliciesRule(
114 "Allow",
115 {
116 gatewaySecurityPolicy: policy.name,
117 gatewaySecurityPolicyRuleId:
118 created.rule.gatewaySecurityPolicyRuleId,
119 location: "us-central1",
120 basicProfile: "DENY",
121 priority: 100,
122 enabled: true,
123 sessionMatcher: "true",
124 description: "deny all b",
125 },
126 );
127 return { policy, rule };
128 }),
129 );
130
131 expect(updated.rule.name).toEqual(created.rule.name);
132 expect(updated.rule.basicProfile).toEqual("DENY");
133 expect(updated.rule.priority).toEqual(100);
134 expect(updated.rule.description).toEqual("deny all b");
135
136 const refetched =
137 yield* networksecurity.getProjectsLocationsGatewaySecurityPoliciesRules(
138 {
139 name: created.rule.name,
140 },
141 );
142 expect(refetched.basicProfile).toEqual("DENY");
143 expect(refetched.priority).toEqual(100);
144 expect(refetched.description).toContain("deny all b");
145
146 yield* stack.destroy();
147
148 const gone = yield* waitUntilGone(created.rule.name);
149 expect(gone).toEqual("gone");
150 }).pipe(logLevel),
151 {
152 tags: ["provider:gcp", "provider:gcp:networksecurity", "live"],
153 timeout: 90_000,
154 },
155);