From 8b4657d052ea503dca699aebef7854960eae8297 Mon Sep 17 00:00:00 2001 From: MarioCadenas Date: Fri, 9 Oct 2026 17:39:47 +0200 Subject: [PATCH] feat(shared): add a modular uc-volumes client to the workspace client Add a lazily built `volumes` accessor (VolumesClient from @databricks/sdk-uc-volumes@0.51.0, auth via mapToClientOptions) so the CLI can read volumes typed instead of through raw request(). Co-authored-by: Isaac Signed-off-by: MarioCadenas --- knip.json | 1 + packages/appkit/package.json | 1 + .../src/testing/mock-workspace-client.ts | 1 + packages/shared/package.json | 1 + .../shared/src/workspace-client/client.ts | 11 ++++++ .../shared/src/workspace-client/modular.ts | 16 ++++++++ .../workspace-client/tests/modular.test.ts | 39 +++++++++++++++++++ packages/shared/src/workspace-client/types.ts | 4 ++ pnpm-lock.yaml | 19 +++++++++ 9 files changed, 93 insertions(+) diff --git a/knip.json b/knip.json index 6a98bd010..02c3b30ac 100644 --- a/knip.json +++ b/knip.json @@ -19,6 +19,7 @@ "@databricks/sdk-postgres", "@databricks/sdk-modelserving", "@databricks/sdk-uc-tables", + "@databricks/sdk-uc-volumes", "@databricks/sdk-vectorsearch", "@databricks/sdk-options", "@databricks/sdk-scim", diff --git a/packages/appkit/package.json b/packages/appkit/package.json index a5d132e32..a724e5eb5 100644 --- a/packages/appkit/package.json +++ b/packages/appkit/package.json @@ -79,6 +79,7 @@ "@databricks/sdk-jobs": "0.57.0", "@databricks/sdk-modelserving": "0.53.0", "@databricks/sdk-uc-tables": "0.52.0", + "@databricks/sdk-uc-volumes": "0.51.0", "@databricks/sdk-vectorsearch": "0.51.0", "@databricks/sdk-options": "0.51.0", "@databricks/sdk-postgres": "0.52.0", diff --git a/packages/appkit/src/testing/mock-workspace-client.ts b/packages/appkit/src/testing/mock-workspace-client.ts index adcd8b777..d6a921920 100644 --- a/packages/appkit/src/testing/mock-workspace-client.ts +++ b/packages/appkit/src/testing/mock-workspace-client.ts @@ -72,6 +72,7 @@ const FACADE_SERVICES = [ "vectorSearch", "tables", "postgres", + "volumes", "statementExecution", "modelServing", "servingEndpoints", diff --git a/packages/shared/package.json b/packages/shared/package.json index 485dfe132..2e965936f 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -56,6 +56,7 @@ "@databricks/sdk-jobs": "0.57.0", "@databricks/sdk-modelserving": "0.53.0", "@databricks/sdk-uc-tables": "0.52.0", + "@databricks/sdk-uc-volumes": "0.51.0", "@databricks/sdk-vectorsearch": "0.51.0", "@databricks/sdk-options": "0.51.0", "@databricks/sdk-postgres": "0.52.0", diff --git a/packages/shared/src/workspace-client/client.ts b/packages/shared/src/workspace-client/client.ts index 29d272d66..dd55d02b4 100644 --- a/packages/shared/src/workspace-client/client.ts +++ b/packages/shared/src/workspace-client/client.ts @@ -30,6 +30,8 @@ import { type TablesClient, buildPostgresClient, type PostgresClient, + buildVolumesClient, + type VolumesClient, buildVectorSearchClient, type VectorSearchClient, type StatementExecutionClient, @@ -53,6 +55,7 @@ export class AppKitWorkspaceClient implements WorkspaceClient { #vectorSearch?: VectorSearchClient; #tables?: TablesClient; #postgres?: PostgresClient; + #volumes?: VolumesClient; constructor(opts: WorkspaceClientOptions) { this.#opts = opts; @@ -114,6 +117,14 @@ export class AppKitWorkspaceClient implements WorkspaceClient { return this.#postgres; } + // Migrated to the modular SDK — built lazily, independent of the legacy client. + get volumes(): VolumesClient { + if (!this.#volumes) { + this.#volumes = buildVolumesClient(this.#opts); + } + return this.#volumes; + } + // Migrated to the modular SDK — built lazily, independent of the legacy client. get statementExecution(): StatementExecutionClient { if (!this.#statementExecution) { diff --git a/packages/shared/src/workspace-client/modular.ts b/packages/shared/src/workspace-client/modular.ts index d077cf542..995039ea7 100644 --- a/packages/shared/src/workspace-client/modular.ts +++ b/packages/shared/src/workspace-client/modular.ts @@ -61,6 +61,7 @@ import type { PostgresClient } from "@databricks/sdk-postgres/v1"; import { ScimClient } from "@databricks/sdk-scim/v1"; import { StatementExecutionClient } from "@databricks/sdk-statementexecution/v1"; import type { TablesClient } from "@databricks/sdk-uc-tables/v1"; +import type { VolumesClient } from "@databricks/sdk-uc-volumes/v1"; import type { VectorSearchClient } from "@databricks/sdk-vectorsearch/v1"; import { WarehousesClient } from "@databricks/sdk-warehouses/v1"; @@ -638,6 +639,16 @@ export function buildTablesClient(opts: WorkspaceClientOptions): TablesClient { ); } +/** Build a modular Unity Catalog Volumes client from wrapper options. */ +export function buildVolumesClient( + opts: WorkspaceClientOptions, +): VolumesClient { + return lazyClient( + () => import("@databricks/sdk-uc-volumes/v1").then((m) => m.VolumesClient), + mapToClientOptions(opts), + ); +} + /** * Build a modular Lakebase Postgres (autoscaling: projects, branches, * endpoints) client from wrapper options. Distinct from the provisioned @@ -665,6 +676,7 @@ export type { PostgresClient } from "@databricks/sdk-postgres/v1"; export type { ScimClient } from "@databricks/sdk-scim/v1"; export type { StatementExecutionClient } from "@databricks/sdk-statementexecution/v1"; export type { TablesClient } from "@databricks/sdk-uc-tables/v1"; +export type { VolumesClient } from "@databricks/sdk-uc-volumes/v1"; export type { VectorSearchClient } from "@databricks/sdk-vectorsearch/v1"; export type { WarehousesClient } from "@databricks/sdk-warehouses/v1"; @@ -724,3 +736,7 @@ export type { QueryVectorIndexRequest, QueryVectorIndexResponse, } from "@databricks/sdk-vectorsearch/v1"; +export type { + GetVolumeRequest, + VolumeInfo, +} from "@databricks/sdk-uc-volumes/v1"; diff --git a/packages/shared/src/workspace-client/tests/modular.test.ts b/packages/shared/src/workspace-client/tests/modular.test.ts index f7c4ff195..b54ca0a8c 100644 --- a/packages/shared/src/workspace-client/tests/modular.test.ts +++ b/packages/shared/src/workspace-client/tests/modular.test.ts @@ -61,6 +61,12 @@ vi.mock("@databricks/sdk-modelserving/v1", () => ({ return { opts, getInferenceEndpoint: async () => ({}) }; }), })); +vi.mock("@databricks/sdk-uc-volumes/v1", () => ({ + VolumesClient: vi.fn().mockImplementation((opts) => { + ctorOpts.push(opts); + return { opts, getVolume: async () => ({}) }; + }), +})); vi.mock("@databricks/sdk-postgres/v1", () => ({ PostgresClient: vi.fn().mockImplementation((opts) => { ctorOpts.push(opts); @@ -132,6 +138,7 @@ import { ApiError } from "../errors"; import { buildGenieClient, buildModelServingClient, + buildVolumesClient, buildWarehousesClient, buildPostgresClient, buildWorkspaceAuth, @@ -384,6 +391,38 @@ describe("modular mapToClientOptions (via buildWarehousesClient)", () => { expect(m2mOpts).toEqual([]); }); + test("volumes: SP env creds → M2M with the scheme-normalized host", async () => { + process.env.DATABRICKS_HOST = "envhost.cloud.databricks.com"; + process.env.DATABRICKS_CLIENT_ID = "sp-client-id"; + process.env.DATABRICKS_CLIENT_SECRET = "sp-secret"; + await buildVolumesClient({}).getVolume({} as never); + expect(ctorOpts[0].host).toBe("https://envhost.cloud.databricks.com"); + expect(m2mOpts).toEqual([ + { + host: "https://envhost.cloud.databricks.com", + clientId: "sp-client-id", + clientSecret: "sp-secret", + }, + ]); + expect((ctorOpts[0].credentials as { name: () => string }).name()).toBe( + "oauth-m2m", + ); + }); + + test("volumes (asUser) uses the OBO token as PAT", async () => { + process.env.DATABRICKS_CLIENT_ID = "sp-client-id"; + process.env.DATABRICKS_CLIENT_SECRET = "sp-secret"; + await buildVolumesClient({ + token: "user-token", + host: "https://x", + }).getVolume({} as never); + expect(ctorOpts[0].credentials).toMatchObject({ + kind: "pat", + token: "user-token", + }); + expect(m2mOpts).toEqual([]); + }); + test("postgres normalizes the host and passes SP M2M credentials", async () => { process.env.DATABRICKS_HOST = "envhost.cloud.databricks.com"; process.env.DATABRICKS_CLIENT_ID = "sp-client-id"; diff --git a/packages/shared/src/workspace-client/types.ts b/packages/shared/src/workspace-client/types.ts index 5541fb20d..66dc9fbf1 100644 --- a/packages/shared/src/workspace-client/types.ts +++ b/packages/shared/src/workspace-client/types.ts @@ -24,6 +24,7 @@ import type { ModelServingClient, FilesClient, TablesClient, + VolumesClient, VectorSearchClient, PostgresClient, } from "./modular"; @@ -69,6 +70,9 @@ export interface WorkspaceClient extends WorkspaceAuth { /** Lakebase Postgres: autoscaling projects, branches, endpoints (modular SDK). */ readonly postgres: PostgresClient; + /** Unity Catalog Volumes (modular SDK). */ + readonly volumes: VolumesClient; + /** Statement Execution (modular SDK). */ readonly statementExecution: StatementExecutionClient; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 82ba5bc69..f1fa623cd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -317,6 +317,9 @@ importers: '@databricks/sdk-uc-tables': specifier: 0.52.0 version: 0.52.0 + '@databricks/sdk-uc-volumes': + specifier: 0.51.0 + version: 0.51.0 '@databricks/sdk-vectorsearch': specifier: 0.51.0 version: 0.51.0(patch_hash=b3d79eea4bba92065adc591ee8e6f1d72c0acdac6c00e0cb522074a5fb14ba8e) @@ -674,6 +677,9 @@ importers: '@databricks/sdk-uc-tables': specifier: 0.52.0 version: 0.52.0 + '@databricks/sdk-uc-volumes': + specifier: 0.51.0 + version: 0.51.0 '@databricks/sdk-vectorsearch': specifier: 0.51.0 version: 0.51.0(patch_hash=b3d79eea4bba92065adc591ee8e6f1d72c0acdac6c00e0cb522074a5fb14ba8e) @@ -2097,6 +2103,10 @@ packages: resolution: {integrity: sha512-Dlqu3+O1krk6ogBX/uJGUDn1xMdt0gVMvrpmf16XkPelmgzwrbdWWtU2LU/zlcCBrb3XvhPPUpxVVHmyNS8Pjg==} engines: {node: '>=22.0.0'} + '@databricks/sdk-uc-volumes@0.51.0': + resolution: {integrity: sha512-Vmk+epraPslz+2pP90XOaZN3wxaoz1UY0mgFnvgUJ/AJHbB5Ei1OTQhtL+Mn5JTVkIaLT6LmJD/xmOqAtaRGLw==} + engines: {node: '>=22.0.0'} + '@databricks/sdk-vectorsearch@0.51.0': resolution: {integrity: sha512-Hr5z5lbT4pt0FV7L+gvKIFdp0PlWtyH14bs6+rJsCxcgwV6BQhuuVecJv8M4FB8QdsDZd2Us/JVIa5LwHHVORA==} engines: {node: '>=22.0.0'} @@ -14478,6 +14488,15 @@ snapshots: json-bigint: 1.0.0 zod: 4.3.6 + '@databricks/sdk-uc-volumes@0.51.0': + dependencies: + '@databricks/sdk-auth': 0.51.0 + '@databricks/sdk-core': 0.51.0 + '@databricks/sdk-options': 0.51.0 + '@js-temporal/polyfill': 0.5.1 + json-bigint: 1.0.0 + zod: 4.3.6 + '@databricks/sdk-vectorsearch@0.51.0(patch_hash=b3d79eea4bba92065adc591ee8e6f1d72c0acdac6c00e0cb522074a5fb14ba8e)': dependencies: '@databricks/sdk-auth': 0.51.0