1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import * as biglake from "@distilled.cloud/gcp/biglake_v1";
4import { expect } from "alchemy-test";
5import * as Effect from "effect/Effect";
6import { location, logLevel, currentProject, waitUntilGone } from "./common.ts";
7
8const { test } = Test.make({ providers: GCP.providers() });
9
10test.provider(
11 "getProjectsLocationsCatalogsDatabasesTables on a missing table fails with a typed tag",
12 (stack) =>
13 Effect.gen(function* () {
14 const project = yield* currentProject;
15
16 yield* stack.destroy();
17
18 const error = yield* Effect.flip(
19 biglake.getProjectsLocationsCatalogsDatabasesTables({
20 name: `projects/${project}/locations/${location}/catalogs/missing/databases/missing/tables/alchemy-missing`,
21 }),
22 );
23 expect(error._tag).toEqual("BigLakeResourceNotFound");
24
25 yield* stack.destroy();
26 }).pipe(logLevel),
27 { tags: ["provider:gcp", "provider:gcp:biglake", "live"], timeout: 90_000 },
28);
29
30test.provider(
31 "create, update, and delete a catalog database table",
32 (stack) =>
33 Effect.gen(function* () {
34 yield* stack.destroy();
35
36 const bucket = yield* stack.deploy(
37 Effect.gen(function* () {
38 return yield* GCP.Storage.Bucket("HiveTable", {
39 location: "US-CENTRAL1",
40 forceDestroy: true,
41 });
42 }),
43 );
44
45 const created = yield* stack.deploy(
46 Effect.gen(function* () {
47 const catalog = yield* GCP.BigLake.Catalog("Lake", { location });
48 const database = yield* GCP.BigLake.CatalogsDatabase("Warehouse", {
49 catalog: catalog.name,
50 locationUri: `gs://${bucket.bucketName}/warehouse`,
51 });
52 const table = yield* GCP.BigLake.CatalogsDatabasesTable("Events", {
53 database: database.name,
54 hiveOptions: {
55 tableType: "MANAGED_TABLE",
56 storageDescriptor: {
57 locationUri: `gs://${bucket.bucketName}/events`,
58 inputFormat: "org.apache.hadoop.mapred.SequenceFileInputFormat",
59 outputFormat:
60 "org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat",
61 },
62 parameters: { owner: "analytics" },
63 },
64 });
65 return { catalog, database, table };
66 }),
67 );
68
69 expect(created.table.name).toContain("/tables/");
70 expect(created.table.database).toEqual(created.database.name);
71 expect(created.table.type).toEqual("HIVE");
72 expect(created.table.tableType).toEqual("MANAGED_TABLE");
73 expect(created.table.parameters).toMatchObject({ owner: "analytics" });
74 expect(created.table.storageDescriptor?.locationUri).toEqual(
75 `gs://${bucket.bucketName}/events`,
76 );
77
78 const fetched =
79 yield* biglake.getProjectsLocationsCatalogsDatabasesTables({
80 name: created.table.name,
81 });
82 expect(fetched.name).toEqual(created.table.name);
83 expect(fetched.type).toEqual("HIVE");
84 expect(fetched.hiveOptions?.tableType).toEqual("MANAGED_TABLE");
85 expect(fetched.hiveOptions?.parameters?.owner).toEqual("analytics");
86 expect(fetched.hiveOptions?.parameters?.["alchemy-id"]).toEqual(
87 expect.any(String),
88 );
89
90 const updated = yield* stack.deploy(
91 Effect.gen(function* () {
92 const catalog = yield* GCP.BigLake.Catalog("Lake", {
93 catalogId: created.catalog.catalogId,
94 location,
95 });
96 const database = yield* GCP.BigLake.CatalogsDatabase("Warehouse", {
97 catalog: catalog.name,
98 databaseId: created.database.databaseId,
99 locationUri: `gs://${bucket.bucketName}/warehouse`,
100 });
101 const table = yield* GCP.BigLake.CatalogsDatabasesTable("Events", {
102 database: database.name,
103 tableId: created.table.tableId,
104 hiveOptions: {
105 tableType: "EXTERNAL_TABLE",
106 storageDescriptor: {
107 locationUri: `gs://${bucket.bucketName}/events-v2`,
108 inputFormat: "org.apache.hadoop.mapred.SequenceFileInputFormat",
109 outputFormat:
110 "org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat",
111 },
112 parameters: { owner: "data", env: "prod" },
113 },
114 });
115 return { catalog, database, table };
116 }),
117 );
118
119 expect(updated.table.name).toEqual(created.table.name);
120 expect(updated.table.tableType).toEqual("EXTERNAL_TABLE");
121 expect(updated.table.storageDescriptor?.locationUri).toEqual(
122 `gs://${bucket.bucketName}/events-v2`,
123 );
124 expect(updated.table.parameters).toMatchObject({
125 owner: "data",
126 env: "prod",
127 });
128
129 yield* stack.destroy();
130 const gone = yield* waitUntilGone(
131 biglake.getProjectsLocationsCatalogsDatabasesTables({
132 name: created.table.name,
133 }),
134 );
135 expect(gone).toEqual("gone");
136 }).pipe(logLevel),
137 { tags: ["provider:gcp", "provider:gcp:biglake", "live"], timeout: 120_000 },
138);