Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 0 additions & 19 deletions packages/databricks-sdk-js/src/auth/CredentialProvider.ts

This file was deleted.

110 changes: 107 additions & 3 deletions packages/databricks-vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,118 @@
"url": "https://github.com/databricks/databricks-vscode.git"
},
"activationEvents": [
"onCommand:databricks.helloWorld"
"onCommand:databricks.hello",
"onCommand:databricks.login",
"onCommand:databricks.logout",
"onCommand:databricks.configureProject",
"onCommand:databricks.openDatabricksConfigFile",
"onCommand:databricks.cluster.refresh",
"onCommand:databricks.cluster.filterByAll",
"onCommand:databricks.cluster.filterByMe",
"onCommand:databricks.cluster.filterByRunning",
"onView:clusterManager",
"onView:clusterList"
],
"main": "./dist/extension.js",
"contributes": {
"commands": [
{
"command": "databricks.helloWorld",
"title": "Hello World"
"command": "databricks.hello",
"title": "Databricks: Hello"
},
{
"command": "databricks.login",
"title": "Databricks: Login"
},
{
"command": "databricks.logout",
"title": "Databricks: Logout"
},
{
"command": "databricks.configureProject",
"icon": "$(gear)",
"title": "Databricks: Configure project"
},
{
"command": "databricks.openDatabricksConfigFile",
"title": "Databricks: Open Databricks configuration file"
},
{
"command": "databricks.cluster.filterByAll",
"title": "All"
},
{
"command": "databricks.cluster.filterByRunning",
"title": "Running"
},
{
"command": "databricks.cluster.filterByMe",
"title": "Created by me"
},
{
"command": "databricks.cluster.refresh",
"icon": "$(refresh)",
"title": "Refresh"
}
],
"viewsContainers": {
"activitybar": [
{
"id": "clusterManager",
"title": "Databricks Clusters",
"icon": "resources/light/logo.svg"
}
]
},
"views": {
"clusterManager": [
{
"id": "clusterList",
"name": "Clusters"
}
]
},
"viewsWelcome": [
{
"view": "clusterList",
"contents": "In order to connect to a cluster you first have to configure your Databricks workspace:\n[Configure Databricks](command:databricks.configureProject)\nTo learn more about how to use Databricks with VS Code [read our docs](https://github.com/databricks/databricks-vscode)."
}
],
"menus": {
"view/title": [
{
"when": "view == clusterList",
"group": "navigation@1",
"submenu": "databricks.cluster.filter"
},
{
"command": "databricks.cluster.refresh",
"when": "view == clusterList",
"group": "navigation@2"
},
{
"command": "databricks.configureProject",
"when": "view == clusterList",
"group": "navigation@3"
}
],
"databricks.cluster.filter": [
{
"command": "databricks.cluster.filterByAll"
},
{
"command": "databricks.cluster.filterByMe"
},
{
"command": "databricks.cluster.filterByRunning"
}
]
},
"submenus": [
{
"id": "databricks.cluster.filter",
"label": "Filter clusters ...",
"icon": "$(filter)"
}
]
},
Expand Down
1 change: 1 addition & 0 deletions packages/databricks-vscode/resources/dark/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions packages/databricks-vscode/resources/light/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 37 additions & 0 deletions packages/databricks-vscode/src/cli/CliWrapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import {execFile, ExecFileException, spawn} from "child_process";

/**
* Entrypoint for all wrapped CLI commands
*/
export class CliWrapper {
constructor() {}

async addProfile(
name: string,
host: URL,
token: string
): Promise<{stdout: string; stderr: string}> {
return new Promise((resolve, reject) => {
let child = spawn(
"databricks",
[
"configure",
"--profile",
name,
"--host",
host.href,
"--token",
],
{
stdio: ["pipe", 0, 0],
}
);

child.stdin!.write(token);
child.stdin!.end();

child.on("error", reject);
child.on("exit", resolve);
});
}
}
26 changes: 26 additions & 0 deletions packages/databricks-vscode/src/cluster/ClusterCommands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {ClusterFilter, ClusterModel} from "./ClusterModel";

