Skip to content

Commit a3c5f14

Browse files
Use a tree representation to structure resource explorer UI components (#1029)
## Changes * Use a recursive tree representation for bundle resource expliorer UI components. This allows us to better structure UI components than the renderer based approach. * Add deeplinks for all bundle resources and run statuses. ## Tests <!-- How is this tested? -->
1 parent 0035539 commit a3c5f14

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1037
-796
lines changed

packages/databricks-vscode/package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,11 @@
392392
"when": "view == configurationView && viewItem =~ /^databricks.configuration.(cluster|sync).*$/",
393393
"group": "inline@1"
394394
},
395+
{
396+
"command": "databricks.utils.openExternal",
397+
"when": "viewItem =~ /^databricks.*\\.(has-url).*$/",
398+
"group": "inline@1"
399+
},
395400
{
396401
"command": "databricks.connection.attachCluster",
397402
"when": "view == clusterView",
@@ -429,7 +434,7 @@
429434
},
430435
{
431436
"command": "databricks.bundle.cancelRun",
432-
"when": "view == dabsResourceExplorerView && viewItem =~ /^databricks.bundle.*.running.*$/",
437+
"when": "view == dabsResourceExplorerView && viewItem =~ /^databricks.bundle.*.cancellable.*$/",
433438
"group": "inline@0"
434439
}
435440
],

packages/databricks-vscode/src/bundle/models/BundleRemoteStateModel.ts

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,31 @@ import {CliWrapper} from "../../cli/CliWrapper";
33
import {BaseModelWithStateCache} from "../../configuration/models/BaseModelWithStateCache";
44
import {Mutex} from "../../locking";
55

6-
import {BundleTarget} from "../types";
6+
import {BundleTarget, Resource, ResourceKey, Resources} from "../types";
77
import {AuthProvider} from "../../configuration/auth/AuthProvider";
88
import lodash from "lodash";
99
import {WorkspaceConfigs} from "../../vscode-objs/WorkspaceConfigs";
10-
import {withLogContext} from "@databricks/databricks-sdk/dist/logging";
10+
import {logging} from "@databricks/databricks-sdk";
1111
import {Loggers} from "../../logger";
1212
import {Context, context} from "@databricks/databricks-sdk";
13+
import {BundleValidateModel} from "./BundleValidateModel";
1314

