1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import * as dataplex from "@distilled.cloud/gcp/dataplex_v1";
4import { expect } from "alchemy-test";
5import * as Effect from "effect/Effect";
6import { MinimumLogLevel } from "effect/References";
7import * as Schedule from "effect/Schedule";
8import { withDataplexSlot } from "./quota.ts";
9
10const { test } = Test.make({ providers: GCP.providers() });
11
12const logLevel = Effect.provideService(
13 MinimumLogLevel,
14 process.env.DEBUG ? "Debug" : "Info",
15);
16
17const RELATED_ENTRY_LINK_TYPE =
18 "projects/dataplex-types/locations/global/entryLinkTypes/related";
19
20const waitUntilGone = (name: string) =>
21 dataplex.getProjectsLocationsEntryGroupsEntryLinks({ name }).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
31test.provider.skipIf(!!process.env.FAST)(
32 "create, update, and delete an entry link",
33 (stack) =>
34 Effect.gen(function* () {
35 yield* stack.destroy();
36
37 const created = yield* stack.deploy(
38 Effect.gen(function* () {
39 const type = yield* GCP.Dataplex.EntryType("Kind", {
40 location: "us-central1",
41 displayName: "kind",
42 });
43 const group = yield* GCP.Dataplex.EntryGroup("Catalog", {
44 location: "us-central1",
45 displayName: "catalog",
46 labels: { env: "test" },
47 });
48 const left = yield* GCP.Dataplex.EntryGroupsEntry("Left", {
49 entryGroup: group.name,
50 entryType: type.name,
51 labels: { env: "test" },
52 });
53 const right = yield* GCP.Dataplex.EntryGroupsEntry("Right", {
54 entryGroup: group.name,
55 entryType: type.name,
56 labels: { env: "test" },
57 });
58 const link = yield* GCP.Dataplex.EntryGroupsEntryLink("Related", {
59 entryGroup: group.name,
60 entryLinkType: RELATED_ENTRY_LINK_TYPE,
61 entryReferences: [
62 { name: left.name, type: "UNSPECIFIED" },
63 { name: right.name, type: "UNSPECIFIED" },
64 ],
65 });
66 return { type, group, left, right, link };
67 }),
68 );
69
70 expect(created.link.name).toContain("/entryLinks/");
71 expect(created.link.entryGroup).toEqual(created.group.name);
72 expect(created.link.entryLinkType).toContain("/entryLinkTypes/related");
73 expect(created.link.entryReferences).toHaveLength(2);
74
75 const fetched = yield* dataplex.getProjectsLocationsEntryGroupsEntryLinks(
76 {
77 name: created.link.name,
78 },
79 );
80 expect(fetched.name).toEqual(created.link.name);
81 expect(fetched.entryLinkType).toContain("/entryLinkTypes/related");
82 expect(fetched.entryReferences ?? []).toHaveLength(2);
83
84 const updated = yield* stack.deploy(
85 Effect.gen(function* () {
86 const type = yield* GCP.Dataplex.EntryType("Kind", {
87 entryTypeId: created.type.entryTypeId,
88 location: "us-central1",
89 displayName: "kind",
90 });
91 const group = yield* GCP.Dataplex.EntryGroup("Catalog", {
92 entryGroupId: created.group.entryGroupId,
93 location: "us-central1",
94 displayName: "catalog",
95 labels: { env: "test" },
96 });
97 const left = yield* GCP.Dataplex.EntryGroupsEntry("Left", {
98 entryGroup: group.name,
99 entryId: created.left.entryId,
100 entryType: type.name,
101 labels: { env: "test" },
102 });
103 const right = yield* GCP.Dataplex.EntryGroupsEntry("Right", {
104 entryGroup: group.name,
105 entryId: created.right.entryId,
106 entryType: type.name,
107 labels: { env: "test" },
108 });
109 const link = yield* GCP.Dataplex.EntryGroupsEntryLink("Related", {
110 entryGroup: group.name,
111 entryLinkId: created.link.entryLinkId,
112 entryLinkType: RELATED_ENTRY_LINK_TYPE,
113 entryReferences: [
114 { name: left.name, type: "UNSPECIFIED" },
115 { name: right.name, type: "UNSPECIFIED" },
116 ],
117 });
118 return { type, group, left, right, link };
119 }),
120 );
121
122 expect(updated.link.name).toEqual(created.link.name);
123 expect(updated.link.entryLinkType).toContain("/entryLinkTypes/related");
124
125 yield* stack.destroy();
126 const gone = yield* waitUntilGone(created.link.name);
127 expect(gone).toEqual("gone");
128 }).pipe(logLevel, withDataplexSlot),
129 { tags: ["provider:gcp", "provider:gcp:dataplex", "live"], timeout: 900_000 },
130);