/**
* Cluster related commands
*/
export class ClusterCommands {
constructor(private clusterModel: ClusterModel) {}

/**
* Refresh cluster tree view by reloading them throug the API
*/
refreshCommand() {
return () => {
this.clusterModel.refresh();
};
}

/**
* Command to filter clusters in the cluster tree view
*/
filterCommand(filter: ClusterFilter) {
return () => {
this.clusterModel.filter = filter;
};
}
}
164 changes: 164 additions & 0 deletions packages/databricks-vscode/src/cluster/ClusterListDataProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import {
Disposable,
Event,
EventEmitter,
ProviderResult,
ThemeIcon,
TreeDataProvider,
TreeItem,
TreeItemCollapsibleState,
} from "vscode";
import {ClusterModel, ClusterNode} from "./ClusterModel";

/**
* Data provider for the cluster tree view
*/
export class ClusterListDataProvider
implements TreeDataProvider<ClusterNode | TreeItem>, Disposable
{
private _onDidChangeTreeData: EventEmitter<
ClusterNode | TreeItem | undefined | void
> = new EventEmitter<ClusterNode | TreeItem | undefined | void>();
readonly onDidChangeTreeData: Event<
ClusterNode | TreeItem | undefined | void
> = this._onDidChangeTreeData.event;

private disposables: Array<Disposable>;

constructor(private model: ClusterModel) {
this.disposables = [
model.onDidChange(() => {
this._onDidChangeTreeData.fire();
}),
this.autoReload(5000),
];
}

dispose() {
this.disposables.forEach((d) => d.dispose());
}

getTreeItem(element: ClusterNode | TreeItem): TreeItem {
if (!this.isClusterNode(element)) {
return element;
}

let icon: ThemeIcon;
switch (element.state) {
case "RUNNING":
icon = new ThemeIcon("debug-start");
break;

case "RESTARTING":
case "PENDING":
case "RESIZING":
icon = new ThemeIcon("debug-restart");
break;

case "TERMINATING":
case "TERMINATED":
case "ERROR":
case "UNKNOWN":
icon = new ThemeIcon("debug-stop");
break;
}

return {
label: element.name,
iconPath: icon,
//description: `${formatSize(element.memoryMb)} MB | ${element.cores} Cores | ${element.sparkVersion}`,
id: element.id,
collapsibleState: TreeItemCollapsibleState.Collapsed,
contextValue:
element.state === "RUNNING"
? "clusterRunning"
: "clusterStopped",
};
}

private isClusterNode(
element: ClusterNode | TreeItem
): element is ClusterNode {
return (element as ClusterNode).state !== undefined;
}

private autoReload(refreshRateInMs: number): Disposable {
let interval = setInterval(() => {
this.model.refresh();
}, refreshRateInMs);
return {
dispose() {
clearInterval(interval);
},
};
}

getChildren(
element?: ClusterNode | TreeItem | undefined
): ProviderResult<Array<ClusterNode | TreeItem>> {
if (element) {
if (this.isClusterNode(element)) {
let children = [
{
label: "Cluster ID:",
description: element.id,
},
];
if (element.cores) {
children.push({
label: "Cores:",
description: element.cores + "",
});
}
if (element.memoryMb) {
children.push({
label: "Memory:",
description: formatSize(element.memoryMb),
});
}
children.push(
{
label: "Spark version:",
description: element.sparkVersion,
},
{
label: "State:",
description: element.state,
},
{
label: "Creator:",
description: element.creator,
}
);

if (element.stateMessage) {
children.push({
label: "State message:",
description: element.stateMessage,
});
}

return children;
} else {
return [];
}
} else {
return (async () => {
let roots = await this.model.roots;
if (roots && roots.length === 0) {
return [new TreeItem("No clusters found")];
} else {
return roots;
}
})();
}

function formatSize(sizeInMB: number): string {
if (sizeInMB > 1024) {
return Math.round(sizeInMB / 1024).toString() + " GB";
} else {
return `${sizeInMB} MB`;
}
}
}
}
Loading