Skip to content

Commit 29474b3

Browse files
Use bundle for configuration and not project.json (#924)
## Changes * Select bundle target from configuration menu. If not selected, a default target will be selected (based on mode and `default=true` flags). * Load the configuration from the bundle for the selected target. * Users can override * **auth type**: triggers login flow with the selected auth type. * **cluster**: triggers cluster selector is logged in * workspace folder This does NOT use bundle to sync and run code. This is still handled by `databricks sync` and custom logic for running. ## Tests <!-- How is this tested? -->
1 parent 9a32556 commit 29474b3

File tree

16 files changed

+446
-768
lines changed

16 files changed

+446
-768
lines changed

packages/databricks-vscode-types/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ export interface PublicApi {
1212
connectionManager: {
1313
onDidChangeState: Event<ConnectionState>;
1414

15-
login(interactive?: boolean, force?: boolean): Promise<void>;
1615
waitForConnect(): Promise<void>;
1716

1817
get state(): ConnectionState;

packages/databricks-vscode/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,13 @@
211211
{
212212
"command": "databricks.call",
213213
"title": "Call",
214-
"enablement": "databricks.context.activated && databricks.context.loggedIn",
214+
"enablement": "databricks.context.activated",
215215
"category": "Databricks"
216216
},
217+
{
218+
"command": "databricks.internal.clearOverrides",
219+
"title": "Clear workspace overrides"
220+
},
217221
{
218222
"command": "databricks.notebookInitScript.verify",
219223
"title": "Verify Databricks notebook init scripts",
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
import {BundleSchema} from "./BundleSchema";
1+
export {type BundleSchema} from "./BundleSchema";
22

3+
import {BundleSchema} from "./BundleSchema";
34
export type BundleTarget = Required<BundleSchema>["targets"][string];

packages/databricks-vscode/src/cluster/ClusterManager.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,13 @@ export class ClusterManager implements Disposable {
1616

1717
private setInterval() {
1818
this.refreshTimer = setInterval(async () => {
19+
const oldState = this.cluster.state;
1920
await this.cluster.refresh();
20-
this.onChange(this.cluster.state);
21+
if (
22+
JSON.stringify(oldState) !== JSON.stringify(this.cluster.state)
23+
) {
24+
this.onChange(this.cluster.state);
25+
}
2126
}, this.refreshTimeout.toMillSeconds().value);
2227
}
2328

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

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,16 @@ import {StateStorage} from "../vscode-objs/StateStorage";
1414
import {WorkspaceFsAccessVerifier} from "../workspace-fs";
1515
import {FeatureManager} from "../feature-manager/FeatureManager";
1616
import {Telemetry} from "../telemetry";
17+
import {ConfigModel} from "./ConfigModel";
18+
import {expect} from "chai";
1719

1820
describe(__filename, () => {
1921
let connectionManagerMock: ConnectionManager;
2022
let disposables: Array<Disposable>;
2123
let onChangeClusterListener: (e: Cluster) => void;
2224
let onChangeSyncDestinationListener: (e: SyncDestinationMapper) => void;
2325
let sync: CodeSynchronizer;
24-
26+
let mockConfigModel: ConfigModel;
2527
beforeEach(() => {
2628
disposables = [];
2729
connectionManagerMock = mock(ConnectionManager);
@@ -56,6 +58,13 @@ describe(__filename, () => {
5658
dispose() {},
5759
});
5860
sync = instance(syncMock);
61+
62+
mockConfigModel = mock(ConfigModel);
63+
mockConfigModel.onDidChangeAny = () => {
64+
return {
65+
dispose() {},
66+
};
67+
};
5968
});
6069

6170
afterEach(() => {
@@ -74,7 +83,8 @@ describe(__filename, () => {
7483
instance(mock(StateStorage)),
7584
instance(mock(WorkspaceFsAccessVerifier)),
7685
instance(mock(FeatureManager<"debugging.dbconnect">)),
77-
instance(mock(Telemetry))
86+
instance(mock(Telemetry)),
87+
mockConfigModel
7888
);
7989
disposables.push(provider);
8090

@@ -98,7 +108,8 @@ describe(__filename, () => {
98108
instance(mock(StateStorage)),
99109
instance(mock(WorkspaceFsAccessVerifier)),
100110
instance(mock(FeatureManager<"debugging.dbconnect">)),
101-
instance(mock(Telemetry))
111+
instance(mock(Telemetry)),
112+
mockConfigModel
102113
);
103114
disposables.push(provider);
104115

@@ -122,16 +133,17 @@ describe(__filename, () => {
122133
instance(mock(StateStorage)),
123134
instance(mock(WorkspaceFsAccessVerifier)),
124135
instance(mock(FeatureManager<"debugging.dbconnect">)),
125-
instance(mock(Telemetry))
136+
instance(mock(Telemetry)),
137+
mockConfigModel
126138
);
127139
disposables.push(provider);
128140

129141
const children = await resolveProviderResult(provider.getChildren());
130142
assert(children);
131-
assert.equal(children.length, 0);
143+
assert.equal(children.length, 4);
132144
});
133145

134-
it("should return cluster children", async () => {
146+
it("should return children", async () => {
135147
const mockApiClient = mock(ApiClient);
136148
when(mockApiClient.host).thenResolve(
137149
new URL("https://www.example.com")
@@ -155,12 +167,13 @@ describe(__filename, () => {
155167
instance(mock(StateStorage)),
156168
instance(mock(WorkspaceFsAccessVerifier)),
157169
instance(mock(FeatureManager<"debugging.dbconnect">)),
158-
instance(mock(Telemetry))
170+
instance(mock(Telemetry)),
171+
mockConfigModel
159172
);
160173
disposables.push(provider);
161174

162175
const children = await resolveProviderResult(provider.getChildren());
163-
assert.deepEqual(children, [
176+
expect(children).to.include.deep.members([
164177
{
165178
collapsibleState: 2,
166179
contextValue: "workspace",

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

Lines changed: 70 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
} from "../workspace-fs";
2222
import {FeatureManager} from "../feature-manager/FeatureManager";
2323
import {Telemetry} from "../telemetry";
24+
import {ConfigModel} from "./ConfigModel";
2425

2526
export type ConfigurationTreeItem = TreeItem & {
2627
url?: string;
@@ -47,7 +48,8 @@ export class ConfigurationDataProvider
4748
private readonly stateStorage: StateStorage,
4849
private readonly wsfsAccessVerifier: WorkspaceFsAccessVerifier,
4950
private readonly featureManager: FeatureManager,
50-
private readonly telemetry: Telemetry
51+
private readonly telemetry: Telemetry,
52+
private readonly configModel: ConfigModel
5153
) {
5254
this.disposables.push(
5355
this.connectionManager.onDidChangeState(() => {
@@ -64,6 +66,9 @@ export class ConfigurationDataProvider
6466
}),
6567
this.wsfsAccessVerifier.onDidChangeState(() => {
6668
this._onDidChangeTreeData.fire();
69+
}),
70+
this.configModel.onDidChangeAny(() => {
71+
this._onDidChangeTreeData.fire();
6772
})
6873
);
6974

@@ -82,28 +87,65 @@ export class ConfigurationDataProvider
8287
element?: ConfigurationTreeItem | undefined
8388
): Promise<Array<ConfigurationTreeItem>> {
8489
switch (this.connectionManager.state) {
90+
case "DISCONNECTED":
8591
case "CONNECTED":
8692
break;
8793
case "CONNECTING":
8894
await this.connectionManager.waitForConnect();
8995
break;
90-
case "DISCONNECTED":
91-
return [];
9296
}
9397

9498
const cluster = this.connectionManager.cluster;
9599
const syncDestination = this.connectionManager.syncDestinationMapper;
96100

97101
if (!element) {
98102
const children: Array<ConfigurationTreeItem> = [];
99-
children.push({
100-
label: `Workspace`,
101-
iconPath: new ThemeIcon("account"),
102-
id: "WORKSPACE",
103-
collapsibleState: TreeItemCollapsibleState.Expanded,
104-
contextValue: "workspace",
105-
url: this.connectionManager.databricksWorkspace?.host?.toString(),
106-
});
103+
children.push(
104+
{
105+
label:
106+
this.configModel.target !== undefined
107+
? `Bundle Target - ${this.configModel.target}`
108+
: `Bundle Target - "None selected"`,
109+
id: "BUNDLE-TARGET",
110+
collapsibleState: TreeItemCollapsibleState.Expanded,
111+
contextValue: "bundleTarget",
112+
command: {
113+
title: "Call",
114+
command: "databricks.call",
115+
arguments: [
116+
async () => {
117+
const targets = await this.configModel
118+
.bundleConfigReaderWriter.targets;
119+
if (targets === undefined) {
120+
return;
121+
}
122+
123+
const selectedTarget =
124+
await window.showQuickPick(
125+
Object.keys(targets),
126+
{title: "Select bundle target"}
127+
);
128+
if (selectedTarget === undefined) {
129+
return;
130+
}
131+
const currentTarget = this.configModel.target;
132+
if (currentTarget !== selectedTarget) {
133+
this._onDidChangeTreeData.fire();
134+
}
135+
this.configModel.setTarget(selectedTarget);
136+
},
137+
],
138+
},
139+
},
140+
{
141+
label: `Workspace`,
142+
iconPath: new ThemeIcon("account"),
143+
id: "WORKSPACE",
144+
collapsibleState: TreeItemCollapsibleState.Expanded,
145+
contextValue: "workspace",
146+
url: this.connectionManager.databricksWorkspace?.host?.toString(),
147+
}
148+
);
107149

108150
if (cluster) {
109151
let contextValue:
@@ -362,6 +404,23 @@ export class ConfigurationDataProvider
362404
return children;
363405
}
364406

407+
if (element.id === "BUNDLE-TARGET") {
408+
if (this.configModel.target === undefined) {
409+
return [];
410+
} else {
411+
return [
412+
{
413+
label: "Host",
414+
description: await this.configModel.get("host"),
415+
},
416+
{
417+
label: "Mode",
418+
description: await this.configModel.get("mode"),
419+
},
420+
];
421+
}
422+
}
423+
365424
return [];
366425
}
367426

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export class ConnectionCommands implements Disposable {
104104
*/
105105
attachClusterCommand() {
106106
return async (cluster: Cluster) => {
107-
await this.connectionManager.attachCluster(cluster);
107+
await this.connectionManager.attachCluster(cluster.id);
108108
};
109109
}
110110

@@ -168,7 +168,7 @@ export class ConnectionCommands implements Disposable {
168168
const selectedItem = quickPick.selectedItems[0];
169169
if ("cluster" in selectedItem) {
170170
const cluster = selectedItem.cluster;
171-
await this.connectionManager.attachCluster(cluster);
171+
await this.connectionManager.attachCluster(cluster.id);
172172
} else {
173173
await UrlUtils.openExternal(
174174
`${

0 commit comments

Comments
 (0)