1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import * as networkconnectivity from "@distilled.cloud/gcp/networkconnectivity_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 runLifecycle = !process.env.FAST;
18
19const waitUntilGone = (name: string) =>
20 networkconnectivity
21 .getProjectsLocationsMulticloudDataTransferConfigs({ name })
22 .pipe(
23 Effect.as("found" as const),
24 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
25 Effect.repeat({
26 schedule: Schedule.spaced("2 seconds"),
27 until: (status) => status === "gone",
28 times: 10,
29 }),
30 );
31
32test.provider(
33 "getProjectsLocationsMulticloudDataTransferConfigs on a missing config fails with a typed tag",
34 (stack) =>
35 Effect.gen(function* () {
36 const { project } = yield* GcpEnvironment.current;
37 yield* stack.destroy();
38
39 const error = yield* Effect.flip(
40 networkconnectivity.getProjectsLocationsMulticloudDataTransferConfigs({
41 name: `projects/${project}/locations/us-central1/multicloudDataTransferConfigs/alchemy-missing`,
42 }),
43 );
44 expect(error._tag).toEqual("NotFound");
45
46 yield* stack.destroy();
47 }).pipe(logLevel),
48 {
49 tags: ["provider:gcp", "provider:gcp:networkconnectivity", "live"],
50 timeout: 90_000,
51 },
52);
53
54test.provider.skipIf(!runLifecycle)(
55 "create, update, and delete a multicloud data transfer config",
56 (stack) =>
57 Effect.gen(function* () {
58 yield* stack.destroy();
59
60 const created = yield* stack.deploy(
61 Effect.gen(function* () {
62 return yield* GCP.NetworkConnectivity.MulticloudDataTransferConfig(
63 "Dte",
64 {
65 location: "europe-west1",
66 description: "dte a",
67 services: { "cloud-storage": {}, "compute-engine": {} },
68 labels: { env: "test" },
69 },
70 );
71 }),
72 );
73
74 expect(created.name).toContain("/multicloudDataTransferConfigs/");
75 expect(created.location).toEqual("europe-west1");
76 expect(created.description).toEqual("dte a");
77 expect(created.labels).toMatchObject({ env: "test" });
78 expect(created.multicloudDataTransferConfigId).toEqual(
79 expect.any(String),
80 );
81
82 const fetched =
83 yield* networkconnectivity.getProjectsLocationsMulticloudDataTransferConfigs(
84 { name: created.name },
85 );
86 expect(fetched.name).toEqual(created.name);
87 expect(fetched.description).toEqual("dte a");
88 expect(fetched.labels?.env).toEqual("test");
89 expect(
90 Object.keys(fetched.labels ?? {}).some((key) =>
91 key.startsWith("alchemy-"),
92 ),
93 ).toEqual(true);
94
95 const updated = yield* stack.deploy(
96 Effect.gen(function* () {
97 return yield* GCP.NetworkConnectivity.MulticloudDataTransferConfig(
98 "Dte",
99 {
100 multicloudDataTransferConfigId:
101 created.multicloudDataTransferConfigId,
102 location: created.location,
103 description: "dte b",
104 labels: { env: "prod", role: "dte" },
105 },
106 );
107 }),
108 );
109
110 expect(updated.name).toEqual(created.name);
111 expect(updated.description).toEqual("dte b");
112 expect(updated.labels).toMatchObject({ env: "prod", role: "dte" });
113
114 const refetched =
115 yield* networkconnectivity.getProjectsLocationsMulticloudDataTransferConfigs(
116 { name: created.name },
117 );
118 expect(refetched.description).toEqual("dte b");
119 expect(refetched.labels?.env).toEqual("prod");
120 expect(refetched.labels?.role).toEqual("dte");
121
122 yield* stack.destroy();
123
124 const gone = yield* waitUntilGone(created.name);
125 expect(gone).toEqual("gone");
126 }).pipe(logLevel),
127 {
128 tags: ["provider:gcp", "provider:gcp:networkconnectivity", "live"],
129 timeout: 180_000,
130 },
131);