diff --git a/extensions/azurecore/package.json b/extensions/azurecore/package.json
index 6d1df09577..58279589e1 100644
--- a/extensions/azurecore/package.json
+++ b/extensions/azurecore/package.json
@@ -261,6 +261,11 @@
"when": "viewItem == azure.resource.itemType.account",
"group": "inline"
},
+ {
+ "command": "azure.resource.connectsqlserver",
+ "when": "viewItem == azure.resource.itemType.azureDataExplorer",
+ "group": "inline"
+ },
{
"command": "azure.resource.startterminal",
"when": "viewItem == azure.resource.itemType.account",
diff --git a/extensions/azurecore/resources/dark/azureDE_inverse.svg b/extensions/azurecore/resources/dark/azureDE_inverse.svg
new file mode 100644
index 0000000000..e6f96e5442
--- /dev/null
+++ b/extensions/azurecore/resources/dark/azureDE_inverse.svg
@@ -0,0 +1,3 @@
+
diff --git a/extensions/azurecore/resources/light/azureDE.svg b/extensions/azurecore/resources/light/azureDE.svg
new file mode 100644
index 0000000000..d6caba532a
--- /dev/null
+++ b/extensions/azurecore/resources/light/azureDE.svg
@@ -0,0 +1,3 @@
+
diff --git a/extensions/azurecore/src/azureResource/commands.ts b/extensions/azurecore/src/azureResource/commands.ts
index 4c87827f6d..9da4ca33cc 100644
--- a/extensions/azurecore/src/azureResource/commands.ts
+++ b/extensions/azurecore/src/azureResource/commands.ts
@@ -167,7 +167,6 @@ export function registerAzureResourceCommands(appContext: AppContext, tree: Azur
});
vscode.commands.registerCommand('azure.resource.openInAzurePortal', async (connectionProfile: azdata.IConnectionProfile) => {
-
if (
!connectionProfile.azureResourceId ||
!connectionProfile.azurePortalEndpoint ||
diff --git a/extensions/azurecore/src/azureResource/constants.ts b/extensions/azurecore/src/azureResource/constants.ts
index aaeca8a73f..17b1070200 100644
--- a/extensions/azurecore/src/azureResource/constants.ts
+++ b/extensions/azurecore/src/azureResource/constants.ts
@@ -10,6 +10,8 @@ export enum AzureResourceItemType {
database = 'azure.resource.itemType.database',
databaseServerContainer = 'azure.resource.itemType.databaseServerContainer',
databaseServer = 'azure.resource.itemType.databaseServer',
+ azureDataExplorerContainer = 'azure.resource.itemType.azureDataExplorerContainer',
+ azureDataExplorer = 'azure.resource.itemType.azureDataExplorer',
sqlInstance = 'azure.resource.itemType.sqlInstance',
message = 'azure.resource.itemType.message'
}
diff --git a/extensions/azurecore/src/azureResource/providers/kusto/kustoProvider.ts b/extensions/azurecore/src/azureResource/providers/kusto/kustoProvider.ts
new file mode 100644
index 0000000000..6c78a62386
--- /dev/null
+++ b/extensions/azurecore/src/azureResource/providers/kusto/kustoProvider.ts
@@ -0,0 +1,26 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import { ExtensionContext } from 'vscode';
+
+import { azureResource } from '../../azure-resource';
+import { IAzureResourceService } from '../../interfaces';
+import { KustoTreeDataProvider as KustoTreeDataProvider } from './kustoTreeDataProvider';
+
+export class KustoProvider implements azureResource.IAzureResourceProvider {
+ public constructor(
+ private _service: IAzureResourceService,
+ private _extensionContext: ExtensionContext
+ ) {
+ }
+
+ public getTreeDataProvider(): azureResource.IAzureResourceTreeDataProvider {
+ return new KustoTreeDataProvider(this._service, this._extensionContext);
+ }
+
+ public get providerId(): string {
+ return 'azure.resource.providers.azureDataExplorer';
+ }
+}
diff --git a/extensions/azurecore/src/azureResource/providers/kusto/kustoService.ts b/extensions/azurecore/src/azureResource/providers/kusto/kustoService.ts
new file mode 100644
index 0000000000..8a83efb7cf
--- /dev/null
+++ b/extensions/azurecore/src/azureResource/providers/kusto/kustoService.ts
@@ -0,0 +1,34 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import { azureResource } from '../../azure-resource';
+import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
+
+export interface KustoGraphData extends GraphData {
+ properties: {
+ fullyQualifiedDomainName: string;
+ administratorLogin: string;
+ uri: string;
+ };
+}
+
+const instanceQuery = 'where type == "microsoft.kusto/clusters"';
+
+export class KustoResourceService extends ResourceServiceBase {
+
+ protected get query(): string {
+ return instanceQuery;
+ }
+
+ protected convertResource(resource: KustoGraphData): azureResource.AzureResourceDatabaseServer {
+ return {
+ id: resource.id,
+ name: resource.name,
+ fullName: resource.properties.uri.replace('https://', ''),
+ loginName: '',
+ defaultDatabaseName: ''
+ };
+ }
+}
diff --git a/extensions/azurecore/src/azureResource/providers/kusto/kustoTreeDataProvider.ts b/extensions/azurecore/src/azureResource/providers/kusto/kustoTreeDataProvider.ts
new file mode 100644
index 0000000000..46e8400642
--- /dev/null
+++ b/extensions/azurecore/src/azureResource/providers/kusto/kustoTreeDataProvider.ts
@@ -0,0 +1,77 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import { ExtensionNodeType, TreeItem, Account } from 'azdata';
+import { TreeItemCollapsibleState, ExtensionContext } from 'vscode';
+import * as nls from 'vscode-nls';
+const localize = nls.loadMessageBundle();
+
+import { AzureResourceItemType } from '../../constants';
+import { generateGuid } from '../../utils';
+import { IAzureResourceService } from '../../interfaces';
+import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
+import { azureResource } from '../../azure-resource';
+
+export class KustoTreeDataProvider extends ResourceTreeDataProviderBase {
+ private static readonly containerId = 'azure.resource.providers.KustoContainer';
+ private static readonly containerLabel = localize('azure.resource.providers.KustoContainerLabel', "Azure Data Explorer Clusters");
+
+ public constructor(
+ databaseServerService: IAzureResourceService,
+ private _extensionContext: ExtensionContext
+ ) {
+ super(databaseServerService);
+ }
+
+
+ protected getTreeItemForResource(databaseServer: azureResource.AzureResourceDatabaseServer, account: Account): TreeItem {
+ return {
+ id: `Kusto_${databaseServer.id ? databaseServer.id : databaseServer.name}`,
+ label: databaseServer.name,
+ iconPath: {
+ dark: this._extensionContext.asAbsolutePath('resources/dark/azureDE_inverse.svg'),
+ light: this._extensionContext.asAbsolutePath('resources/light/azureDE.svg')
+ },
+ collapsibleState: TreeItemCollapsibleState.Collapsed,
+ contextValue: AzureResourceItemType.azureDataExplorer,
+ payload: {
+ id: generateGuid(),
+ connectionName: undefined,
+ serverName: databaseServer.fullName,
+ databaseName: databaseServer.defaultDatabaseName,
+ userName: databaseServer.loginName,
+ password: '',
+ authenticationType: 'AzureMFA',
+ savePassword: true,
+ groupFullName: '',
+ groupId: '',
+ providerName: 'KUSTO',
+ saveProfile: false,
+ options: {},
+ azureAccount: account.key.accountId
+ },
+ childProvider: 'KUSTO',
+ type: ExtensionNodeType.Server
+ };
+ }
+
+ protected createContainerNode(): azureResource.IAzureResourceNode {
+ return {
+ account: undefined,
+ subscription: undefined,
+ tenantId: undefined,
+ treeItem: {
+ id: KustoTreeDataProvider.containerId,
+ label: KustoTreeDataProvider.containerLabel,
+ iconPath: {
+ dark: this._extensionContext.asAbsolutePath('resources/dark/folder_inverse.svg'),
+ light: this._extensionContext.asAbsolutePath('resources/light/folder.svg')
+ },
+ collapsibleState: TreeItemCollapsibleState.Collapsed,
+ contextValue: AzureResourceItemType.databaseServerContainer
+ }
+ };
+ }
+}
diff --git a/extensions/azurecore/src/extension.ts b/extensions/azurecore/src/extension.ts
index 196e22aadd..49acf85c5c 100644
--- a/extensions/azurecore/src/extension.ts
+++ b/extensions/azurecore/src/extension.ts
@@ -26,6 +26,8 @@ import { registerAzureResourceCommands } from './azureResource/commands';
import { AzureResourceTreeProvider } from './azureResource/tree/treeProvider';
import { SqlInstanceResourceService } from './azureResource/providers/sqlinstance/sqlInstanceService';
import { SqlInstanceProvider } from './azureResource/providers/sqlinstance/sqlInstanceProvider';
+import { KustoResourceService } from './azureResource/providers/kusto/kustoService';
+import { KustoProvider } from './azureResource/providers/kusto/kustoProvider';
import { PostgresServerProvider } from './azureResource/providers/postgresServer/postgresServerProvider';
import { PostgresServerService } from './azureResource/providers/postgresServer/postgresServerService';
import { AzureTerminalService } from './azureResource/services/terminalService';
@@ -92,6 +94,7 @@ export async function activate(context: vscode.ExtensionContext): Promise