1415
/* eslint-disable @typescript-eslint/naming-convention */
15-
type Resources = Required<BundleTarget>["resources"];
16-
export type Resource<K extends keyof Required<Resources>> =
17-
Required<Resources>[K];
18-
16+
export type BundleResourceModifiedStatus = "created" | "deleted" | "updated";
1917
export type BundleRemoteState = BundleTarget & {
20-
resources?: Resources & {
21-
[r in keyof Resources]?: {
22-
[k in keyof Resource<r>]?: Resource<r>[k] & {
18+
resources?: Resources<BundleTarget> & {
19+
[r in ResourceKey<BundleTarget>]?: {
20+
[k in keyof Required<Resources<BundleTarget>>[r]]?: Resource<
21+
BundleTarget,
22+
r
23+
> & {
2324
id?: string;
24-
modified_status?: "CREATED" | "DELETED" | "UPDATED";
25+
modified_status?: BundleResourceModifiedStatus;
2526
};
2627
};
2728
};
2829
};
2930

30-
export type ResourceType = keyof Resources;
31-
3231
/* eslint-enable @typescript-eslint/naming-convention */
3332

3433
export class BundleRemoteStateModel extends BaseModelWithStateCache<BundleRemoteState> {
@@ -40,9 +39,13 @@ export class BundleRemoteStateModel extends BaseModelWithStateCache<BundleRemote
4039
constructor(
4140
private readonly cli: CliWrapper,
4241
private readonly workspaceFolder: Uri,
43-
private readonly workspaceConfigs: WorkspaceConfigs
42+
private readonly workspaceConfigs: WorkspaceConfigs,
43+
private readonly bundleValidateModel: BundleValidateModel
4444
) {
4545
super();
46+
this.bundleValidateModel.onDidChange(async () => {
47+
this.refresh();
48+
});
4649
}
4750

4851
public async refresh() {
@@ -88,7 +91,7 @@ export class BundleRemoteStateModel extends BaseModelWithStateCache<BundleRemote
8891
);
8992
}
9093

91-
@withLogContext(Loggers.Extension)
94+
@logging.withLogContext(Loggers.Extension)
9295
public init(@context ctx?: Context) {
9396
this.refreshInterval = setInterval(async () => {
9497
try {

packages/databricks-vscode/src/bundle/run/BundleRunStatus.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import {EventEmitter} from "vscode";
2-
import {ResourceType} from "../models/BundleRemoteStateModel";
32
import {RunState} from "./types";
3+
import {ResourceKey} from "../types";
4+
import {BundleRemoteState} from "../models/BundleRemoteStateModel";
45

56
export abstract class BundleRunStatus {
6-
abstract readonly type: ResourceType;
7+
abstract readonly type: ResourceKey<BundleRemoteState>;
78
protected readonly onDidChangeEmitter = new EventEmitter<void>();
89
readonly onDidChange = this.onDidChangeEmitter.event;
910
runId: string | undefined;

packages/databricks-vscode/src/bundle/run/BundleRunStatusManager.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import {Disposable, EventEmitter} from "vscode";
22
import {
3+
BundleRemoteState,
34
BundleRemoteStateModel,
4-
Resource,
5-
ResourceType,
65
} from "../models/BundleRemoteStateModel";
76
import {BundleRunTerminalManager} from "./BundleRunTerminalManager";
87
import {JobRunStatus} from "./JobRunStatus";
98
import {AuthProvider} from "../../configuration/auth/AuthProvider";
109
import {BundleRunStatus} from "./BundleRunStatus";
1110
import {PipelineRunStatus} from "./PipelineRunStatus";
11+
import {Resource, ResourceKey} from "../types";
1212
/**
1313
* This class monitors the cli bundle run output and record ids for runs. It also polls for status of the these runs.
1414
*/
@@ -26,15 +26,17 @@ export class BundleRunStatusManager implements Disposable {
2626

2727
getRunStatusMonitor(
2828
resourceKey: string,
29-
resourceType: ResourceType,
29+
resourceType: ResourceKey<BundleRemoteState>,
3030
authProvider: AuthProvider,
3131
resource: any
3232
): BundleRunStatus {
3333
switch (resourceType) {
3434
case "jobs":
3535
return new JobRunStatus(authProvider);
3636
case "pipelines": {
37-
const id = (resource as Resource<"pipelines">[string]).id;
37+
const id = (
38+
resource as Resource<BundleRemoteState, "pipelines">
39+
).id;
3840
if (id === undefined) {
3941
throw new Error(
4042
`Pipeline id is undefined for ${resourceKey}. This likely means the pipeline is not deployed.`
@@ -48,7 +50,10 @@ export class BundleRunStatusManager implements Disposable {
4850
}
4951
}
5052

51-
async run(resourceKey: string, resourceType: ResourceType) {
53+
async run(
54+
resourceKey: string,
55+
resourceType: ResourceKey<BundleRemoteState>
56+
) {
5257
const target = this.bundleRemoteStateModel.target;
5358
const authProvider = this.bundleRemoteStateModel.authProvider;
5459
const resource =

packages/databricks-vscode/src/bundle/run/JobRunStatus.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import {
33
JobsError,
44
JobsRetriableError,
5+
Run,
56
} from "@databricks/databricks-sdk/dist/apis/jobs";
67
import {Event, EventEmitter} from "vscode";
78
import {AuthProvider} from "../../configuration/auth/AuthProvider";
@@ -10,7 +11,7 @@ import {BundleRunStatus} from "./BundleRunStatus";
1011

1112
export class JobRunStatus extends BundleRunStatus {
1213
readonly type = "jobs";
13-
14+
data: Run | undefined;
1415
private readonly onDidCompleteEmitter = new EventEmitter<void>();
1516
onDidComplete: Event<void> = this.onDidCompleteEmitter.event;
1617

packages/databricks-vscode/src/bundle/run/PipelineRunStatus.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
import {BundleRunStatus} from "./BundleRunStatus";
33
import {AuthProvider} from "../../configuration/auth/AuthProvider";
44
import {onError} from "../../utils/onErrorDecorator";
5-
import {UpdateInfoState} from "@databricks/databricks-sdk/dist/apis/pipelines";
5+
import {pipelines} from "@databricks/databricks-sdk";
66

7-
function isRunning(status?: UpdateInfoState) {
7+
function isRunning(status?: pipelines.UpdateInfoState) {
88
if (status === undefined) {
99
return false;
1010
}
@@ -14,7 +14,7 @@ function isRunning(status?: UpdateInfoState) {
1414
export class PipelineRunStatus extends BundleRunStatus {
1515
readonly type = "pipelines";
1616
private interval?: NodeJS.Timeout;
17-
17+
data: pipelines.GetUpdateResponse | undefined;
1818
constructor(
1919
private readonly authProvider: AuthProvider,
2020
private readonly pipelineId: string

packages/databricks-vscode/src/bundle/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,8 @@ export {type BundleSchema} from "./BundleSchema";
22
import {BundleSchema} from "./BundleSchema";
33

44
export type BundleTarget = Required<BundleSchema>["targets"][string];
5+
export type Resources<T> = T extends {resources?: infer D} ? D : never;
6+
export type ResourceKey<T> = keyof Resources<T>;
7+
export type Resource<T, K extends ResourceKey<T>> = Required<
8+
Resources<T>
9+
>[K][keyof Required<Resources<T>>[K]];

packages/databricks-vscode/src/cli/SyncTasks.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ describe(__filename, () => {
6666
)
6767
);
6868
when(mockDbWorkspace.host).thenReturn(
69-
Uri.parse("https://000000000000.00.azuredatabricks.net/")
69+
new URL("https://000000000000.00.azuredatabricks.net/")
7070
);
7171

7272
const mockSyncDestination = mock(SyncDestinationMapper);

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {WorkspaceClient, iam, logging} from "@databricks/databricks-sdk";
22
import {Cluster, WorkspaceConf, WorkspaceConfProps} from "../sdk-extensions";
3-
import {Context, context} from "@databricks/databricks-sdk/dist/context";
3+
import {context, Context} from "@databricks/databricks-sdk";
44
import {Uri, window, env} from "vscode";
55
import {Loggers} from "../logger";
66
import {workspaceConfigs} from "../vscode-objs/WorkspaceConfigs";
@@ -36,8 +36,8 @@ export class DatabricksWorkspace {
3636
);
3737
}
3838

39-
get host(): Uri {
40-
return Uri.parse(this._authProvider.host.toString());
39+
get host(): URL {
40+
return this._authProvider.host;
4141
}
4242

4343
get authProvider(): AuthProvider {

packages/databricks-vscode/src/extension.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ import {OverrideableConfigModel} from "./configuration/models/OverrideableConfig
5858
import {BundlePreValidateModel} from "./bundle/models/BundlePreValidateModel";
5959
import {BundleRemoteStateModel} from "./bundle/models/BundleRemoteStateModel";
6060
import {BundleResourceExplorerTreeDataProvider} from "./ui/bundle-resource-explorer/BundleResourceExplorerTreeDataProvider";
61-
import {BundleCommands} from "./bundle/BundleCommands";
61+
import {BundleCommands} from "./ui/bundle-resource-explorer/BundleCommands";
6262
import {BundleRunTerminalManager} from "./bundle/run/BundleRunTerminalManager";
6363
import {BundleRunStatusManager} from "./bundle/run/BundleRunStatusManager";
6464
import {BundleProjectManager} from "./bundle/BundleProjectManager";
@@ -185,7 +185,8 @@ export async function activate(
185185
const bundleRemoteStateModel = new BundleRemoteStateModel(
186186
cli,
187187
workspaceUri,
188-
workspaceConfigs
188+
workspaceConfigs,
189+
bundleValidateModel
189190
);
190191
const configModel = new ConfigModel(
191192
bundleValidateModel,
@@ -532,13 +533,13 @@ export async function activate(
532533
new BundleResourceExplorerTreeDataProvider(
533534
configModel,
534535
bundleRunStatusManager,
535-
context
536+
context,
537+
connectionManager
536538
);
537539

538540
const bundleCommands = new BundleCommands(
539541
bundleRemoteStateModel,
540-
bundleRunStatusManager,
541-
bundleFileWatcher
542+
bundleRunStatusManager
542543
);
543544
context.subscriptions.push(
544545
bundleResourceExplorerTreeDataProvider,

0 commit comments

Comments
 (0)