Skip to content

Commit 968c084

Browse files
authored
Automatically enable serverless when serverless_compute_id=auto (#1550)
## Changes Automatically enable serverless when serverless_compute_id=auto ## Tests Manually, e2e tests in the followup
1 parent e7b4ac0 commit 968c084

File tree

10 files changed

+105
-43
lines changed

10 files changed

+105
-43
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
},
1515
"scripts": {
1616
"install:sdk": "yarn fetch:sdk && chmod a+x scripts/install_sdk.sh && scripts/install_sdk.sh",
17-
"fetch:sdk": "rm -rf vendor && mkdir vendor && gh release download -R databricks/databricks-sdk-js v0.7.0 -p '*.tgz' && mv *.tgz vendor/databricks-sdk.tgz",
17+
"fetch:sdk": "rm -rf vendor && mkdir vendor && gh release download -R databricks/databricks-sdk-js v0.8.0 -p '*.tgz' && mv *.tgz vendor/databricks-sdk.tgz",
1818
"test": "yarn workspaces foreach run test",
1919
"test:integ": "yarn workspaces foreach run test:integ",
2020
"build": "yarn workspaces foreach run build",

packages/databricks-vscode/src/configuration/ConnectionCommands.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -135,16 +135,9 @@ export class ConnectionCommands implements Disposable {
135135
quickPick.title =
136136
typeof title === "string" ? title : "Select Cluster";
137137
quickPick.keepScrollPosition = true;
138-
quickPick.busy = true;
139-
140138
quickPick.busy = true;
141139
quickPick.canSelectMany = false;
142140
const items: QuickPickItem[] = [
143-
{
144-
label: "$(cloud) Serverless",
145-
detail: `Run files as Workflows or use Databricks Connect without a dedicated cluster`,
146-
alwaysShow: false,
147-
},
148141
{
149142
label: "$(repo-create) Create New Cluster",
150143
detail: `Open Databricks in the browser and create a new cluster`,
@@ -155,6 +148,15 @@ export class ConnectionCommands implements Disposable {
155148
kind: QuickPickItemKind.Separator,
156149
},
157150
];
151+
if (
152+
this.connectionManager.databricksWorkspace?.isServerlessEnabled
153+
) {
154+
items.unshift({
155+
label: "$(cloud) Serverless",
156+
detail: `Run files as Workflows or use Databricks Connect without a dedicated cluster`,
157+
alwaysShow: false,
158+
});
159+
}
158160
quickPick.items = items;
159161

160162
this.clusterModel.refresh();

packages/databricks-vscode/src/configuration/ConnectionManager.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,17 @@ export class ConnectionManager implements Disposable {
150150
}
151151

152152
private async updateServerless() {
153+
if (this.configModel.target === undefined) {
154+
return;
155+
}
153156
const serverless = await this.configModel.get("serverless");
154-
if (serverless) {
157+
const computeId = this.apiClient?.config.serverlessComputeId;
158+
const autoEnable =
159+
serverless === undefined &&
160+
!this.cluster &&
161+
computeId === "auto" &&
162+
this.databricksWorkspace?.isServerlessEnabled;
163+
if (serverless || autoEnable) {
155164
await this.enableServerless();
156165
} else {
157166
await this.disableServerless();

packages/databricks-vscode/src/configuration/DatabricksWorkspace.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,26 @@ describe(__filename, () => {
1616
const wsConf = {
1717
enableProjectTypeInWorkspace: "true",
1818
enableWorkspaceFilesystem: "dbr11.0+",
19+
enableServerless: true,
1920
} as const;
2021
const authProvider = new ProfileAuthProvider(
2122
new URL("https://fabian.databricks.com"),
2223
"DEFAULT",
2324
instance(mock(CliWrapper))
2425
);
2526
const dbWorkspace: DatabricksWorkspace = new DatabricksWorkspace(
27+
"workspace-id",
2628
authProvider,
2729
user,
2830
wsConf
2931
);
3032

3133
assert(dbWorkspace.host.toString() === host.toString());
3234
assert.equal(dbWorkspace.userName, user.userName);
35+
assert.equal(dbWorkspace.id, "workspace-id");
3336
assert(dbWorkspace.isFilesInReposEnabled);
3437
assert(dbWorkspace.isFilesInReposEnabled);
38+
assert(dbWorkspace.isServerlessEnabled);
3539

3640
assert(
3741
dbWorkspace.supportFilesInReposForCluster({

packages/databricks-vscode/src/configuration/DatabricksWorkspace.ts

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,23 @@ import {Loggers} from "../logger";
66
import {AuthProvider} from "./auth/AuthProvider";
77
import {RemoteUri} from "../sync/SyncDestination";
88

9+
type ServerlessEnablementResponse = {
10+
setting?: {
11+
value?: {
12+
// eslint-disable-next-line @typescript-eslint/naming-convention
13+
preview_enablement_val?: {
14+
enabled: boolean;
15+
};
16+
};
17+
};
18+
};
19+
920
export class DatabricksWorkspace {
1021
constructor(
22+
public readonly id: string,
1123
private _authProvider: AuthProvider,
1224
private me: iam.User,
13-
private wsConf: WorkspaceConfProps
25+
private wsConf: WorkspaceConfProps & {enableServerless?: boolean}
1426
) {}
1527

1628
/**
@@ -56,6 +68,10 @@ export class DatabricksWorkspace {
5668
return this.wsConf.enableWorkspaceFilesystem !== "false";
5769
}
5870

71+
get isServerlessEnabled(): boolean {
72+
return this.wsConf.enableServerless === true;
73+
}
74+
5975
supportFilesInReposForCluster(cluster: Cluster): boolean {
6076
if (!this.isReposEnabled || !this.isFilesInReposEnabled) {
6177
return false;
@@ -90,27 +106,36 @@ export class DatabricksWorkspace {
90106
@context ctx?: Context
91107
) {
92108
const me = await client.currentUser.me(ctx);
109+
// Workspace ID is returned in a header, which is then copied to the response object.
110+
const id = (me as any)["x-databricks-org-id"] as string;
93111

94112
const wsConfApi = new WorkspaceConf(client.apiClient);
95-
let state: WorkspaceConfProps = {
113+
let state: WorkspaceConfProps & {enableServerless?: boolean} = {
96114
enableProjectTypeInWorkspace: "true",
97115
enableWorkspaceFilesystem: "true",
98116
};
99117
try {
100-
state = {
101-
...state,
102-
...(await wsConfApi.getStatus(
103-
[
104-
"enableProjectTypeInWorkspace",
105-
"enableWorkspaceFilesystem",
106-
],
107-
ctx
108-
)),
109-
};
118+
const confStatus = await wsConfApi.getStatus(
119+
["enableProjectTypeInWorkspace", "enableWorkspaceFilesystem"],
120+
ctx
121+
);
122+
state = {...state, ...confStatus};
110123
} catch (e) {
111124
ctx?.logger?.error("Can't fetch workspace confs", e);
112125
}
126+
try {
127+
const serverlessEnablement = (await client.apiClient.request(
128+
`/api/2.0/settings-api/workspace/${id}/serverless_job_nb`,
129+
"GET"
130+
)) as ServerlessEnablementResponse;
131+
const enableServerless =
132+
serverlessEnablement?.setting?.value?.preview_enablement_val
133+
?.enabled === true;
134+
state = {...state, enableServerless};
135+
} catch (e) {
136+
ctx?.logger?.error("Can't detect serverless support", e);
137+
}
113138

114-
return new DatabricksWorkspace(authProvider, me, state);
139+
return new DatabricksWorkspace(id, authProvider, me, state);
115140
}
116141
}

packages/databricks-vscode/src/telemetry/constants.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ export class MetadataTypes {
239239
[Metadata.USER]: EventType<{
240240
hashedUserName: string;
241241
host: string;
242+
workspaceId: string;
242243
authType: AuthType;
243244
}> = {
244245
hashedUserName: {
@@ -248,6 +249,9 @@ export class MetadataTypes {
248249
comment:
249250
"The hostname of the workspace that the user is connected to",
250251
},
252+
workspaceId: {
253+
comment: "The id of the workspace",
254+
},
251255
authType: {
252256
comment: "The kind of authentication used by the user",
253257
},

packages/databricks-vscode/src/telemetry/index.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ describe(__filename, () => {
7777

7878
it("sets user metadata correctly after logged in", async () => {
7979
const ws = mock(DatabricksWorkspace);
80+
when(ws.id).thenReturn("workspace-id");
8081
when(ws.userName).thenReturn("[email protected]");
8182
when(ws.host).thenReturn(new URL("https://my.databricks.com"));
8283
const cm = mock(ConnectionManager);
@@ -110,6 +111,7 @@ describe(__filename, () => {
110111
"$2b$07$97f780c0d2a202b5f54aeOJ9MKnLacIH6dXoDUpQLfJXKjhYqxJLW",
111112
"user.host": "my.databricks.com",
112113
"user.authType": "azure-cli",
114+
"user.workspaceId": "workspace-id",
113115
});
114116
assert.deepEqual(metrics, {
115117
"event.duration": 100,

packages/databricks-vscode/src/telemetry/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ async function getDatabricksWorkspaceMetadata(
5757
return {
5858
hashedUserName: hashedUserName,
5959
host: databricksWorkspace.host.host,
60+
workspaceId: databricksWorkspace.id,
6061
};
6162
}
6263

vendor/databricks-sdk.tgz

127 Bytes
Binary file not shown.

yarn.lock

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ __metadata:
284284
linkType: hard
285285

286286
"@databricks/databricks-sdk@file:../../vendor/databricks-sdk.tgz::locator=%40databricks%2Fdatabricks-vscode-types%40workspace%3Apackages%2Fdatabricks-vscode-types":
287-
version: 0.7.0
287+
version: 0.8.0
288288
resolution: "@databricks/databricks-sdk@file:../../vendor/databricks-sdk.tgz::locator=%40databricks%2Fdatabricks-vscode-types%40workspace%3Apackages%2Fdatabricks-vscode-types"
289289
dependencies:
290290
"@types/ini": ^4.1.0
@@ -294,12 +294,12 @@ __metadata:
294294
ini: ^4.1.2
295295
reflect-metadata: ^0.2.1
296296
semver: ^7.6.0
297-
checksum: fc3186dc4dda2a06e01c8e7e20b5f76ec6d1b4379b65deb80cacfd506427f38841af890858bd3335c3ab76f8a7255c4f4ce295f6470d7d0905f236b211fa617b
297+
checksum: be59ab37615aa63780fdb841cdd6199f930710d409e29233abc2c66d8e5a7ac9928497bdf2f38075970e89e6ade0d9ae37ea39efcf721bd85f0c484c535f46d0
298298
languageName: node
299299
linkType: hard
300300

301301
"@databricks/databricks-sdk@file:../../vendor/databricks-sdk.tgz::locator=databricks%40workspace%3Apackages%2Fdatabricks-vscode":
302-
version: 0.7.0
302+
version: 0.8.0
303303
resolution: "@databricks/databricks-sdk@file:../../vendor/databricks-sdk.tgz::locator=databricks%40workspace%3Apackages%2Fdatabricks-vscode"
304304
dependencies:
305305
"@types/ini": ^4.1.0
@@ -309,7 +309,7 @@ __metadata:
309309
ini: ^4.1.2
310310
reflect-metadata: ^0.2.1
311311
semver: ^7.6.0
312-
checksum: fc3186dc4dda2a06e01c8e7e20b5f76ec6d1b4379b65deb80cacfd506427f38841af890858bd3335c3ab76f8a7255c4f4ce295f6470d7d0905f236b211fa617b
312+
checksum: be59ab37615aa63780fdb841cdd6199f930710d409e29233abc2c66d8e5a7ac9928497bdf2f38075970e89e6ade0d9ae37ea39efcf721bd85f0c484c535f46d0
313313
languageName: node
314314
linkType: hard
315315

@@ -1448,11 +1448,11 @@ __metadata:
14481448
linkType: hard
14491449

14501450
"@types/node@npm:^18.19.23":
1451-
version: 18.19.64
1452-
resolution: "@types/node@npm:18.19.64"
1451+
version: 18.19.75
1452+
resolution: "@types/node@npm:18.19.75"
14531453
dependencies:
14541454
undici-types: ~5.26.4
1455-
checksum: e7680215b03c9bee8a33947f03d06048e8e460f23b1b7b29c45350cf437faa5f8fcb7d8c3eb8dfec8427923e7a184df42bc710c1b6252b4852e3ed7064c6228f
1455+
checksum: 8f780a51a2dc1d597b104a2c33a2ab175fda492defbaab2cbb5fd098124d867ebed7cda0eaf80309bba25fbd4e41b4a04c91b7f14b50547b4377a39ccf749a7c
14561456
languageName: node
14571457
linkType: hard
14581458

@@ -2220,6 +2220,13 @@ __metadata:
22202220
languageName: node
22212221
linkType: hard
22222222

2223+
"agent-base@npm:^7.1.2":
2224+
version: 7.1.3
2225+
resolution: "agent-base@npm:7.1.3"
2226+
checksum: 87bb7ee54f5ecf0ccbfcba0b07473885c43ecd76cb29a8db17d6137a19d9f9cd443a2a7c5fd8a3f24d58ad8145f9eb49116344a66b107e1aeab82cf2383f4753
2227+
languageName: node
2228+
linkType: hard
2229+
22232230
"agentkeepalive@npm:^4.2.1":
22242231
version: 4.3.0
22252232
resolution: "agentkeepalive@npm:4.3.0"
@@ -5398,12 +5405,13 @@ __metadata:
53985405
linkType: hard
53995406

54005407
"gcp-metadata@npm:^6.1.0":
5401-
version: 6.1.0
5402-
resolution: "gcp-metadata@npm:6.1.0"
5408+
version: 6.1.1
5409+
resolution: "gcp-metadata@npm:6.1.1"
54035410
dependencies:
5404-
gaxios: ^6.0.0
5411+
gaxios: ^6.1.1
5412+
google-logging-utils: ^0.0.2
54055413
json-bigint: ^1.0.0
5406-
checksum: 55de8ae4a6b7664379a093abf7e758ae06e82f244d41bd58d881a470bf34db94c4067ce9e1b425d9455b7705636d5f8baad844e49bb73879c338753ba7785b2b
5414+
checksum: 7dffe884fd718482b559a841da469dc30e766a4b86c71cda96bed42579763d58f28328238b2eb424c29ba10ef45d4bb8a6586441921734f01012b55bbea79711
54075415
languageName: node
54085416
linkType: hard
54095417

@@ -5731,16 +5739,23 @@ __metadata:
57315739
linkType: hard
57325740

57335741
"google-auth-library@npm:^9.10.0":
5734-
version: 9.14.2
5735-
resolution: "google-auth-library@npm:9.14.2"
5742+
version: 9.15.1
5743+
resolution: "google-auth-library@npm:9.15.1"
57365744
dependencies:
57375745
base64-js: ^1.3.0
57385746
ecdsa-sig-formatter: ^1.0.11
57395747
gaxios: ^6.1.1
57405748
gcp-metadata: ^6.1.0
57415749
gtoken: ^7.0.0
57425750
jws: ^4.0.0
5743-
checksum: 64b3a6c1b1b14f1c891dbcfb850bc4db63dc8fae17e70197636244d00c83b539ac3da8688aae0bd1f09c884fc538d203945ae751edbabf666b41066385d86e30
5751+
checksum: 1c7660b7d21504a58b6b7780b0ca56f07a4d2b68d2ca14e5c4beaedd45cc4898baa8df1cfaf4dac15413a8db3cecc00e84662d8a327f9b9488ff2df7d8d23c84
5752+
languageName: node
5753+
linkType: hard
5754+
5755+
"google-logging-utils@npm:^0.0.2":
5756+
version: 0.0.2
5757+
resolution: "google-logging-utils@npm:0.0.2"
5758+
checksum: 270de74cde8abe0a6639b4bebbb6db2c7d8a495cf14b23779450d3d010e759f3ffcb7eb200b1bcb05da1897fa63f3e336df2274f02fc69d3bb388019fa2b3134
57445759
languageName: node
57455760
linkType: hard
57465761

@@ -6086,12 +6101,12 @@ __metadata:
60866101
linkType: hard
60876102

60886103
"https-proxy-agent@npm:^7.0.1":
6089-
version: 7.0.5
6090-
resolution: "https-proxy-agent@npm:7.0.5"
6104+
version: 7.0.6
6105+
resolution: "https-proxy-agent@npm:7.0.6"
60916106
dependencies:
6092-
agent-base: ^7.0.2
6107+
agent-base: ^7.1.2
60936108
debug: 4
6094-
checksum: 2e1a28960f13b041a50702ee74f240add8e75146a5c37fc98f1960f0496710f6918b3a9fe1e5aba41e50f58e6df48d107edd9c405c5f0d73ac260dabf2210857
6109+
checksum: b882377a120aa0544846172e5db021fa8afbf83fea2a897d397bd2ddd8095ab268c24bc462f40a15f2a8c600bf4aa05ce52927f70038d4014e68aefecfa94e8d
60956110
languageName: node
60966111
linkType: hard
60976112

@@ -9435,11 +9450,11 @@ __metadata:
94359450
linkType: hard
94369451

94379452
"semver@npm:^7.6.0":
9438-
version: 7.6.3
9439-
resolution: "semver@npm:7.6.3"
9453+
version: 7.7.1
9454+
resolution: "semver@npm:7.7.1"
94409455
bin:
94419456
semver: bin/semver.js
9442-
checksum: 4110ec5d015c9438f322257b1c51fe30276e5f766a3f64c09edd1d7ea7118ecbc3f379f3b69032bacf13116dc7abc4ad8ce0d7e2bd642e26b0d271b56b61a7d8
9457+
checksum: 586b825d36874007c9382d9e1ad8f93888d8670040add24a28e06a910aeebd673a2eb9e3bf169c6679d9245e66efb9057e0852e70d9daa6c27372aab1dda7104
94439458
languageName: node
94449459
linkType: hard
94459460

0 commit comments

Comments
 (0)