1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import * as beyondcorp from "@distilled.cloud/gcp/beyondcorp_v1";
4import { expect } from "alchemy-test";
5import * as Effect from "effect/Effect";
6import * as Schedule from "effect/Schedule";
7import { logLevel, currentProject, runLifecycle } from "./common.ts";
8
9const { test } = Test.make({ providers: GCP.providers() });
10
11const waitUntilGone = (name: string) =>
12 beyondcorp.getProjectsLocationsSecurityGateways({ name }).pipe(
13 Effect.as("found" as const),
14 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
15 Effect.repeat({
16 schedule: Schedule.spaced("2 seconds"),
17 until: (status) => status === "gone",
18 times: 10,
19 }),
20 );
21
22test.provider(
23 "getProjectsLocationsSecurityGateways on a missing gateway fails with a typed tag",
24 (stack) =>
25 Effect.gen(function* () {
26 const project = yield* currentProject;
27 yield* stack.destroy();
28
29 const error = yield* Effect.flip(
30 beyondcorp.getProjectsLocationsSecurityGateways({
31 name: `projects/${project}/locations/global/securityGateways/alchemy-missing-sg`,
32 }),
33 );
34 expect(error._tag).toEqual("NotFound");
35
36 const page = yield* beyondcorp.listProjectsLocationsSecurityGateways({
37 parent: `projects/${project}/locations/global`,
38 pageSize: 10,
39 });
40 expect(
41 (page.securityGateways ?? []).map((item) => item.name),
42 ).not.toContain(
43 `projects/${project}/locations/global/securityGateways/alchemy-missing-sg`,
44 );
45
46 yield* stack.destroy();
47 }).pipe(logLevel),
48 {
49 tags: ["provider:gcp", "provider:gcp:beyondcorp", "live"],
50 timeout: 90_000,
51 },
52);
53
54test.provider.skipIf(runLifecycle)(
55 "createProjectsLocationsSecurityGateways without entitlement fails with a typed tag",
56 (stack) =>
57 Effect.gen(function* () {
58 const project = yield* currentProject;
59 yield* stack.destroy();
60
61 const error = yield* Effect.flip(
62 beyondcorp.createProjectsLocationsSecurityGateways({
63 parent: `projects/${project}/locations/global`,
64 securityGatewayId: "alch-probe-sg",
65 body: {
66 displayName: "probe",
67 hubs: { "us-central1": { internetGateway: {} } },
68 },
69 }),
70 );
71 expect(error._tag).toEqual("BadRequest");
72 expect(error.message).toContain("Chrome Enterprise Premium");
73
74 yield* stack.destroy();
75 }).pipe(logLevel),
76 {
77 tags: ["provider:gcp", "provider:gcp:beyondcorp", "live"],
78 timeout: 90_000,
79 },
80);
81
82test.provider.skipIf(!runLifecycle)(
83 "create, update, and delete a security gateway",
84 (stack) =>
85 Effect.gen(function* () {
86 yield* stack.destroy();
87
88 const created = yield* stack.deploy(
89 Effect.gen(function* () {
90 return yield* GCP.BeyondCorp.SecurityGateway("Pep", {
91 location: "global",
92 displayName: "gateway a",
93 hubs: { "us-central1": { internetGateway: {} } },
94 });
95 }),
96 );
97
98 expect(created.name).toContain("/securityGateways/");
99 expect(created.location).toEqual("global");
100 expect(created.displayName).toEqual("gateway a");
101 expect(Object.keys(created.hubs ?? {})).toContain("us-central1");
102
103 const fetched = yield* beyondcorp.getProjectsLocationsSecurityGateways({
104 name: created.name,
105 });
106 expect(fetched.name).toEqual(created.name);
107 expect(fetched.displayName).toContain("gateway a");
108
109 const updated = yield* stack.deploy(
110 Effect.gen(function* () {
111 return yield* GCP.BeyondCorp.SecurityGateway("Pep", {
112 securityGatewayId: created.securityGatewayId,
113 location: "global",
114 displayName: "gateway b",
115 hubs: { "us-central1": { internetGateway: {} } },
116 });
117 }),
118 );
119
120 expect(updated.name).toEqual(created.name);
121 expect(updated.displayName).toEqual("gateway b");
122
123 const refetched = yield* beyondcorp.getProjectsLocationsSecurityGateways({
124 name: created.name,
125 });
126 expect(refetched.displayName).toContain("gateway b");
127
128 yield* stack.destroy();
129
130 const gone = yield* waitUntilGone(created.name);
131 expect(gone).toEqual("gone");
132 }).pipe(logLevel),
133 {
134 tags: ["provider:gcp", "provider:gcp:beyondcorp", "live"],
135 timeout: 120_000,
136 },
137);