1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import * as datacatalog from "@distilled.cloud/gcp/datacatalog_v1";
4import { expect } from "alchemy-test";
5import * as Effect from "effect/Effect";
6import * as Schedule from "effect/Schedule";
7import { location, logLevel, currentProject } from "./common.ts";
8
9const { test } = Test.make({ providers: GCP.providers() });
10
11const waitUntilGone = (name: string) =>
12 datacatalog.getProjectsLocationsTaxonomies({ name }).pipe(
13 Effect.as("found" as const),
14 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
15 Effect.repeat({
16 schedule: Schedule.spaced("1 second"),
17 until: (status) => status === "gone",
18 times: 10,
19 }),
20 );
21
22test.provider(
23 "getProjectsLocationsTaxonomies on a missing taxonomy 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 datacatalog.getProjectsLocationsTaxonomies({
31 name: `projects/${project}/locations/${location}/taxonomies/alchemy-missing-taxonomy`,
32 }),
33 );
34 expect(error._tag).toEqual("NotFound");
35
36 yield* stack.destroy();
37 }).pipe(logLevel),
38 {
39 tags: ["provider:gcp", "provider:gcp:datacatalog", "live"],
40 timeout: 90_000,
41 },
42);
43
44test.provider(
45 "create, update, and delete a taxonomy",
46 (stack) =>
47 Effect.gen(function* () {
48 const project = yield* currentProject;
49 yield* stack.destroy();
50
51 const created = yield* stack.deploy(
52 Effect.gen(function* () {
53 return yield* GCP.DataCatalog.Taxonomy("Pii", {
54 location,
55 description: "taxonomy a",
56 activatedPolicyTypes: ["FINE_GRAINED_ACCESS_CONTROL"],
57 });
58 }),
59 );
60
61 expect(created.name).toContain("/taxonomies/");
62 expect(created.taxonomyId).toEqual(expect.any(String));
63 expect(created.project).toEqual(project);
64 expect(created.location).toEqual(location);
65 expect(created.displayName).toEqual(expect.any(String));
66 expect(created.description).toEqual("taxonomy a");
67 expect(created.activatedPolicyTypes).toContain(
68 "FINE_GRAINED_ACCESS_CONTROL",
69 );
70
71 const fetched = yield* datacatalog.getProjectsLocationsTaxonomies({
72 name: created.name,
73 });
74 expect(fetched.name).toEqual(created.name);
75 expect(fetched.description).toContain("alchemy-id=");
76 expect(fetched.description).toContain("taxonomy a");
77 expect(fetched.displayName).toEqual(created.displayName);
78
79 const updated = yield* stack.deploy(
80 Effect.gen(function* () {
81 return yield* GCP.DataCatalog.Taxonomy("Pii", {
82 location,
83 displayName: created.displayName,
84 description: "taxonomy b",
85 activatedPolicyTypes: ["FINE_GRAINED_ACCESS_CONTROL"],
86 });
87 }),
88 );
89
90 expect(updated.name).toEqual(created.name);
91 expect(updated.displayName).toEqual(created.displayName);
92 expect(updated.description).toEqual("taxonomy b");
93
94 yield* stack.destroy();
95 const gone = yield* waitUntilGone(created.name);
96 expect(gone).toEqual("gone");
97 }).pipe(logLevel),
98 {
99 tags: ["provider:gcp", "provider:gcp:datacatalog", "live"],
100 timeout: 90_000,
101 },
102);