1import { Action } from "@/Action";
2import * as GCP from "@/GCP";
3import * as Test from "@/Test/Alchemy";
4import * as bigqueryconnection from "@distilled.cloud/gcp/bigqueryconnection_v1";
5import { expect } from "alchemy-test";
6import * as Effect from "effect/Effect";
7import { MinimumLogLevel } from "effect/References";
8import * as Schedule from "effect/Schedule";
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 bigqueryconnection.getProjectsLocationsConnections({ name }).pipe(
19 Effect.as("found" as const),
20 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
21 Effect.repeat({
22 schedule: Schedule.spaced("1 second"),
23 until: (status) => status === "gone",
24 times: 10,
25 }),
26 );
27
28test.provider(
29 "create, update, replace, and delete a cloud resource connection",
30 (stack) =>
31 Effect.gen(function* () {
32 yield* stack.destroy();
33
34 const { connection: created, live } = yield* stack.deploy(
35 Effect.gen(function* () {
36 const connection = yield* GCP.BigQueryConnection.Connection("Gcs", {
37 location: "us-central1",
38 friendlyName: "gcs-test",
39 description: "cloud resource connection",
40 cloudResource: {},
41 });
42 const Probe = Action(
43 "Probe",
44 Effect.gen(function* () {
45 yield* connection.name;
46 const getConnection =
47 yield* GCP.BigQueryConnection.GetConnection(connection);
48 return Effect.fn(function* () {
49 return yield* getConnection();
50 });
51 }),
52 );
53 return {
54 connection,
55 live: yield* Probe({}),
56 };
57 }),
58 );
59
60 expect(created.connectionId).toEqual(expect.any(String));
61 expect(created.name).toContain("/connections/");
62 expect(created.location).toEqual("us-central1");
63 expect(created.kind).toEqual("cloudResource");
64 expect(created.friendlyName).toEqual("gcs-test");
65 expect(created.description).toEqual("cloud resource connection");
66 expect(created.cloudResource).toEqual(expect.any(Object));
67 expect(created.serviceAccountId).toEqual(expect.any(String));
68 expect(live.name).toEqual(created.name);
69 expect(live.cloudResource).toEqual(expect.any(Object));
70
71 const fetched = yield* bigqueryconnection.getProjectsLocationsConnections(
72 {
73 name: created.name,
74 },
75 );
76 expect(fetched.name).toEqual(created.name);
77 expect(fetched.friendlyName).toEqual("gcs-test");
78 expect(fetched.description).toContain("alchemy-id=");
79 expect(fetched.description).toContain("cloud resource connection");
80 expect(fetched.cloudResource).toEqual(expect.any(Object));
81
82 const listed = yield* bigqueryconnection.listProjectsLocationsConnections(
83 {
84 parent: `projects/${created.project}/locations/${created.location}`,
85 pageSize: 100,
86 },
87 );
88 expect(
89 (listed.connections ?? []).some(
90 (connection) => connection.name === created.name,
91 ),
92 ).toEqual(true);
93
94 const updated = yield* stack.deploy(
95 Effect.gen(function* () {
96 return yield* GCP.BigQueryConnection.Connection("Gcs", {
97 connectionId: created.connectionId,
98 location: "us-central1",
99 friendlyName: "gcs-prod",
100 description: "updated cloud resource",
101 cloudResource: {},
102 });
103 }),
104 );
105
106 expect(updated.name).toEqual(created.name);
107 expect(updated.connectionId).toEqual(created.connectionId);
108 expect(updated.friendlyName).toEqual("gcs-prod");
109 expect(updated.description).toEqual("updated cloud resource");
110 expect(updated.kind).toEqual("cloudResource");
111 expect(updated.creationTime).toEqual(created.creationTime);
112
113 const fetchedUpdate =
114 yield* bigqueryconnection.getProjectsLocationsConnections({
115 name: updated.name,
116 });
117 expect(fetchedUpdate.friendlyName).toEqual("gcs-prod");
118 expect(fetchedUpdate.description).toContain("updated cloud resource");
119
120 const last = created.connectionId.at(-1) ?? "a";
121 const nextConnectionId = `${created.connectionId.slice(0, -1)}${last === "z" ? "0" : "z"}`;
122
123 const replaced = yield* stack.deploy(
124 Effect.gen(function* () {
125 return yield* GCP.BigQueryConnection.Connection("Gcs", {
126 connectionId: nextConnectionId,
127 location: "us-central1",
128 friendlyName: "gcs-replaced",
129 description: "replaced connection",
130 cloudResource: {},
131 });
132 }),
133 );
134
135 expect(replaced.connectionId).not.toEqual(created.connectionId);
136 expect(replaced.connectionId).toEqual(nextConnectionId);
137 expect(replaced.friendlyName).toEqual("gcs-replaced");
138 expect(replaced.kind).toEqual("cloudResource");
139
140 const fetchedReplace =
141 yield* bigqueryconnection.getProjectsLocationsConnections({
142 name: replaced.name,
143 });
144 expect(fetchedReplace.name).toEqual(replaced.name);
145 expect(fetchedReplace.friendlyName).toEqual("gcs-replaced");
146
147 const oldGone = yield* waitUntilGone(created.name);
148 expect(oldGone).toEqual("gone");
149
150 yield* stack.destroy();
151
152 const gone = yield* waitUntilGone(replaced.name);
153 expect(gone).toEqual("gone");
154 }).pipe(logLevel),
155 {
156 tags: ["provider:gcp", "provider:gcp:bigqueryconnection", "live"],
157 timeout: 90_000,
158 },
159);