mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-13 17:22:15 -05:00
Introduce Universal resource provider to fix ARM throttling issues (#23078)
This commit is contained in:
@@ -34,4 +34,33 @@ export enum AzureResourceServiceNames {
|
||||
terminalService = 'AzureTerminalService',
|
||||
}
|
||||
|
||||
export enum AzureResourcePrefixes {
|
||||
logAnalytics = 'LogAnalytics_',
|
||||
cosmosdb = 'Cosmosdb_',
|
||||
database = 'database_',
|
||||
databaseServer = 'databaseServer_',
|
||||
kusto = 'Kusto_',
|
||||
mySqlFlexibleServer = 'mySqlFlexibleServer_',
|
||||
postgresServerArc = 'postgresServerArc_',
|
||||
postgresServer = 'postgresServer_',
|
||||
sqlInstance = 'sqlInstance_',
|
||||
sqlInstanceArc = 'sqlInstanceArc_',
|
||||
synapseSqlPool = 'synapseSqlPool_',
|
||||
synapseWorkspace = 'synapseWorkspace_'
|
||||
}
|
||||
|
||||
export const mssqlProvider = 'MSSQL';
|
||||
export const logAnalyticsProvider = 'LOGANALYTICS';
|
||||
export const cosmosDBProvider = 'COSMOSDB_MONGO';
|
||||
export const kustoProvider = 'KUSTO';
|
||||
export const mySqlProvider = 'MySQL';
|
||||
export const pgsqlProvider = 'PGSQL';
|
||||
|
||||
// Kinds
|
||||
export const analyticsKind = 'v12.0,analytics';
|
||||
export const mongoDbKind = 'MongoDB';
|
||||
|
||||
export enum ResourceCategory {
|
||||
Server = 0,
|
||||
Database = 1
|
||||
}
|
||||
|
||||
@@ -3,10 +3,126 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as msRest from '@azure/ms-rest-js';
|
||||
|
||||
import { AzureAccount, Tenant, azureResource } from 'azurecore';
|
||||
|
||||
export interface GraphData {
|
||||
subscriptionId: string,
|
||||
subscriptionName?: string,
|
||||
tenantId: string;
|
||||
id: string;
|
||||
name: string;
|
||||
location: string;
|
||||
type: string;
|
||||
resourceGroup: string;
|
||||
}
|
||||
|
||||
export interface AzureMonitorGraphData extends GraphData {
|
||||
properties: {
|
||||
fullyQualifiedDomainName: string;
|
||||
administratorLogin: string;
|
||||
uri: string;
|
||||
customerId: string
|
||||
};
|
||||
}
|
||||
|
||||
export interface SqlInstanceArcGraphData extends GraphData {
|
||||
properties: {
|
||||
admin: string;
|
||||
hybridDataManager: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface PostgresArcServerGraphData extends GraphData {
|
||||
properties: {
|
||||
admin: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface DatabaseGraphData extends GraphData {
|
||||
kind: string;
|
||||
}
|
||||
|
||||
export interface SynapseGraphData extends GraphData {
|
||||
kind: string;
|
||||
}
|
||||
|
||||
export interface DbServerGraphData extends GraphData {
|
||||
properties: {
|
||||
fullyQualifiedDomainName: string;
|
||||
administratorLogin: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface KustoGraphData extends GraphData {
|
||||
properties: {
|
||||
fullyQualifiedDomainName: string;
|
||||
administratorLogin: string;
|
||||
uri: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface SqlInstanceGraphData extends GraphData {
|
||||
properties: {
|
||||
fullyQualifiedDomainName: string;
|
||||
administratorLogin: string;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Properties combined from all providers to create a universal interface that can be translated to any resource provider.
|
||||
*/
|
||||
export interface UniversalGraphData extends GraphData {
|
||||
kind?: string,
|
||||
properties?: {
|
||||
/**
|
||||
* SQL connectivity endpoint and other endpoints are found here, instead of fullyQualifiedDomainName.
|
||||
*/
|
||||
connectivityEndpoints?: { sql: string };
|
||||
/**
|
||||
* managedResourceGroupName is the resource group used by any SQL pools inside the workspace
|
||||
* which is different from the resource group of the workspace itself.
|
||||
*/
|
||||
managedResourceGroupName?: string;
|
||||
/**
|
||||
* administratorLogin is called sqlAdministratorLogin for Synapse.
|
||||
*/
|
||||
sqlAdministratorLogin?: string;
|
||||
|
||||
admin?: string;
|
||||
|
||||
hybridDataManager?: string;
|
||||
|
||||
fullyQualifiedDomainName?: string;
|
||||
|
||||
administratorLogin?: string;
|
||||
|
||||
uri?: string;
|
||||
|
||||
customerId?: string
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Properties returned by the Synapse query are different from the server ones and have to be treated differently.
|
||||
*/
|
||||
export interface SynapseWorkspaceGraphData extends GraphData {
|
||||
properties: {
|
||||
/**
|
||||
* SQL connectivity endpoint and other endpoints are found here, instead of fullyQualifiedDomainName.
|
||||
*/
|
||||
connectivityEndpoints: { sql: string };
|
||||
/**
|
||||
* managedResourceGroupName is the resource group used by any SQL pools inside the workspace
|
||||
* which is different from the resource group of the workspace itself.
|
||||
*/
|
||||
managedResourceGroupName: string;
|
||||
/**
|
||||
* administratorLogin is called sqlAdministratorLogin here.
|
||||
*/
|
||||
sqlAdministratorLogin: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface IAzureResourceSubscriptionService {
|
||||
/**
|
||||
* Gets subscriptions for the given account. Any errors that occur while fetching the subscriptions for each tenant
|
||||
@@ -41,6 +157,10 @@ export interface IAzureResourceNodeWithProviderId {
|
||||
resourceNode: azureResource.IAzureResourceNode;
|
||||
}
|
||||
|
||||
export interface IAzureResourceService<T extends azureResource.AzureResource> {
|
||||
getResources(subscriptions: azureResource.AzureResourceSubscription[], credential: msRest.ServiceClientCredentials, account: AzureAccount): Promise<T[]>;
|
||||
export interface IAzureResourceDbService<S extends GraphData, T extends GraphData> extends azureResource.IAzureResourceService {
|
||||
convertDatabaseResource(resource: T, server?: S): azureResource.AzureResource | undefined;
|
||||
}
|
||||
|
||||
export interface IAzureResourceServerService<T extends GraphData> extends azureResource.IAzureResourceService {
|
||||
convertServerResource(resource: T): azureResource.AzureResource | undefined;
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 'azurecore';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { AzureMonitorTreeDataProvider as AzureMonitorTreeDataProvider } from './azuremonitorTreeDataProvider';
|
||||
|
||||
export class AzureMonitorProvider implements azureResource.IAzureResourceProvider {
|
||||
public constructor(
|
||||
private _service: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
|
||||
private _extensionContext: ExtensionContext
|
||||
) {
|
||||
}
|
||||
|
||||
public getTreeDataProvider(): azureResource.IAzureResourceTreeDataProvider {
|
||||
return new AzureMonitorTreeDataProvider(this._service, this._extensionContext);
|
||||
}
|
||||
|
||||
public get providerId(): string {
|
||||
return 'azure.resource.providers.azureMonitor';
|
||||
}
|
||||
}
|
||||
@@ -5,27 +5,18 @@
|
||||
|
||||
import { azureResource } from 'azurecore';
|
||||
import { logAnalyticsQuery } from '../queryStringConstants';
|
||||
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
|
||||
import { ResourceServiceBase } from '../resourceTreeDataProviderBase';
|
||||
import { AzureMonitorGraphData } from '../../interfaces';
|
||||
import { AZURE_MONITOR_PROVIDER_ID } from '../../../constants';
|
||||
|
||||
export interface AzureMonitorGraphData extends GraphData {
|
||||
properties: {
|
||||
fullyQualifiedDomainName: string;
|
||||
administratorLogin: string;
|
||||
uri: string;
|
||||
customerId: string
|
||||
};
|
||||
}
|
||||
export class AzureMonitorResourceService extends ResourceServiceBase<AzureMonitorGraphData> {
|
||||
public override queryFilter: string = logAnalyticsQuery;
|
||||
|
||||
export class AzureMonitorResourceService extends ResourceServiceBase<AzureMonitorGraphData, azureResource.AzureResourceDatabaseServer> {
|
||||
|
||||
protected get query(): string {
|
||||
return logAnalyticsQuery;
|
||||
}
|
||||
|
||||
protected convertResource(resource: AzureMonitorGraphData): azureResource.AzureResourceDatabaseServer {
|
||||
public convertServerResource(resource: AzureMonitorGraphData): azureResource.AzureResourceDatabaseServer {
|
||||
return {
|
||||
id: resource.id,
|
||||
name: resource.name,
|
||||
provider: AZURE_MONITOR_PROVIDER_ID,
|
||||
fullName: resource.properties.customerId,
|
||||
loginName: '',
|
||||
defaultDatabaseName: '',
|
||||
|
||||
@@ -8,27 +8,26 @@ import { TreeItemCollapsibleState, ExtensionContext } from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
import { AzureResourceItemType } from '../../constants';
|
||||
import { AzureResourceItemType, AzureResourcePrefixes, logAnalyticsProvider } from '../../constants';
|
||||
import { generateGuid } from '../../utils';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { AzureMonitorGraphData, GraphData } from '../../interfaces';
|
||||
import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
|
||||
import { AzureAccount, azureResource } from 'azurecore';
|
||||
|
||||
export class AzureMonitorTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> {
|
||||
export class AzureMonitorTreeDataProvider extends ResourceTreeDataProviderBase<GraphData, AzureMonitorGraphData> {
|
||||
private static readonly containerId = 'azure.resource.providers.AzureMonitorContainer';
|
||||
private static readonly containerLabel = localize('azure.resource.providers.AzureMonitorContainerLabel', "Log Analytics workspace");
|
||||
|
||||
public constructor(
|
||||
databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
|
||||
databaseServerService: azureResource.IAzureResourceService,
|
||||
private _extensionContext: ExtensionContext
|
||||
) {
|
||||
super(databaseServerService);
|
||||
}
|
||||
|
||||
|
||||
protected getTreeItemForResource(databaseServer: azureResource.AzureResourceDatabaseServer, account: AzureAccount): TreeItem {
|
||||
public getTreeItemForResource(databaseServer: azureResource.AzureResourceDatabaseServer, account: AzureAccount): TreeItem {
|
||||
return {
|
||||
id: `LogAnalytics_${databaseServer.id ? databaseServer.id : databaseServer.name}`,
|
||||
id: `${AzureResourcePrefixes.logAnalytics}${account.key.accountId}${databaseServer.id ? databaseServer.id : databaseServer.name}`,
|
||||
label: this.browseConnectionMode ? `${databaseServer.name} (${AzureMonitorTreeDataProvider.containerLabel}, ${databaseServer.subscription.name})` : databaseServer.name,
|
||||
iconPath: {
|
||||
dark: this._extensionContext.asAbsolutePath('resources/dark/azure_monitor_dark.svg'),
|
||||
@@ -47,7 +46,7 @@ export class AzureMonitorTreeDataProvider extends ResourceTreeDataProviderBase<a
|
||||
savePassword: true,
|
||||
groupFullName: '',
|
||||
groupId: '',
|
||||
providerName: 'LOGANALYTICS',
|
||||
providerName: logAnalyticsProvider,
|
||||
saveProfile: false,
|
||||
options: {},
|
||||
azureAccount: account.key.accountId,
|
||||
@@ -55,7 +54,7 @@ export class AzureMonitorTreeDataProvider extends ResourceTreeDataProviderBase<a
|
||||
azureResourceId: databaseServer.id,
|
||||
azurePortalEndpoint: account.properties.providerSettings.settings.portalEndpoint
|
||||
},
|
||||
childProvider: 'LOGANALYTICS',
|
||||
childProvider: logAnalyticsProvider,
|
||||
type: ExtensionNodeType.Server
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 'azurecore';
|
||||
import { IAzureResourceService } from '../../../interfaces';
|
||||
import { CosmosDbMongoTreeDataProvider } from './cosmosDbMongoTreeDataProvider';
|
||||
|
||||
export class CosmosDbMongoProvider implements azureResource.IAzureResourceProvider {
|
||||
public constructor(
|
||||
private _databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
|
||||
private _extensionContext: ExtensionContext
|
||||
) {
|
||||
}
|
||||
|
||||
public getTreeDataProvider(): azureResource.IAzureResourceTreeDataProvider {
|
||||
return new CosmosDbMongoTreeDataProvider(this._databaseServerService, this._extensionContext);
|
||||
}
|
||||
|
||||
public get providerId(): string {
|
||||
return 'azure.resource.providers.cosmosDbMongo';
|
||||
}
|
||||
}
|
||||
@@ -4,28 +4,20 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
import { ResourceServiceBase, GraphData } from '../../resourceTreeDataProviderBase';
|
||||
import { ResourceServiceBase } from '../../resourceTreeDataProviderBase';
|
||||
import { azureResource } from 'azurecore';
|
||||
import { cosmosMongoDbQuery } from '../../queryStringConstants';
|
||||
import { DbServerGraphData } from '../../../interfaces';
|
||||
import { COSMOSDB_MONGO_PROVIDER_ID } from '../../../../constants';
|
||||
|
||||
export class CosmosDbMongoService extends ResourceServiceBase<DbServerGraphData> {
|
||||
public override queryFilter: string = cosmosMongoDbQuery;
|
||||
|
||||
interface DbServerGraphData extends GraphData {
|
||||
properties: {
|
||||
fullyQualifiedDomainName: string;
|
||||
administratorLogin: string;
|
||||
};
|
||||
}
|
||||
|
||||
export class CosmosDbMongoService extends ResourceServiceBase<DbServerGraphData, azureResource.AzureResourceDatabaseServer> {
|
||||
|
||||
protected get query(): string {
|
||||
return cosmosMongoDbQuery;
|
||||
}
|
||||
|
||||
protected convertResource(resource: DbServerGraphData): azureResource.AzureResourceDatabaseServer {
|
||||
public convertServerResource(resource: DbServerGraphData): azureResource.AzureResourceDatabaseServer | undefined {
|
||||
return {
|
||||
id: resource.id,
|
||||
name: resource.name,
|
||||
provider: COSMOSDB_MONGO_PROVIDER_ID,
|
||||
fullName: resource.properties.fullyQualifiedDomainName,
|
||||
loginName: resource.properties.administratorLogin,
|
||||
defaultDatabaseName: '',
|
||||
|
||||
@@ -7,28 +7,27 @@ import { TreeItemCollapsibleState, ExtensionContext } from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
import { AzureResourceItemType } from '../../../constants';
|
||||
import { AzureResourceItemType, AzureResourcePrefixes, cosmosDBProvider } from '../../../constants';
|
||||
import { generateGuid } from '../../../utils';
|
||||
import { IAzureResourceService } from '../../../interfaces';
|
||||
import { DbServerGraphData, GraphData } from '../../../interfaces';
|
||||
import { ResourceTreeDataProviderBase } from '../../resourceTreeDataProviderBase';
|
||||
import { AzureAccountProperties, azureResource } from 'azurecore';
|
||||
import * as azdata from 'azdata';
|
||||
|
||||
export class CosmosDbMongoTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> {
|
||||
private static readonly COSMOSDG_MONGO_PROVIDER_ID = 'COSMOSDB_MONGO';
|
||||
export class CosmosDbMongoTreeDataProvider extends ResourceTreeDataProviderBase<GraphData, DbServerGraphData> {
|
||||
private static readonly CONTAINER_ID = 'azure.resource.providers.databaseServer.treeDataProvider.cosmosDbMongoContainer';
|
||||
private static readonly CONTAINER_LABEL = localize('azure.resource.providers.databaseServer.treeDataProvider.cosmosDbMongoContainerLabel', "CosmosDB for Mongo");
|
||||
|
||||
public constructor(
|
||||
databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
|
||||
databaseServerService: azureResource.IAzureResourceService,
|
||||
private _extensionContext: ExtensionContext
|
||||
) {
|
||||
super(databaseServerService);
|
||||
}
|
||||
|
||||
protected getTreeItemForResource(databaseServer: azureResource.AzureResourceDatabaseServer, account: azdata.Account): azdata.TreeItem {
|
||||
public getTreeItemForResource(databaseServer: azureResource.AzureResourceDatabaseServer, account: azdata.Account): azdata.TreeItem {
|
||||
return {
|
||||
id: `Cosmosdb_${databaseServer.id ? databaseServer.id : databaseServer.name}`,
|
||||
id: `${AzureResourcePrefixes.cosmosdb}${account.key.accountId}${databaseServer.id ?? databaseServer.name}`,
|
||||
label: `${databaseServer.name} (CosmosDB Mongo API)`,
|
||||
iconPath: {
|
||||
dark: this._extensionContext.asAbsolutePath('resources/dark/cosmosdb_inverse.svg'),
|
||||
@@ -46,7 +45,7 @@ export class CosmosDbMongoTreeDataProvider extends ResourceTreeDataProviderBase<
|
||||
savePassword: true,
|
||||
groupFullName: '',
|
||||
groupId: '',
|
||||
providerName: CosmosDbMongoTreeDataProvider.COSMOSDG_MONGO_PROVIDER_ID,
|
||||
providerName: cosmosDBProvider,
|
||||
saveProfile: false,
|
||||
options: {},
|
||||
azureAccount: account.key.accountId,
|
||||
@@ -54,7 +53,7 @@ export class CosmosDbMongoTreeDataProvider extends ResourceTreeDataProviderBase<
|
||||
azureResourceId: databaseServer.id,
|
||||
azurePortalEndpoint: (account.properties as AzureAccountProperties).providerSettings.settings.portalEndpoint
|
||||
},
|
||||
childProvider: CosmosDbMongoTreeDataProvider.COSMOSDG_MONGO_PROVIDER_ID,
|
||||
childProvider: cosmosDBProvider,
|
||||
type: azdata.ExtensionNodeType.Server
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 'azurecore';
|
||||
import { AzureResourceDatabaseTreeDataProvider } from './databaseTreeDataProvider';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
|
||||
export class AzureResourceDatabaseProvider implements azureResource.IAzureResourceProvider {
|
||||
public constructor(
|
||||
private _databaseService: IAzureResourceService<azureResource.AzureResourceDatabase>,
|
||||
private _extensionContext: ExtensionContext
|
||||
) {
|
||||
}
|
||||
|
||||
public getTreeDataProvider(): azureResource.IAzureResourceTreeDataProvider {
|
||||
return new AzureResourceDatabaseTreeDataProvider(this._databaseService, this._extensionContext);
|
||||
}
|
||||
|
||||
public get providerId(): string {
|
||||
return 'azure.resource.providers.database';
|
||||
}
|
||||
}
|
||||
@@ -4,24 +4,24 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ServiceClientCredentials } from '@azure/ms-rest-js';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { DbServerGraphData } from '../databaseServer/databaseServerService';
|
||||
import { sqlServerQuery, sqlDatabaseQuery } from '../queryStringConstants';
|
||||
import { DatabaseGraphData, DbServerGraphData, GraphData, IAzureResourceDbService } from '../../interfaces';
|
||||
import { sqlServerQuery, sqlDatabaseQuery, where } from '../queryStringConstants';
|
||||
import { ResourceGraphClient } from '@azure/arm-resourcegraph';
|
||||
import { queryGraphResources, GraphData } from '../resourceTreeDataProviderBase';
|
||||
import { queryGraphResources } from '../resourceTreeDataProviderBase';
|
||||
import { AzureAccount, azureResource } from 'azurecore';
|
||||
import { DATABASE_PROVIDER_ID } from '../../../constants';
|
||||
|
||||
export class AzureResourceDatabaseService implements IAzureResourceDbService<DbServerGraphData, DatabaseGraphData> {
|
||||
|
||||
public queryFilter: string = sqlDatabaseQuery;
|
||||
|
||||
interface DatabaseGraphData extends GraphData {
|
||||
kind: string;
|
||||
}
|
||||
export class AzureResourceDatabaseService implements IAzureResourceService<azureResource.AzureResourceDatabase> {
|
||||
public async getResources(subscriptions: azureResource.AzureResourceSubscription[], credential: ServiceClientCredentials, account: AzureAccount): Promise<azureResource.AzureResourceDatabase[]> {
|
||||
const databases: azureResource.AzureResourceDatabase[] = [];
|
||||
const resourceClient = new ResourceGraphClient(credential, { baseUri: account.properties.providerSettings.settings.armResource.endpoint });
|
||||
|
||||
// Query servers and databases in parallel (start all promises before waiting on the 1st)
|
||||
let serverQueryPromise = queryGraphResources<GraphData>(resourceClient, subscriptions, sqlServerQuery);
|
||||
let dbQueryPromise = queryGraphResources<GraphData>(resourceClient, subscriptions, sqlDatabaseQuery);
|
||||
let serverQueryPromise = queryGraphResources<GraphData>(resourceClient, subscriptions, where + sqlServerQuery);
|
||||
let dbQueryPromise = queryGraphResources<GraphData>(resourceClient, subscriptions, where + this.queryFilter);
|
||||
let servers: DbServerGraphData[] = await serverQueryPromise as DbServerGraphData[];
|
||||
let dbByGraph: DatabaseGraphData[] = await dbQueryPromise as DatabaseGraphData[];
|
||||
|
||||
@@ -39,7 +39,7 @@ export class AzureResourceDatabaseService implements IAzureResourceService<azure
|
||||
const synapseDBRegExp = new RegExp(`\/subscriptions\/.+\/resourceGroups\/(.+)\/providers\/Microsoft\.Synapse\/workspaces\/(.+)\/databases\/.+`);
|
||||
|
||||
dbByGraph.forEach(db => {
|
||||
// Filter master DBs, and for all others find their server to get login info
|
||||
// Filter master DBs, and for all others find their server to get login information
|
||||
let serversForRg = rgMap.get(db.resourceGroup);
|
||||
if (serversForRg && !db.kind.endsWith('system') && (svrIdRegExp.test(db.id) || synapseDBRegExp.test(db.id))) {
|
||||
const founds = svrIdRegExp.exec(db.id) ?? synapseDBRegExp.exec(db.id);
|
||||
@@ -50,23 +50,32 @@ export class AzureResourceDatabaseService implements IAzureResourceService<azure
|
||||
const serverName = founds[2];
|
||||
let server = servers.find(s => s.name === serverName);
|
||||
if (server) {
|
||||
databases.push({
|
||||
name: db.name,
|
||||
id: db.id,
|
||||
serverName: server.name,
|
||||
serverFullName: server.properties.fullyQualifiedDomainName,
|
||||
loginName: server.properties.administratorLogin,
|
||||
subscription: {
|
||||
id: db.subscriptionId,
|
||||
name: (subscriptions.find(sub => sub.id === db.subscriptionId))?.name || ''
|
||||
},
|
||||
tenant: db.tenantId,
|
||||
resourceGroup: db.resourceGroup
|
||||
});
|
||||
databases.push(this.convertDatabaseResource(db, server)!);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return databases;
|
||||
}
|
||||
|
||||
public convertDatabaseResource(resource: DatabaseGraphData, server?: DbServerGraphData | undefined): azureResource.AzureResourceDatabase | undefined {
|
||||
if (server) {
|
||||
return {
|
||||
name: resource.name,
|
||||
id: resource.id,
|
||||
provider: DATABASE_PROVIDER_ID,
|
||||
serverName: server.name,
|
||||
serverFullName: server.properties.fullyQualifiedDomainName,
|
||||
loginName: server.properties.administratorLogin,
|
||||
subscription: {
|
||||
id: resource.subscriptionId,
|
||||
name: resource.subscriptionName!
|
||||
},
|
||||
tenant: resource.tenantId,
|
||||
resourceGroup: resource.resourceGroup
|
||||
};
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,27 +8,27 @@ import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
import { AzureResourceItemType, mssqlProvider } from '../../../azureResource/constants';
|
||||
import { AzureResourceItemType, AzureResourcePrefixes, mssqlProvider } from '../../../azureResource/constants';
|
||||
import { generateGuid } from '../../utils';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { DatabaseGraphData, DbServerGraphData } from '../../interfaces';
|
||||
import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
|
||||
import { AzureAccount, azureResource } from 'azurecore';
|
||||
|
||||
export class AzureResourceDatabaseTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabase> {
|
||||
export class AzureResourceDatabaseTreeDataProvider extends ResourceTreeDataProviderBase<DbServerGraphData, DatabaseGraphData> {
|
||||
|
||||
private static readonly containerId = 'azure.resource.providers.database.treeDataProvider.databaseContainer';
|
||||
private static readonly containerLabel = localize('azure.resource.providers.database.treeDataProvider.databaseContainerLabel', "SQL database");
|
||||
|
||||
public constructor(
|
||||
databaseService: IAzureResourceService<azureResource.AzureResourceDatabase>,
|
||||
databaseService: azureResource.IAzureResourceService,
|
||||
private _extensionContext: vscode.ExtensionContext
|
||||
) {
|
||||
super(databaseService);
|
||||
}
|
||||
|
||||
protected getTreeItemForResource(database: azureResource.AzureResourceDatabase, account: AzureAccount): TreeItem {
|
||||
public getTreeItemForResource(database: azureResource.AzureResourceDatabase, account: AzureAccount): TreeItem {
|
||||
return {
|
||||
id: `databaseServer_${database.serverFullName}.database_${database.name}`,
|
||||
id: `${AzureResourcePrefixes.databaseServer}${account.key.accountId}${database.serverFullName}.${AzureResourcePrefixes.database}${database.id ?? database.name}`,
|
||||
label: this.browseConnectionMode ? `${database.serverName}/${database.name} (${AzureResourceDatabaseTreeDataProvider.containerLabel}, ${database.subscription.name})` : `${database.name} (${database.serverName})`,
|
||||
iconPath: {
|
||||
dark: this._extensionContext.asAbsolutePath('resources/dark/sql_database_inverse.svg'),
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 'azurecore';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { AzureResourceDatabaseServerTreeDataProvider } from './databaseServerTreeDataProvider';
|
||||
|
||||
export class AzureResourceDatabaseServerProvider implements azureResource.IAzureResourceProvider {
|
||||
public constructor(
|
||||
private _databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
|
||||
private _extensionContext: ExtensionContext
|
||||
) {
|
||||
}
|
||||
|
||||
public getTreeDataProvider(): azureResource.IAzureResourceTreeDataProvider {
|
||||
return new AzureResourceDatabaseServerTreeDataProvider(this._databaseServerService, this._extensionContext);
|
||||
}
|
||||
|
||||
public get providerId(): string {
|
||||
return 'azure.resource.providers.databaseServer';
|
||||
}
|
||||
}
|
||||
@@ -5,42 +5,39 @@
|
||||
|
||||
import { ServiceClientCredentials } from '@azure/ms-rest-js';
|
||||
import { ResourceGraphClient } from '@azure/arm-resourcegraph';
|
||||
import { GraphData, queryGraphResources } from '../resourceTreeDataProviderBase';
|
||||
import { sqlServerQuery } from '../queryStringConstants';
|
||||
import { queryGraphResources } from '../resourceTreeDataProviderBase';
|
||||
import { sqlServerQuery, where } from '../queryStringConstants';
|
||||
import { azureResource, AzureAccount } from 'azurecore';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { DbServerGraphData, IAzureResourceServerService } from '../../interfaces';
|
||||
import { DATABASE_SERVER_PROVIDER_ID } from '../../../constants';
|
||||
|
||||
export interface DbServerGraphData extends GraphData {
|
||||
properties: {
|
||||
fullyQualifiedDomainName: string;
|
||||
administratorLogin: string;
|
||||
};
|
||||
}
|
||||
export class AzureResourceDatabaseServerService implements IAzureResourceServerService<DbServerGraphData> {
|
||||
|
||||
export class AzureResourceDatabaseServerService implements IAzureResourceService<azureResource.AzureResourceDatabaseServer> {
|
||||
public queryFilter: string = sqlServerQuery;
|
||||
|
||||
public async getResources(subscriptions: azureResource.AzureResourceSubscription[], credential: ServiceClientCredentials, account: AzureAccount): Promise<azureResource.AzureResourceDatabaseServer[]> {
|
||||
const convertedResources: azureResource.AzureResourceDatabaseServer[] = [];
|
||||
const resourceClient = new ResourceGraphClient(credential, { baseUri: account.properties.providerSettings.settings.armResource.endpoint });
|
||||
let serverGraphResources: DbServerGraphData[] = await queryGraphResources<DbServerGraphData>(resourceClient, subscriptions, sqlServerQuery);
|
||||
let serverGraphResources: DbServerGraphData[] = await queryGraphResources<DbServerGraphData>(resourceClient, subscriptions, where + this.queryFilter);
|
||||
const ids = new Set<string>();
|
||||
serverGraphResources.forEach((res) => {
|
||||
if (!ids.has(res.id)) {
|
||||
ids.add(res.id);
|
||||
res.subscriptionName = subscriptions.find(sub => sub.id === res.subscriptionId)?.name;
|
||||
const converted = this.convertResource(res);
|
||||
convertedResources.push(converted);
|
||||
const converted = this.convertServerResource(res);
|
||||
convertedResources.push(converted!);
|
||||
}
|
||||
});
|
||||
|
||||
return convertedResources;
|
||||
}
|
||||
|
||||
protected convertResource(resource: DbServerGraphData): azureResource.AzureResourceDatabaseServer {
|
||||
public convertServerResource(resource: DbServerGraphData): azureResource.AzureResourceDatabaseServer | undefined {
|
||||
|
||||
return {
|
||||
id: resource.id,
|
||||
name: resource.name,
|
||||
provider: DATABASE_SERVER_PROVIDER_ID,
|
||||
// Determine if resource object is for Synapse Workspace or not and get the needed property from the correct place.
|
||||
fullName: resource.properties.fullyQualifiedDomainName,
|
||||
loginName: resource.properties.administratorLogin,
|
||||
|
||||
@@ -8,26 +8,26 @@ import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
import { AzureResourceItemType, mssqlProvider } from '../../../azureResource/constants';
|
||||
import { AzureResourceItemType, AzureResourcePrefixes, mssqlProvider } from '../../../azureResource/constants';
|
||||
import { generateGuid } from '../../utils';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { DbServerGraphData, GraphData } from '../../interfaces';
|
||||
import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
|
||||
import { AzureAccount, azureResource } from 'azurecore';
|
||||
|
||||
export class AzureResourceDatabaseServerTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> {
|
||||
export class AzureResourceDatabaseServerTreeDataProvider extends ResourceTreeDataProviderBase<GraphData, DbServerGraphData> {
|
||||
private static readonly containerId = 'azure.resource.providers.databaseServer.treeDataProvider.databaseServerContainer';
|
||||
private static readonly containerLabel = localize('azure.resource.providers.databaseServer.treeDataProvider.databaseServerContainerLabel', "SQL server");
|
||||
|
||||
public constructor(
|
||||
databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
|
||||
databaseServerService: azureResource.IAzureResourceService,
|
||||
private _extensionContext: vscode.ExtensionContext
|
||||
) {
|
||||
super(databaseServerService);
|
||||
}
|
||||
|
||||
protected getTreeItemForResource(databaseServer: azureResource.AzureResourceDatabaseServer, account: AzureAccount): TreeItem {
|
||||
public getTreeItemForResource(databaseServer: azureResource.AzureResourceDatabaseServer, account: AzureAccount): TreeItem {
|
||||
return {
|
||||
id: `databaseServer_${databaseServer.id ? databaseServer.id : databaseServer.name}`,
|
||||
id: `${AzureResourcePrefixes.databaseServer}${account.key.accountId}${databaseServer.id ?? databaseServer.name}`,
|
||||
label: this.browseConnectionMode ? `${databaseServer.name} (${AzureResourceDatabaseServerTreeDataProvider.containerLabel}, ${databaseServer.subscription.name})` : databaseServer.name,
|
||||
iconPath: {
|
||||
dark: this._extensionContext.asAbsolutePath('resources/dark/sql_server_inverse.svg'),
|
||||
|
||||
@@ -5,26 +5,18 @@
|
||||
|
||||
import { azureResource } from 'azurecore';
|
||||
import { kustoClusterQuery } from '../queryStringConstants';
|
||||
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
|
||||
import { ResourceServiceBase } from '../resourceTreeDataProviderBase';
|
||||
import { KustoGraphData } from '../../interfaces';
|
||||
import { KUSTO_PROVIDER_ID } from '../../../constants';
|
||||
|
||||
export interface KustoGraphData extends GraphData {
|
||||
properties: {
|
||||
fullyQualifiedDomainName: string;
|
||||
administratorLogin: string;
|
||||
uri: string;
|
||||
};
|
||||
}
|
||||
export class KustoResourceService extends ResourceServiceBase<KustoGraphData> {
|
||||
public override queryFilter: string = kustoClusterQuery;
|
||||
|
||||
export class KustoResourceService extends ResourceServiceBase<KustoGraphData, azureResource.AzureResourceDatabaseServer> {
|
||||
|
||||
protected get query(): string {
|
||||
return kustoClusterQuery;
|
||||
}
|
||||
|
||||
protected convertResource(resource: KustoGraphData): azureResource.AzureResourceDatabaseServer {
|
||||
public convertServerResource(resource: KustoGraphData): azureResource.AzureResourceDatabaseServer | undefined {
|
||||
return {
|
||||
id: resource.id,
|
||||
name: resource.name,
|
||||
provider: KUSTO_PROVIDER_ID,
|
||||
fullName: resource.properties.uri.replace('https://', ''),
|
||||
loginName: '',
|
||||
defaultDatabaseName: '',
|
||||
|
||||
@@ -8,27 +8,26 @@ import { TreeItemCollapsibleState, ExtensionContext } from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
import { AzureResourceItemType } from '../../constants';
|
||||
import { AzureResourceItemType, AzureResourcePrefixes, kustoProvider } from '../../constants';
|
||||
import { generateGuid } from '../../utils';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { GraphData, KustoGraphData } from '../../interfaces';
|
||||
import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
|
||||
import { AzureAccount, azureResource } from 'azurecore';
|
||||
|
||||
export class KustoTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> {
|
||||
export class KustoTreeDataProvider extends ResourceTreeDataProviderBase<GraphData, KustoGraphData> {
|
||||
private static readonly containerId = 'azure.resource.providers.KustoContainer';
|
||||
private static readonly containerLabel = localize('azure.resource.providers.KustoContainerLabel', "Azure Data Explorer Cluster");
|
||||
|
||||
public constructor(
|
||||
databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
|
||||
databaseServerService: azureResource.IAzureResourceService,
|
||||
private _extensionContext: ExtensionContext
|
||||
) {
|
||||
super(databaseServerService);
|
||||
}
|
||||
|
||||
|
||||
protected getTreeItemForResource(databaseServer: azureResource.AzureResourceDatabaseServer, account: AzureAccount): TreeItem {
|
||||
public getTreeItemForResource(databaseServer: azureResource.AzureResourceDatabaseServer, account: AzureAccount): TreeItem {
|
||||
return {
|
||||
id: `Kusto_${databaseServer.id ? databaseServer.id : databaseServer.name}`,
|
||||
id: `${AzureResourcePrefixes.kusto}${account.key.accountId}${databaseServer.id ?? databaseServer.name}`,
|
||||
label: this.browseConnectionMode ? `${databaseServer.name} (${KustoTreeDataProvider.containerLabel}, ${databaseServer.subscription.name})` : databaseServer.name,
|
||||
iconPath: {
|
||||
dark: this._extensionContext.asAbsolutePath('resources/dark/azureDE_inverse.svg'),
|
||||
@@ -47,7 +46,7 @@ export class KustoTreeDataProvider extends ResourceTreeDataProviderBase<azureRes
|
||||
savePassword: true,
|
||||
groupFullName: '',
|
||||
groupId: '',
|
||||
providerName: 'KUSTO',
|
||||
providerName: kustoProvider,
|
||||
saveProfile: false,
|
||||
options: {},
|
||||
azureAccount: account.key.accountId,
|
||||
@@ -55,7 +54,7 @@ export class KustoTreeDataProvider extends ResourceTreeDataProviderBase<azureRes
|
||||
azureResourceId: databaseServer.id,
|
||||
azurePortalEndpoint: account.properties.providerSettings.settings.portalEndpoint
|
||||
},
|
||||
childProvider: 'KUSTO',
|
||||
childProvider: kustoProvider,
|
||||
type: ExtensionNodeType.Server
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 'azurecore';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { MysqlFlexibleServerTreeDataProvider } from './mysqlFlexibleServerTreeDataProvider';
|
||||
|
||||
export class MysqlFlexibleServerProvider implements azureResource.IAzureResourceProvider {
|
||||
public constructor(
|
||||
private _databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
|
||||
private _extensionContext: ExtensionContext
|
||||
) {
|
||||
}
|
||||
|
||||
public getTreeDataProvider(): azureResource.IAzureResourceTreeDataProvider {
|
||||
return new MysqlFlexibleServerTreeDataProvider(this._databaseServerService, this._extensionContext);
|
||||
}
|
||||
|
||||
public get providerId(): string {
|
||||
return 'azure.resource.providers.mysqlFlexibleServer';
|
||||
}
|
||||
}
|
||||
@@ -4,28 +4,20 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
|
||||
import { ResourceServiceBase } from '../resourceTreeDataProviderBase';
|
||||
import { azureResource } from 'azurecore';
|
||||
import { mysqlFlexibleServerQuery } from '../queryStringConstants';
|
||||
import { DbServerGraphData } from '../../interfaces';
|
||||
import { MYSQL_FLEXIBLE_SERVER_PROVIDER_ID } from '../../../constants';
|
||||
|
||||
export class MysqlFlexibleServerService extends ResourceServiceBase<DbServerGraphData> {
|
||||
public override queryFilter: string = mysqlFlexibleServerQuery;
|
||||
|
||||
interface DbServerGraphData extends GraphData {
|
||||
properties: {
|
||||
fullyQualifiedDomainName: string;
|
||||
administratorLogin: string;
|
||||
};
|
||||
}
|
||||
|
||||
export class MysqlFlexibleServerService extends ResourceServiceBase<DbServerGraphData, azureResource.AzureResourceDatabaseServer> {
|
||||
|
||||
protected get query(): string {
|
||||
return mysqlFlexibleServerQuery;
|
||||
}
|
||||
|
||||
protected convertResource(resource: DbServerGraphData): azureResource.AzureResourceDatabaseServer {
|
||||
public convertServerResource(resource: DbServerGraphData): azureResource.AzureResourceDatabaseServer | undefined {
|
||||
return {
|
||||
id: resource.id,
|
||||
name: resource.name,
|
||||
provider: MYSQL_FLEXIBLE_SERVER_PROVIDER_ID,
|
||||
fullName: resource.properties.fullyQualifiedDomainName,
|
||||
loginName: resource.properties.administratorLogin,
|
||||
defaultDatabaseName: '',
|
||||
|
||||
@@ -7,28 +7,27 @@ import { TreeItemCollapsibleState, ExtensionContext } from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
import { AzureResourceItemType } from '../../constants';
|
||||
import { AzureResourceItemType, AzureResourcePrefixes, mySqlProvider } from '../../constants';
|
||||
import { generateGuid } from '../../utils';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { DbServerGraphData, GraphData } from '../../interfaces';
|
||||
import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
|
||||
import { AzureAccountProperties, azureResource } from 'azurecore';
|
||||
import { Account, ExtensionNodeType, TreeItem, connection } from 'azdata';
|
||||
|
||||
export class MysqlFlexibleServerTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> {
|
||||
private static readonly MYSQL_FLEXIBLE_SERVER_PROVIDER_ID = 'MySQL';
|
||||
export class MysqlFlexibleServerTreeDataProvider extends ResourceTreeDataProviderBase<GraphData, DbServerGraphData> {
|
||||
private static readonly CONTAINER_ID = 'azure.resource.providers.databaseServer.treeDataProvider.mysqlFlexibleServerContainer';
|
||||
private static readonly CONTAINER_LABEL = localize('azure.resource.providers.databaseServer.treeDataProvider.mysqlFlexibleServerContainerLabel', "Azure Database for MySQL Flexible server");
|
||||
|
||||
public constructor(
|
||||
databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
|
||||
databaseServerService: azureResource.IAzureResourceService,
|
||||
private _extensionContext: ExtensionContext
|
||||
) {
|
||||
super(databaseServerService);
|
||||
}
|
||||
|
||||
protected getTreeItemForResource(databaseServer: azureResource.AzureResourceDatabaseServer, account: Account): TreeItem {
|
||||
public getTreeItemForResource(databaseServer: azureResource.AzureResourceDatabaseServer, account: Account): TreeItem {
|
||||
return {
|
||||
id: `databaseServer_${databaseServer.id ? databaseServer.id : databaseServer.name}`,
|
||||
id: `${AzureResourcePrefixes.mySqlFlexibleServer}${account.key.accountId}${databaseServer.id ?? databaseServer.name}`,
|
||||
label: this.browseConnectionMode ? `${databaseServer.name} (${MysqlFlexibleServerTreeDataProvider.CONTAINER_LABEL}, ${databaseServer.subscription.name})` : databaseServer.name,
|
||||
iconPath: {
|
||||
dark: this._extensionContext.asAbsolutePath('resources/dark/mysql_server_inverse.svg'),
|
||||
@@ -47,7 +46,7 @@ export class MysqlFlexibleServerTreeDataProvider extends ResourceTreeDataProvide
|
||||
savePassword: true,
|
||||
groupFullName: '',
|
||||
groupId: '',
|
||||
providerName: MysqlFlexibleServerTreeDataProvider.MYSQL_FLEXIBLE_SERVER_PROVIDER_ID,
|
||||
providerName: mySqlProvider,
|
||||
saveProfile: false,
|
||||
options: {
|
||||
},
|
||||
@@ -56,7 +55,7 @@ export class MysqlFlexibleServerTreeDataProvider extends ResourceTreeDataProvide
|
||||
azureResourceId: databaseServer.id,
|
||||
azurePortalEndpoint: (account.properties as AzureAccountProperties).providerSettings.settings.portalEndpoint
|
||||
},
|
||||
childProvider: MysqlFlexibleServerTreeDataProvider.MYSQL_FLEXIBLE_SERVER_PROVIDER_ID,
|
||||
childProvider: mySqlProvider,
|
||||
type: ExtensionNodeType.Server
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,26 +3,21 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
|
||||
import { ResourceServiceBase } from '../resourceTreeDataProviderBase';
|
||||
import { azureResource } from 'azurecore';
|
||||
import { postgresArcServerQuery } from '../queryStringConstants';
|
||||
import { PostgresArcServerGraphData } from '../../interfaces';
|
||||
import { POSTGRES_ARC_SERVER_PROVIDER_ID } from '../../../constants';
|
||||
|
||||
export interface PostgresArcServerGraphData extends GraphData {
|
||||
properties: {
|
||||
admin: string;
|
||||
};
|
||||
}
|
||||
export class PostgresServerArcService extends ResourceServiceBase<PostgresArcServerGraphData> {
|
||||
|
||||
export class PostgresServerArcService extends ResourceServiceBase<PostgresArcServerGraphData, azureResource.AzureResourceDatabaseServer> {
|
||||
public override queryFilter: string = postgresArcServerQuery;
|
||||
|
||||
protected get query(): string {
|
||||
return postgresArcServerQuery;
|
||||
}
|
||||
|
||||
protected convertResource(resource: PostgresArcServerGraphData): azureResource.AzureResourceDatabaseServer {
|
||||
public convertServerResource(resource: PostgresArcServerGraphData): azureResource.AzureResourceDatabaseServer | undefined {
|
||||
return {
|
||||
id: resource.id,
|
||||
name: resource.name,
|
||||
provider: POSTGRES_ARC_SERVER_PROVIDER_ID,
|
||||
fullName: resource.name,
|
||||
loginName: resource.properties.admin,
|
||||
defaultDatabaseName: 'postgres',
|
||||
@@ -8,28 +8,27 @@ import { TreeItemCollapsibleState, ExtensionContext } from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
import { AzureResourceItemType } from '../../constants';
|
||||
import { AzureResourceItemType, AzureResourcePrefixes, pgsqlProvider } from '../../constants';
|
||||
import { generateGuid } from '../../utils';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
|
||||
import { AzureAccount, azureResource } from 'azurecore';
|
||||
import { GraphData, PostgresArcServerGraphData } from '../../interfaces';
|
||||
|
||||
export class PostgresServerArcTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> {
|
||||
export class PostgresServerArcTreeDataProvider extends ResourceTreeDataProviderBase<GraphData, PostgresArcServerGraphData> {
|
||||
private static readonly containerId = 'azure.resource.providers.postgresArcServer.treeDataProvider.postgresServerContainer';
|
||||
// allow-any-unicode-next-line
|
||||
private static readonly containerLabel = localize('azure.resource.providers.postgresArcServer.treeDataProvider.postgresServerContainerLabel', "PostgreSQL Hyperscale – Azure Arc");
|
||||
|
||||
public constructor(
|
||||
databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
|
||||
databaseServerService: azureResource.IAzureResourceService,
|
||||
private _extensionContext: ExtensionContext
|
||||
) {
|
||||
super(databaseServerService);
|
||||
}
|
||||
|
||||
|
||||
protected getTreeItemForResource(databaseServer: azureResource.AzureResourceDatabaseServer, account: AzureAccount): TreeItem {
|
||||
public getTreeItemForResource(databaseServer: azureResource.AzureResourceDatabaseServer, account: AzureAccount): TreeItem {
|
||||
return {
|
||||
id: `databaseServer_${databaseServer.id ? databaseServer.id : databaseServer.name}`,
|
||||
id: `${AzureResourcePrefixes.postgresServerArc}${account.key.accountId}${databaseServer.id ?? databaseServer.name}`,
|
||||
label: this.browseConnectionMode ? `${databaseServer.name} (${PostgresServerArcTreeDataProvider.containerLabel}, ${databaseServer.subscription.name})` : databaseServer.name,
|
||||
iconPath: {
|
||||
dark: this._extensionContext.asAbsolutePath('resources/dark/sql_server_inverse.svg'),
|
||||
@@ -48,7 +47,7 @@ export class PostgresServerArcTreeDataProvider extends ResourceTreeDataProviderB
|
||||
savePassword: true,
|
||||
groupFullName: '',
|
||||
groupId: '',
|
||||
providerName: 'PGSQL',
|
||||
providerName: pgsqlProvider,
|
||||
saveProfile: false,
|
||||
options: {
|
||||
// Set default for SSL or will get error complaining about it not being set correctly
|
||||
@@ -59,7 +58,7 @@ export class PostgresServerArcTreeDataProvider extends ResourceTreeDataProviderB
|
||||
azureResourceId: databaseServer.id,
|
||||
azurePortalEndpoint: account.properties.providerSettings.settings.portalEndpoint
|
||||
},
|
||||
childProvider: 'PGSQL',
|
||||
childProvider: pgsqlProvider,
|
||||
type: ExtensionNodeType.Server
|
||||
};
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 'azurecore';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { PostgresServerArcTreeDataProvider as PostgresServerArcTreeDataProvider } from './postgresServerTreeDataProvider';
|
||||
|
||||
export class PostgresServerArcProvider implements azureResource.IAzureResourceProvider {
|
||||
public constructor(
|
||||
private _databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
|
||||
private _extensionContext: ExtensionContext
|
||||
) {
|
||||
}
|
||||
|
||||
public getTreeDataProvider(): azureResource.IAzureResourceTreeDataProvider {
|
||||
return new PostgresServerArcTreeDataProvider(this._databaseServerService, this._extensionContext);
|
||||
}
|
||||
|
||||
public get providerId(): string {
|
||||
return 'azure.resource.providers.postgresArcServer';
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 'azurecore';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { PostgresServerTreeDataProvider as PostgresServerTreeDataProvider } from './postgresServerTreeDataProvider';
|
||||
|
||||
export class PostgresServerProvider implements azureResource.IAzureResourceProvider {
|
||||
public constructor(
|
||||
private _databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
|
||||
private _extensionContext: ExtensionContext
|
||||
) {
|
||||
}
|
||||
|
||||
public getTreeDataProvider(): azureResource.IAzureResourceTreeDataProvider {
|
||||
return new PostgresServerTreeDataProvider(this._databaseServerService, this._extensionContext);
|
||||
}
|
||||
|
||||
public get providerId(): string {
|
||||
return 'azure.resource.providers.postgresServer';
|
||||
}
|
||||
}
|
||||
@@ -4,27 +4,21 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
|
||||
import { ResourceServiceBase } from '../resourceTreeDataProviderBase';
|
||||
import { azureResource } from 'azurecore';
|
||||
import { postgresServerQuery } from '../queryStringConstants';
|
||||
import { DbServerGraphData } from '../../interfaces';
|
||||
import { POSTGRES_SERVER_PROVIDER_ID } from '../../../constants';
|
||||
|
||||
interface DbServerGraphData extends GraphData {
|
||||
properties: {
|
||||
fullyQualifiedDomainName: string;
|
||||
administratorLogin: string;
|
||||
};
|
||||
}
|
||||
export class PostgresServerService extends ResourceServiceBase<DbServerGraphData> {
|
||||
|
||||
export class PostgresServerService extends ResourceServiceBase<DbServerGraphData, azureResource.AzureResourceDatabaseServer> {
|
||||
public override queryFilter: string = postgresServerQuery;
|
||||
|
||||
protected get query(): string {
|
||||
return postgresServerQuery;
|
||||
}
|
||||
|
||||
protected convertResource(resource: DbServerGraphData): azureResource.AzureResourceDatabaseServer {
|
||||
public override convertServerResource(resource: DbServerGraphData): azureResource.AzureResourceDatabaseServer | undefined {
|
||||
return {
|
||||
id: resource.id,
|
||||
name: resource.name,
|
||||
provider: POSTGRES_SERVER_PROVIDER_ID,
|
||||
fullName: resource.properties.fullyQualifiedDomainName,
|
||||
loginName: resource.properties.administratorLogin,
|
||||
defaultDatabaseName: 'postgres',
|
||||
|
||||
@@ -8,27 +8,26 @@ import { TreeItemCollapsibleState, ExtensionContext } from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
import { AzureResourceItemType } from '../../constants';
|
||||
import { AzureResourceItemType, AzureResourcePrefixes, pgsqlProvider } from '../../constants';
|
||||
import { generateGuid } from '../../utils';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { GraphData, DbServerGraphData } from '../../interfaces';
|
||||
import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
|
||||
import { AzureAccount, azureResource } from 'azurecore';
|
||||
|
||||
export class PostgresServerTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> {
|
||||
export class PostgresServerTreeDataProvider extends ResourceTreeDataProviderBase<GraphData, DbServerGraphData> {
|
||||
private static readonly containerId = 'azure.resource.providers.databaseServer.treeDataProvider.postgresServerContainer';
|
||||
private static readonly containerLabel = localize('azure.resource.providers.databaseServer.treeDataProvider.postgresServerContainerLabel', "Azure Database for PostgreSQL server");
|
||||
|
||||
public constructor(
|
||||
databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
|
||||
databaseServerService: azureResource.IAzureResourceService,
|
||||
private _extensionContext: ExtensionContext
|
||||
) {
|
||||
super(databaseServerService);
|
||||
}
|
||||
|
||||
|
||||
protected getTreeItemForResource(databaseServer: azureResource.AzureResourceDatabaseServer, account: AzureAccount): TreeItem {
|
||||
public getTreeItemForResource(databaseServer: azureResource.AzureResourceDatabaseServer, account: AzureAccount): TreeItem {
|
||||
return {
|
||||
id: `databaseServer_${databaseServer.id ? databaseServer.id : databaseServer.name}`,
|
||||
id: `${AzureResourcePrefixes.postgresServer}${account.key.accountId}${databaseServer.id ?? databaseServer.name}`,
|
||||
label: this.browseConnectionMode ? `${databaseServer.name} (${PostgresServerTreeDataProvider.containerLabel}, ${databaseServer.subscription.name})` : databaseServer.name,
|
||||
iconPath: {
|
||||
dark: this._extensionContext.asAbsolutePath('resources/dark/sql_server_inverse.svg'),
|
||||
@@ -47,7 +46,7 @@ export class PostgresServerTreeDataProvider extends ResourceTreeDataProviderBase
|
||||
savePassword: true,
|
||||
groupFullName: '',
|
||||
groupId: '',
|
||||
providerName: 'PGSQL',
|
||||
providerName: pgsqlProvider,
|
||||
saveProfile: false,
|
||||
options: {
|
||||
// Set default for SSL or will get error complaining about it not being set correctly
|
||||
@@ -58,7 +57,7 @@ export class PostgresServerTreeDataProvider extends ResourceTreeDataProviderBase
|
||||
azureResourceId: databaseServer.id,
|
||||
azurePortalEndpoint: account.properties.providerSettings.settings.portalEndpoint
|
||||
},
|
||||
childProvider: 'PGSQL',
|
||||
childProvider: pgsqlProvider,
|
||||
type: ExtensionNodeType.Server
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,37 +4,39 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { azureResource } from 'azurecore';
|
||||
import * as Constants from '../constants';
|
||||
|
||||
export const where = `where `;
|
||||
/**
|
||||
* Lists all SQL Databases and Synapse SQL Databases
|
||||
*/
|
||||
export const sqlDatabaseQuery = `where type == "${azureResource.AzureResourceType.sqlDatabase}" or type == "${azureResource.AzureResourceType.sqlSynapseSqlDatabase}"`;
|
||||
export const sqlDatabaseQuery = `type == "${azureResource.AzureResourceType.sqlDatabase}" or type == "${azureResource.AzureResourceType.sqlSynapseSqlDatabase}"`;
|
||||
|
||||
/**
|
||||
* Lists all Synapse Workspaces with information such as SQL connection endpoints.
|
||||
*/
|
||||
export const synapseWorkspacesQuery = `where type == "${azureResource.AzureResourceType.sqlSynapseWorkspace}"`;
|
||||
export const synapseWorkspacesQuery = `type == "${azureResource.AzureResourceType.sqlSynapseWorkspace}"`;
|
||||
|
||||
/**
|
||||
* Lists all Synapse Dedicated SQL Pools
|
||||
*/
|
||||
export const synapseSqlPoolsQuery = `where type == "${azureResource.AzureResourceType.sqlSynapseSqlPool}"`;
|
||||
export const synapseSqlPoolsQuery = `type == "${azureResource.AzureResourceType.sqlSynapseSqlPool}"`;
|
||||
|
||||
/**
|
||||
* Lists all Sql Servers excluding Synapse Pool Servers
|
||||
* (they have different properties and need to be handled separately)
|
||||
*/
|
||||
export const sqlServerQuery = `where type == "${azureResource.AzureResourceType.sqlServer}" and kind != "v12.0,analytics"`;
|
||||
export const sqlServerQuery = `type == "${azureResource.AzureResourceType.sqlServer}" and kind != "${Constants.analyticsKind}"`;
|
||||
|
||||
/**
|
||||
* Lists all Azure Arc SQL Managed Instances
|
||||
*/
|
||||
export const sqlInstanceArcQuery = `where type == "${azureResource.AzureResourceType.azureArcSqlManagedInstance}"`;
|
||||
export const sqlInstanceArcQuery = `type == "${azureResource.AzureResourceType.azureArcSqlManagedInstance}"`;
|
||||
|
||||
/**
|
||||
* Lists all Azure SQL Managed Instances
|
||||
*/
|
||||
export const sqlInstanceQuery = `where type == "${azureResource.AzureResourceType.sqlManagedInstance}"`;
|
||||
export const sqlInstanceQuery = `type == "${azureResource.AzureResourceType.sqlManagedInstance}"`;
|
||||
|
||||
/**
|
||||
* Lists all resource containers and resource groups
|
||||
@@ -44,29 +46,29 @@ export const resourceGroupQuery = `ResourceContainers | where type=="${azureReso
|
||||
/**
|
||||
* Lists all postgreSQL servers
|
||||
*/
|
||||
export const postgresServerQuery = `where type == "${azureResource.AzureResourceType.postgresServer}"`;
|
||||
export const postgresServerQuery = `type == "${azureResource.AzureResourceType.postgresServer}"`;
|
||||
|
||||
/**
|
||||
* Lists all Azure Arc PostgreSQL servers
|
||||
*/
|
||||
export const postgresArcServerQuery = `where type == "${azureResource.AzureResourceType.azureArcPostgresServer}"`;
|
||||
export const postgresArcServerQuery = `type == "${azureResource.AzureResourceType.azureArcPostgresServer}"`;
|
||||
|
||||
/**
|
||||
* Lists all MySQL Flexible servers
|
||||
*/
|
||||
export const mysqlFlexibleServerQuery = `where type == "${azureResource.AzureResourceType.mysqlFlexibleServer}"`;
|
||||
export const mysqlFlexibleServerQuery = `type == "${azureResource.AzureResourceType.mysqlFlexibleServer}"`;
|
||||
|
||||
/**
|
||||
* Lists all Kusto Clusters
|
||||
*/
|
||||
export const kustoClusterQuery = `where type == "${azureResource.AzureResourceType.kustoClusters}"`;
|
||||
export const kustoClusterQuery = `type == "${azureResource.AzureResourceType.kustoClusters}"`;
|
||||
|
||||
/**
|
||||
* Lists all Cosmos DB for MongoDB accounts
|
||||
*/
|
||||
export const cosmosMongoDbQuery = `where type == "${azureResource.AzureResourceType.cosmosDbAccount}" and kind == "MongoDB"`;
|
||||
export const cosmosMongoDbQuery = `type == "${azureResource.AzureResourceType.cosmosDbAccount}" and kind == "${Constants.mongoDbKind}"`;
|
||||
|
||||
/**
|
||||
* Lists all Log Analytics workspaces
|
||||
*/
|
||||
export const logAnalyticsQuery = `where type == "${azureResource.AzureResourceType.logAnalytics}"`;
|
||||
export const logAnalyticsQuery = `type == "${azureResource.AzureResourceType.logAnalytics}"`;
|
||||
|
||||
@@ -3,18 +3,16 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { DbServerGraphData } from '../databaseServer/databaseServerService';
|
||||
import { azureResource } from 'azurecore';
|
||||
import { ResourceServiceBase } from '../resourceTreeDataProviderBase';
|
||||
import { resourceGroupQuery } from '../queryStringConstants';
|
||||
import { DbServerGraphData } from '../../interfaces';
|
||||
|
||||
export class AzureResourceGroupService extends ResourceServiceBase<DbServerGraphData, azureResource.AzureResourceResourceGroup> {
|
||||
export class AzureResourceGroupService extends ResourceServiceBase<DbServerGraphData> {
|
||||
|
||||
protected get query(): string {
|
||||
return resourceGroupQuery;
|
||||
}
|
||||
public override queryFilter: string = resourceGroupQuery;
|
||||
|
||||
protected convertResource(resource: DbServerGraphData): azureResource.AzureResourceResourceGroup {
|
||||
public override convertServerResource(resource: DbServerGraphData): azureResource.AzureResourceResourceGroup | undefined {
|
||||
return {
|
||||
id: resource.id,
|
||||
name: resource.name,
|
||||
|
||||
@@ -3,24 +3,19 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ExtensionContext } from 'vscode';
|
||||
|
||||
import { azureResource } from 'azurecore';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { KustoTreeDataProvider as KustoTreeDataProvider } from './kustoTreeDataProvider';
|
||||
|
||||
export class KustoProvider implements azureResource.IAzureResourceProvider {
|
||||
export class ResourceProvider implements azureResource.IAzureResourceProvider {
|
||||
public constructor(
|
||||
private _service: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
|
||||
private _extensionContext: ExtensionContext
|
||||
) {
|
||||
}
|
||||
private _providerId: string,
|
||||
private _treeProvider: azureResource.IAzureResourceTreeDataProvider
|
||||
) { }
|
||||
|
||||
public getTreeDataProvider(): azureResource.IAzureResourceTreeDataProvider {
|
||||
return new KustoTreeDataProvider(this._service, this._extensionContext);
|
||||
return this._treeProvider;
|
||||
}
|
||||
|
||||
public get providerId(): string {
|
||||
return 'azure.resource.providers.azureDataExplorer';
|
||||
return this._providerId;
|
||||
}
|
||||
}
|
||||
@@ -6,67 +6,59 @@
|
||||
import * as azdata from 'azdata';
|
||||
import * as msRest from '@azure/ms-rest-js';
|
||||
|
||||
import { IAzureResourceService } from '../interfaces';
|
||||
import { GraphData, IAzureResourceDbService, IAzureResourceServerService } from '../interfaces';
|
||||
import { AzureResourceErrorMessageUtil } from '../utils';
|
||||
import { ResourceGraphClient } from '@azure/arm-resourcegraph';
|
||||
import { AzureAccount, azureResource } from 'azurecore';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
import { ErrorResponse } from '@azure/arm-resourcegraph/esm/models';
|
||||
import { where } from './queryStringConstants';
|
||||
|
||||
export abstract class ResourceTreeDataProviderBase<T extends azureResource.AzureResource> implements azureResource.IAzureResourceTreeDataProvider {
|
||||
export abstract class ResourceTreeDataProviderBase<S extends GraphData, T extends GraphData> implements azureResource.IAzureResourceTreeDataProvider {
|
||||
public browseConnectionMode: boolean = false;
|
||||
|
||||
public constructor(protected _resourceService: IAzureResourceService<T>) {
|
||||
public constructor(
|
||||
protected _resourceService: azureResource.IAzureResourceService | IAzureResourceServerService<T> | IAzureResourceDbService<S, T>) {
|
||||
}
|
||||
|
||||
public async getResourceTreeItem(element: azureResource.IAzureResourceNode): Promise<azdata.TreeItem> {
|
||||
return element.treeItem;
|
||||
public getService(): azureResource.IAzureResourceService {
|
||||
return this._resourceService;
|
||||
}
|
||||
|
||||
public async getChildren(element: azureResource.IAzureResourceNode): Promise<azureResource.IAzureResourceNode[]> {
|
||||
public async getChildren(parent: azureResource.IAzureResourceNode): Promise<azureResource.IAzureResourceNode[]> {
|
||||
try {
|
||||
let resources: T[] = await this.getResources(element);
|
||||
|
||||
return resources.map((resource) => <azureResource.IAzureResourceNode>{
|
||||
account: element.account,
|
||||
subscription: element.subscription,
|
||||
tenantId: element.subscription.tenant,
|
||||
treeItem: this.getTreeItemForResource(resource, element.account)
|
||||
}).sort((a, b) => (<any>a.treeItem.label).localeCompare(b.treeItem.label));
|
||||
let resources: azureResource.AzureResource[] = await this.getResources(parent);
|
||||
return resources.map((resource) => this.convertDataToResource(resource, parent))
|
||||
.sort((a, b) => (<any>a.treeItem.label).localeCompare(b.treeItem.label));
|
||||
} catch (error) {
|
||||
Logger.error(AzureResourceErrorMessageUtil.getErrorMessage(error));
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private async getResources(element: azureResource.IAzureResourceNode): Promise<T[]> {
|
||||
public convertDataToResource(resource: azureResource.AzureResource, parent: azureResource.IAzureResourceNode): any {
|
||||
return <azureResource.IAzureResourceNode>{
|
||||
account: parent.account,
|
||||
subscription: parent.subscription,
|
||||
tenantId: parent.subscription.tenant,
|
||||
treeItem: this.getTreeItemForResource(resource, parent.account)
|
||||
}
|
||||
}
|
||||
|
||||
private async getResources(element: azureResource.IAzureResourceNode): Promise<azureResource.AzureResource[]> {
|
||||
const response = await azdata.accounts.getAccountSecurityToken(element.account, element.subscription.tenant!, azdata.AzureResource.ResourceManagement);
|
||||
if (!response) {
|
||||
throw new Error(`Did not receive security token when getting resources for account ${element.account.displayInfo.displayName}`);
|
||||
}
|
||||
const credential = new msRest.TokenCredentials(response.token, response.tokenType);
|
||||
|
||||
const resources: T[] = await this._resourceService.getResources([element.subscription], credential, element.account) || <T[]>[];
|
||||
return resources;
|
||||
return await this._resourceService.getResources([element.subscription], credential, element.account) || <azureResource.AzureResource[]>[];
|
||||
}
|
||||
|
||||
protected abstract getTreeItemForResource(resource: T, account: AzureAccount): azdata.TreeItem;
|
||||
public abstract getTreeItemForResource(resource: azureResource.AzureResource, account: AzureAccount): azdata.TreeItem;
|
||||
|
||||
public abstract getRootChildren(): Promise<azdata.TreeItem[]>;
|
||||
}
|
||||
|
||||
export interface GraphData {
|
||||
subscriptionId: string,
|
||||
subscriptionName?: string,
|
||||
tenantId: string;
|
||||
id: string;
|
||||
name: string;
|
||||
location: string;
|
||||
type: string;
|
||||
resourceGroup: string;
|
||||
}
|
||||
|
||||
|
||||
export async function queryGraphResources<T extends GraphData>(resourceClient: ResourceGraphClient, subscriptions: azureResource.AzureResourceSubscription[], resourceQuery: string): Promise<T[]> {
|
||||
const allResources: T[] = [];
|
||||
let totalProcessed = 0;
|
||||
@@ -112,34 +104,31 @@ export async function queryGraphResources<T extends GraphData>(resourceClient: R
|
||||
return allResources;
|
||||
}
|
||||
|
||||
export abstract class ResourceServiceBase<T extends GraphData, U extends azureResource.AzureResource> implements IAzureResourceService<U> {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
export abstract class ResourceServiceBase<T extends GraphData> implements IAzureResourceServerService<T> {
|
||||
/**
|
||||
* The query to use - see https://docs.microsoft.com/azure/governance/resource-graph/concepts/query-language
|
||||
* for more information on the supported syntax and tables/properties
|
||||
*/
|
||||
protected abstract get query(): string;
|
||||
public abstract queryFilter: string;
|
||||
|
||||
public async getResources(subscriptions: azureResource.AzureResourceSubscription[], credential: msRest.ServiceClientCredentials, account: AzureAccount): Promise<U[]> {
|
||||
const convertedResources: U[] = [];
|
||||
public async getResources(subscriptions: azureResource.AzureResourceSubscription[], credential: msRest.ServiceClientCredentials, account: AzureAccount): Promise<azureResource.AzureResource[]> {
|
||||
const convertedResources: azureResource.AzureResource[] = [];
|
||||
const resourceClient = new ResourceGraphClient(credential, { baseUri: account.properties.providerSettings.settings.armResource.endpoint });
|
||||
const graphResources = await queryGraphResources<T>(resourceClient, subscriptions, this.query);
|
||||
const graphResources = await queryGraphResources<T>(resourceClient, subscriptions, where + this.queryFilter);
|
||||
const ids = new Set<string>();
|
||||
graphResources.forEach((res) => {
|
||||
if (!ids.has(res.id)) {
|
||||
ids.add(res.id);
|
||||
res.subscriptionName = subscriptions.find(sub => sub.id === res.subscriptionId)?.name;
|
||||
const converted = this.convertResource(res);
|
||||
convertedResources.push(converted);
|
||||
const converted = this.convertServerResource(res);
|
||||
convertedResources.push(converted!);
|
||||
}
|
||||
});
|
||||
|
||||
return convertedResources;
|
||||
}
|
||||
|
||||
protected abstract convertResource(resource: T): U;
|
||||
public abstract convertServerResource(resource: T): azureResource.AzureResource | undefined;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 'azurecore';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { SqlInstanceTreeDataProvider as SqlInstanceTreeDataProvider } from './sqlInstanceTreeDataProvider';
|
||||
|
||||
export class SqlInstanceProvider implements azureResource.IAzureResourceProvider {
|
||||
public constructor(
|
||||
private _service: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
|
||||
private _extensionContext: ExtensionContext
|
||||
) {
|
||||
}
|
||||
|
||||
public getTreeDataProvider(): azureResource.IAzureResourceTreeDataProvider {
|
||||
return new SqlInstanceTreeDataProvider(this._service, this._extensionContext);
|
||||
}
|
||||
|
||||
public get providerId(): string {
|
||||
return 'azure.resource.providers.sqlInstance';
|
||||
}
|
||||
}
|
||||
@@ -5,25 +5,19 @@
|
||||
|
||||
import { azureResource } from 'azurecore';
|
||||
import { sqlInstanceQuery } from '../queryStringConstants';
|
||||
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
|
||||
import { ResourceServiceBase } from '../resourceTreeDataProviderBase';
|
||||
import { SqlInstanceGraphData } from '../../interfaces';
|
||||
import { SQLINSTANCE_PROVIDER_ID } from '../../../constants';
|
||||
|
||||
interface SqlInstanceGraphData extends GraphData {
|
||||
properties: {
|
||||
fullyQualifiedDomainName: string;
|
||||
administratorLogin: string;
|
||||
};
|
||||
}
|
||||
export class SqlInstanceResourceService extends ResourceServiceBase<SqlInstanceGraphData> {
|
||||
|
||||
export class SqlInstanceResourceService extends ResourceServiceBase<SqlInstanceGraphData, azureResource.AzureResourceDatabaseServer> {
|
||||
public override queryFilter: string = sqlInstanceQuery;
|
||||
|
||||
protected get query(): string {
|
||||
return sqlInstanceQuery;
|
||||
}
|
||||
|
||||
protected convertResource(resource: SqlInstanceGraphData): azureResource.AzureResourceDatabaseServer {
|
||||
public override convertServerResource(resource: SqlInstanceGraphData): azureResource.AzureResourceDatabaseServer | undefined {
|
||||
return {
|
||||
id: resource.id,
|
||||
name: resource.name,
|
||||
provider: SQLINSTANCE_PROVIDER_ID,
|
||||
fullName: resource.properties.fullyQualifiedDomainName,
|
||||
loginName: resource.properties.administratorLogin,
|
||||
defaultDatabaseName: 'master',
|
||||
|
||||
@@ -8,27 +8,26 @@ import { TreeItemCollapsibleState, ExtensionContext } from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
import { AzureResourceItemType, mssqlProvider } from '../../constants';
|
||||
import { AzureResourceItemType, AzureResourcePrefixes, mssqlProvider } from '../../constants';
|
||||
import { generateGuid } from '../../utils';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { GraphData, SqlInstanceGraphData } from '../../interfaces';
|
||||
import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
|
||||
import { AzureAccount, azureResource } from 'azurecore';
|
||||
|
||||
export class SqlInstanceTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> {
|
||||
export class SqlInstanceTreeDataProvider extends ResourceTreeDataProviderBase<GraphData, SqlInstanceGraphData> {
|
||||
private static readonly containerId = 'azure.resource.providers.sqlInstanceContainer';
|
||||
private static readonly containerLabel = localize('azure.resource.providers.sqlInstanceContainerLabel', "Azure SQL DB managed instance");
|
||||
|
||||
public constructor(
|
||||
databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
|
||||
databaseServerService: azureResource.IAzureResourceService,
|
||||
private _extensionContext: ExtensionContext
|
||||
) {
|
||||
super(databaseServerService);
|
||||
}
|
||||
|
||||
|
||||
protected getTreeItemForResource(databaseServer: azureResource.AzureResourceDatabaseServer, account: AzureAccount): TreeItem {
|
||||
public getTreeItemForResource(databaseServer: azureResource.AzureResourceDatabaseServer, account: AzureAccount): TreeItem {
|
||||
return {
|
||||
id: `sqlInstance_${databaseServer.id ? databaseServer.id : databaseServer.name}`,
|
||||
id: `${AzureResourcePrefixes.sqlInstance}${account.key.accountId}${account.key.accountId}${databaseServer.id ?? databaseServer.name}`,
|
||||
label: this.browseConnectionMode ? `${databaseServer.name} (${SqlInstanceTreeDataProvider.containerLabel}, ${databaseServer.subscription.name})` : databaseServer.name,
|
||||
iconPath: {
|
||||
dark: this._extensionContext.asAbsolutePath('resources/dark/sql_instance_inverse.svg'),
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 'azurecore';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { SqlInstanceArcTreeDataProvider as SqlInstanceArcTreeDataProvider } from './sqlInstanceArcTreeDataProvider';
|
||||
|
||||
export class SqlInstanceArcProvider implements azureResource.IAzureResourceProvider {
|
||||
public constructor(
|
||||
private _service: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
|
||||
private _extensionContext: ExtensionContext
|
||||
) {
|
||||
}
|
||||
|
||||
public getTreeDataProvider(): azureResource.IAzureResourceTreeDataProvider {
|
||||
return new SqlInstanceArcTreeDataProvider(this._service, this._extensionContext);
|
||||
}
|
||||
|
||||
public get providerId(): string {
|
||||
return 'azure.resource.providers.sqlInstanceArc';
|
||||
}
|
||||
}
|
||||
@@ -3,27 +3,21 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
|
||||
import { ResourceServiceBase } from '../resourceTreeDataProviderBase';
|
||||
import { azureResource } from 'azurecore';
|
||||
import { sqlInstanceArcQuery } from '../queryStringConstants';
|
||||
import { SqlInstanceArcGraphData } from '../../interfaces';
|
||||
import { SQLINSTANCE_ARC_PROVIDER_ID } from '../../../constants';
|
||||
|
||||
export interface SqlInstanceArcGraphData extends GraphData {
|
||||
properties: {
|
||||
admin: string;
|
||||
hybridDataManager: string;
|
||||
};
|
||||
}
|
||||
export class SqlInstanceArcResourceService extends ResourceServiceBase<SqlInstanceArcGraphData> {
|
||||
|
||||
export class SqlInstanceArcResourceService extends ResourceServiceBase<SqlInstanceArcGraphData, azureResource.AzureResourceDatabaseServer> {
|
||||
public override queryFilter: string = sqlInstanceArcQuery;
|
||||
|
||||
protected get query(): string {
|
||||
return sqlInstanceArcQuery;
|
||||
}
|
||||
|
||||
protected convertResource(resource: SqlInstanceArcGraphData): azureResource.AzureResourceDatabaseServer {
|
||||
public override convertServerResource(resource: SqlInstanceArcGraphData): azureResource.AzureResourceDatabaseServer | undefined {
|
||||
return {
|
||||
id: resource.id,
|
||||
name: resource.name,
|
||||
provider: SQLINSTANCE_ARC_PROVIDER_ID,
|
||||
fullName: resource.name,
|
||||
loginName: resource.properties.admin,
|
||||
defaultDatabaseName: 'master',
|
||||
|
||||
@@ -8,28 +8,27 @@ import { TreeItemCollapsibleState, ExtensionContext } from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
import { AzureResourceItemType, mssqlProvider } from '../../constants';
|
||||
import { AzureResourceItemType, AzureResourcePrefixes, mssqlProvider } from '../../constants';
|
||||
import { generateGuid } from '../../utils';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { GraphData, SqlInstanceArcGraphData } from '../../interfaces';
|
||||
import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
|
||||
import { AzureAccount, azureResource } from 'azurecore';
|
||||
|
||||
export class SqlInstanceArcTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> {
|
||||
export class SqlInstanceArcTreeDataProvider extends ResourceTreeDataProviderBase<GraphData, SqlInstanceArcGraphData> {
|
||||
private static readonly containerId = 'azure.resource.providers.sqlInstanceArcContainer';
|
||||
// allow-any-unicode-next-line
|
||||
private static readonly containerLabel = localize('azure.resource.providers.sqlInstanceArcContainerLabel', "SQL managed instance – Azure Arc");
|
||||
|
||||
public constructor(
|
||||
databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
|
||||
databaseServerService: azureResource.IAzureResourceService,
|
||||
private _extensionContext: ExtensionContext
|
||||
) {
|
||||
super(databaseServerService);
|
||||
}
|
||||
|
||||
|
||||
protected getTreeItemForResource(databaseServer: azureResource.AzureResourceDatabaseServer, account: AzureAccount): TreeItem {
|
||||
public getTreeItemForResource(databaseServer: azureResource.AzureResourceDatabaseServer, account: AzureAccount): TreeItem {
|
||||
return {
|
||||
id: `sqlInstance_${databaseServer.id ? databaseServer.id : databaseServer.name}`,
|
||||
id: `${AzureResourcePrefixes.sqlInstanceArc}${account.key.accountId}${databaseServer.id ?? databaseServer.name}`,
|
||||
label: this.browseConnectionMode ? `${databaseServer.name} (${SqlInstanceArcTreeDataProvider.containerLabel}, ${databaseServer.subscription.name})` : databaseServer.name,
|
||||
iconPath: {
|
||||
dark: this._extensionContext.asAbsolutePath('resources/dark/sql_instance_inverse.svg'),
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 'azurecore';
|
||||
import { AzureResourceSynapseSqlPoolTreeDataProvider as AzureResourceSynapseSqlPoolTreeDataProvider } from './synapseSqlPoolTreeDataProvider';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
|
||||
export class AzureResourceSynapseSqlPoolProvider implements azureResource.IAzureResourceProvider {
|
||||
public constructor(
|
||||
private _synapseSqlPoolService: IAzureResourceService<azureResource.AzureResourceDatabase>,
|
||||
private _extensionContext: ExtensionContext
|
||||
) {
|
||||
}
|
||||
|
||||
public getTreeDataProvider(): azureResource.IAzureResourceTreeDataProvider {
|
||||
return new AzureResourceSynapseSqlPoolTreeDataProvider(this._synapseSqlPoolService, this._extensionContext);
|
||||
}
|
||||
|
||||
public get providerId(): string {
|
||||
return 'azure.resource.providers.synapseSqlPool';
|
||||
}
|
||||
}
|
||||
@@ -4,24 +4,45 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ServiceClientCredentials } from '@azure/ms-rest-js';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { SynapseWorkspaceGraphData } from '../synapseWorkspace/synapseWorkspaceService';
|
||||
import { synapseWorkspacesQuery, synapseSqlPoolsQuery } from '../queryStringConstants';
|
||||
import { GraphData, IAzureResourceDbService, SynapseGraphData, SynapseWorkspaceGraphData } from '../../interfaces';
|
||||
import { synapseWorkspacesQuery, synapseSqlPoolsQuery, where } from '../queryStringConstants';
|
||||
import { ResourceGraphClient } from '@azure/arm-resourcegraph';
|
||||
import { queryGraphResources, GraphData } from '../resourceTreeDataProviderBase';
|
||||
import { queryGraphResources } from '../resourceTreeDataProviderBase';
|
||||
import { AzureAccount, azureResource } from 'azurecore';
|
||||
import { SYNAPSE_SQL_POOL_PROVIDER_ID } from '../../../constants';
|
||||
|
||||
interface SynapseGraphData extends GraphData {
|
||||
kind: string;
|
||||
}
|
||||
export class AzureResourceSynapseService implements IAzureResourceService<azureResource.AzureResourceDatabase> {
|
||||
export class AzureResourceSynapseService implements IAzureResourceDbService<SynapseWorkspaceGraphData, SynapseGraphData> {
|
||||
|
||||
// TODO: @Cheena
|
||||
public convertDatabaseResource(resource: SynapseGraphData, server?: SynapseWorkspaceGraphData | undefined): azureResource.AzureResourceDatabase | undefined {
|
||||
if (server) {
|
||||
return {
|
||||
name: resource.name,
|
||||
id: resource.id,
|
||||
provider: SYNAPSE_SQL_POOL_PROVIDER_ID,
|
||||
serverName: server.name,
|
||||
serverFullName: server.properties.connectivityEndpoints?.sql,
|
||||
loginName: server.properties.sqlAdministratorLogin,
|
||||
subscription: {
|
||||
id: resource.subscriptionId,
|
||||
name: resource.subscriptionName!
|
||||
},
|
||||
tenant: resource.tenantId,
|
||||
resourceGroup: resource.resourceGroup
|
||||
};
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
public queryFilter: string = synapseSqlPoolsQuery;
|
||||
public async getResources(subscriptions: azureResource.AzureResourceSubscription[], credential: ServiceClientCredentials, account: AzureAccount): Promise<azureResource.AzureResourceDatabase[]> {
|
||||
const databases: azureResource.AzureResourceDatabase[] = [];
|
||||
const resourceClient = new ResourceGraphClient(credential, { baseUri: account.properties.providerSettings.settings.armResource.endpoint });
|
||||
|
||||
// Query synapse servers, and databases in parallel (start all promises before waiting on the 1st)
|
||||
let synapseQueryPromise = queryGraphResources<GraphData>(resourceClient, subscriptions, synapseSqlPoolsQuery);
|
||||
let synapseWorkspaceQueryPromise = queryGraphResources<GraphData>(resourceClient, subscriptions, synapseWorkspacesQuery);
|
||||
let synapseQueryPromise = queryGraphResources<GraphData>(resourceClient, subscriptions, where + this.queryFilter);
|
||||
let synapseWorkspaceQueryPromise = queryGraphResources<GraphData>(resourceClient, subscriptions, where + synapseWorkspacesQuery);
|
||||
let synapse = await synapseQueryPromise as SynapseGraphData[];
|
||||
let synapseWorkspaceByGraph: SynapseWorkspaceGraphData[] = await synapseWorkspaceQueryPromise as SynapseWorkspaceGraphData[];
|
||||
|
||||
@@ -50,19 +71,8 @@ export class AzureResourceSynapseService implements IAzureResourceService<azureR
|
||||
const serverName = founds[2];
|
||||
let server = synapseWorkspaceByGraph.find(s => s.name === serverName);
|
||||
if (server) {
|
||||
databases.push({
|
||||
name: db.name,
|
||||
id: db.id,
|
||||
serverName: server.name,
|
||||
serverFullName: server.properties.connectivityEndpoints?.sql,
|
||||
loginName: server.properties.sqlAdministratorLogin,
|
||||
subscription: {
|
||||
id: db.subscriptionId,
|
||||
name: (subscriptions.find(sub => sub.id === db.subscriptionId))?.name || ''
|
||||
},
|
||||
tenant: db.tenantId,
|
||||
resourceGroup: db.resourceGroup
|
||||
});
|
||||
let res = this.convertDatabaseResource(db, server);
|
||||
databases.push(res!);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -8,27 +8,27 @@ import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
import { AzureResourceItemType, mssqlProvider } from '../../constants';
|
||||
import { AzureResourceItemType, AzureResourcePrefixes, mssqlProvider } from '../../constants';
|
||||
import { generateGuid } from '../../utils';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { SynapseGraphData, SynapseWorkspaceGraphData } from '../../interfaces';
|
||||
import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
|
||||
import { AzureAccount, azureResource } from 'azurecore';
|
||||
|
||||
export class AzureResourceSynapseSqlPoolTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabase> {
|
||||
export class AzureResourceSynapseSqlPoolTreeDataProvider extends ResourceTreeDataProviderBase<SynapseWorkspaceGraphData, SynapseGraphData> {
|
||||
|
||||
private static readonly containerId = 'azure.resource.providers.synapseSqlPool.treeDataProvider.synapseSqlPoolContainer';
|
||||
private static readonly containerLabel = localize('azure.resource.providers.synapseSqlPool.treeDataProvider.synapseSqlPoolContainerLabel', "Dedicated SQL Pools");
|
||||
|
||||
public constructor(
|
||||
synapseSqlPoolService: IAzureResourceService<azureResource.AzureResourceDatabase>,
|
||||
synapseSqlPoolService: azureResource.IAzureResourceService,
|
||||
private _extensionContext: vscode.ExtensionContext
|
||||
) {
|
||||
super(synapseSqlPoolService);
|
||||
}
|
||||
|
||||
protected getTreeItemForResource(synapse: azureResource.AzureResourceDatabase, account: AzureAccount): TreeItem {
|
||||
public getTreeItemForResource(synapse: azureResource.AzureResourceDatabase, account: AzureAccount): TreeItem {
|
||||
return {
|
||||
id: `synapseWorkspace_${synapse.serverFullName}.synapseSqlPool_${synapse.name}`,
|
||||
id: `${AzureResourcePrefixes.synapseWorkspace}${account.key.accountId}${synapse.serverFullName}.${AzureResourcePrefixes.synapseSqlPool}${synapse.id ?? synapse.name}`,
|
||||
label: this.browseConnectionMode ? `${synapse.serverName}/${synapse.name} (${AzureResourceSynapseSqlPoolTreeDataProvider.containerLabel}, ${synapse.subscription.name})` : `${synapse.name} (${synapse.serverName})`,
|
||||
iconPath: {
|
||||
dark: this._extensionContext.asAbsolutePath('resources/dark/sql_database_inverse.svg'),
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 'azurecore';
|
||||
import { AzureResourceSynapseWorkspaceTreeDataProvider } from './synapseWorkspaceTreeDataProvider';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
|
||||
export class AzureResourceSynapseWorkspaceProvider implements azureResource.IAzureResourceProvider {
|
||||
public constructor(
|
||||
private _synapseWorkspaceService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
|
||||
private _extensionContext: ExtensionContext
|
||||
) {
|
||||
}
|
||||
|
||||
public getTreeDataProvider(): azureResource.IAzureResourceTreeDataProvider {
|
||||
return new AzureResourceSynapseWorkspaceTreeDataProvider(this._synapseWorkspaceService, this._extensionContext);
|
||||
}
|
||||
|
||||
public get providerId(): string {
|
||||
return 'azure.resource.providers.synapseWorkspace';
|
||||
}
|
||||
}
|
||||
@@ -5,60 +5,39 @@
|
||||
|
||||
import { ServiceClientCredentials } from '@azure/ms-rest-js';
|
||||
import { ResourceGraphClient } from '@azure/arm-resourcegraph';
|
||||
import { GraphData, queryGraphResources } from '../resourceTreeDataProviderBase';
|
||||
import { queryGraphResources } from '../resourceTreeDataProviderBase';
|
||||
import { azureResource, AzureAccount } from 'azurecore';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { synapseWorkspacesQuery } from '../queryStringConstants';
|
||||
import { IAzureResourceServerService, SynapseWorkspaceGraphData } from '../../interfaces';
|
||||
import { synapseWorkspacesQuery, where } from '../queryStringConstants';
|
||||
import { SYNAPSE_WORKSPACE_PROVIDER_ID } from '../../../constants';
|
||||
|
||||
/**
|
||||
* Properties returned by the Synapse query are different from the server ones and have to be treated differently.
|
||||
*/
|
||||
export interface SynapseWorkspaceGraphData extends GraphData {
|
||||
properties: {
|
||||
/**
|
||||
* SQL connectivity endpoint and other endpoints are found here, instead of fullyQualifiedDomainName.
|
||||
*/
|
||||
connectivityEndpoints: { sql: string };
|
||||
/**
|
||||
* managedResourceGroupName is the resource group used by any SQL pools inside the workspace
|
||||
* which is different from the resource group of the workspace itself.
|
||||
*/
|
||||
managedResourceGroupName: string;
|
||||
/**
|
||||
* administratorLogin is called sqlAdministratorLogin here.
|
||||
*/
|
||||
sqlAdministratorLogin: string;
|
||||
};
|
||||
}
|
||||
export class AzureResourceSynapseWorkspaceService implements IAzureResourceServerService<SynapseWorkspaceGraphData> {
|
||||
|
||||
export class AzureResourceSynapseWorkspaceService implements IAzureResourceService<azureResource.AzureResourceDatabaseServer> {
|
||||
|
||||
protected get query(): string {
|
||||
return synapseWorkspacesQuery;
|
||||
}
|
||||
public queryFilter: string = synapseWorkspacesQuery;
|
||||
|
||||
public async getResources(subscriptions: azureResource.AzureResourceSubscription[], credential: ServiceClientCredentials, account: AzureAccount): Promise<azureResource.AzureResourceDatabaseServer[]> {
|
||||
const convertedResources: azureResource.AzureResourceDatabaseServer[] = [];
|
||||
const resourceClient = new ResourceGraphClient(credential, { baseUri: account.properties.providerSettings.settings.armResource.endpoint });
|
||||
let serverGraphResources: SynapseWorkspaceGraphData[] = await queryGraphResources<SynapseWorkspaceGraphData>(resourceClient, subscriptions, this.query);
|
||||
let serverGraphResources: SynapseWorkspaceGraphData[] = await queryGraphResources<SynapseWorkspaceGraphData>(resourceClient, subscriptions, where + this.queryFilter);
|
||||
const ids = new Set<string>();
|
||||
serverGraphResources.forEach((res) => {
|
||||
if (!ids.has(res.id)) {
|
||||
ids.add(res.id);
|
||||
res.subscriptionName = subscriptions.find(sub => sub.id === res.subscriptionId)?.name;
|
||||
const converted = this.convertResource(res);
|
||||
convertedResources.push(converted);
|
||||
const converted = this.convertServerResource(res);
|
||||
convertedResources.push(converted!);
|
||||
}
|
||||
});
|
||||
|
||||
return convertedResources;
|
||||
}
|
||||
|
||||
protected convertResource(resource: SynapseWorkspaceGraphData): azureResource.AzureResourceDatabaseServer {
|
||||
public convertServerResource(resource: SynapseWorkspaceGraphData): azureResource.AzureResourceDatabaseServer | undefined {
|
||||
|
||||
return {
|
||||
id: resource.id,
|
||||
name: resource.name,
|
||||
provider: SYNAPSE_WORKSPACE_PROVIDER_ID,
|
||||
fullName: resource.properties.connectivityEndpoints?.sql,
|
||||
loginName: resource.properties.sqlAdministratorLogin,
|
||||
defaultDatabaseName: 'master',
|
||||
|
||||
@@ -8,26 +8,26 @@ import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
import { AzureResourceItemType, mssqlProvider } from '../../constants';
|
||||
import { AzureResourceItemType, AzureResourcePrefixes, mssqlProvider } from '../../constants';
|
||||
import { generateGuid } from '../../utils';
|
||||
import { IAzureResourceService } from '../../interfaces';
|
||||
import { GraphData, SynapseWorkspaceGraphData } from '../../interfaces';
|
||||
import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
|
||||
import { AzureAccount, azureResource } from 'azurecore';
|
||||
|
||||
export class AzureResourceSynapseWorkspaceTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> {
|
||||
export class AzureResourceSynapseWorkspaceTreeDataProvider extends ResourceTreeDataProviderBase<GraphData, SynapseWorkspaceGraphData> {
|
||||
private static readonly containerId = 'azure.resource.providers.synapseWorkspace.treeDataProvider.synapseWorkspaceContainer';
|
||||
private static readonly containerLabel = localize('azure.resource.providers.synapseWorkspace.treeDataProvider.synapseWorkspaceContainerLabel', "Azure Synapse Analytics");
|
||||
|
||||
public constructor(
|
||||
synapseWorkspaceService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
|
||||
synapseWorkspaceService: azureResource.IAzureResourceService,
|
||||
private _extensionContext: vscode.ExtensionContext
|
||||
) {
|
||||
super(synapseWorkspaceService);
|
||||
}
|
||||
|
||||
protected getTreeItemForResource(synapseWorkspace: azureResource.AzureResourceDatabaseServer, account: AzureAccount): TreeItem {
|
||||
public getTreeItemForResource(synapseWorkspace: azureResource.AzureResourceDatabaseServer, account: AzureAccount): TreeItem {
|
||||
return {
|
||||
id: `synapseWorkspace_${synapseWorkspace.id ?? synapseWorkspace.name}`,
|
||||
id: `${AzureResourcePrefixes.synapseWorkspace}${account.key.accountId}${synapseWorkspace.id ?? synapseWorkspace.name}`,
|
||||
label: this.browseConnectionMode ? `${synapseWorkspace.name} (${AzureResourceSynapseWorkspaceTreeDataProvider.containerLabel}, ${synapseWorkspace.subscription.name})` : synapseWorkspace.name,
|
||||
iconPath: {
|
||||
dark: this._extensionContext.asAbsolutePath('resources/dark/sql_server_inverse.svg'),
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 'azurecore';
|
||||
|
||||
export class AzureResourceUniversalResourceProvider implements azureResource.IAzureUniversalResourceProvider {
|
||||
public constructor(
|
||||
private _providerId: string,
|
||||
private _treeProvider: azureResource.IAzureUniversalTreeDataProvider
|
||||
) { }
|
||||
|
||||
public getTreeDataProvider(): azureResource.IAzureUniversalTreeDataProvider {
|
||||
return this._treeProvider;
|
||||
}
|
||||
|
||||
public get providerId(): string {
|
||||
return this._providerId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ServiceClientCredentials } from '@azure/ms-rest-js';
|
||||
import { ResourceGraphClient } from '@azure/arm-resourcegraph';
|
||||
import { queryGraphResources } from '../resourceTreeDataProviderBase';
|
||||
import { azureResource, AzureAccount } from 'azurecore';
|
||||
import { UniversalGraphData, IAzureResourceServerService, IAzureResourceDbService } from '../../interfaces';
|
||||
import { where } from '../queryStringConstants';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { AzureResourcePrefixes, ResourceCategory, analyticsKind, mongoDbKind } from '../../constants';
|
||||
import {
|
||||
COSMOSDB_MONGO_PROVIDER_ID, DATABASE_PROVIDER_ID, DATABASE_SERVER_PROVIDER_ID, KUSTO_PROVIDER_ID, AZURE_MONITOR_PROVIDER_ID,
|
||||
MYSQL_FLEXIBLE_SERVER_PROVIDER_ID, POSTGRES_SERVER_PROVIDER_ID, POSTGRES_ARC_SERVER_PROVIDER_ID, SQLINSTANCE_PROVIDER_ID,
|
||||
SQLINSTANCE_ARC_PROVIDER_ID, SYNAPSE_SQL_POOL_PROVIDER_ID, SYNAPSE_WORKSPACE_PROVIDER_ID
|
||||
} from '../../../constants';
|
||||
import { Logger } from '../../../utils/Logger';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export class AzureResourceUniversalService implements azureResource.IAzureResourceService {
|
||||
|
||||
constructor(
|
||||
private registeredTreeDataProviders: Map<string, azureResource.IAzureResourceTreeDataProvider>
|
||||
) {
|
||||
this.queryFilter = this.generateUniversalQueryFilter();
|
||||
}
|
||||
|
||||
public queryFilter: string;
|
||||
|
||||
private generateUniversalQueryFilter(): string {
|
||||
let queryFilter = where;
|
||||
this.registeredTreeDataProviders.forEach((v, k) => {
|
||||
queryFilter += ' (' + v.getService().queryFilter + ') ' + 'or';
|
||||
})
|
||||
return queryFilter.substring(0, queryFilter.length - 3); // remove last || clause.
|
||||
}
|
||||
|
||||
public getRegisteredTreeDataProviderInstance(id: string): azureResource.IAzureResourceTreeDataProvider {
|
||||
if (this.registeredTreeDataProviders.has(id)) {
|
||||
return this.registeredTreeDataProviders.get(id)!;
|
||||
}
|
||||
throw new Error(localize('azurecore.unregisteredProvider', 'Unrecognized Provider resource: {0}', id));
|
||||
}
|
||||
|
||||
public async getResources(subscriptions: azureResource.AzureResourceSubscription[], credential: ServiceClientCredentials, account: AzureAccount): Promise<azureResource.AzureResource[]> {
|
||||
const convertedResources: azureResource.AzureResource[] = [];
|
||||
const resourceClient = new ResourceGraphClient(credential, { baseUri: account.properties.providerSettings.settings.armResource.endpoint });
|
||||
let graphResources: UniversalGraphData[] = await queryGraphResources<UniversalGraphData>(resourceClient, subscriptions, this.queryFilter);
|
||||
const ids = new Set<string>();
|
||||
graphResources.forEach((res) => {
|
||||
if (!ids.has(res.id)) {
|
||||
ids.add(res.id);
|
||||
res.subscriptionName = subscriptions.find(sub => sub.id === res.subscriptionId)?.name;
|
||||
let converted: azureResource.AzureResource | undefined;
|
||||
let providerInfo = this.getProviderFromResourceType(res.type, res.kind);
|
||||
// Convert based on server/database type.
|
||||
if (providerInfo[1] === ResourceCategory.Server) {
|
||||
let serverProvider = providerInfo[0].getService() as IAzureResourceServerService<UniversalGraphData>;
|
||||
converted = serverProvider.convertServerResource(res);
|
||||
} else { // database
|
||||
// Don't select 'master' Azure databases as they are internal databases and repititive with server names.
|
||||
if (!res.kind?.endsWith('system')) {
|
||||
let dbProvider = providerInfo[0].getService() as IAzureResourceDbService<UniversalGraphData, UniversalGraphData>;
|
||||
let serverResource = this.getServerResource(res, graphResources);
|
||||
converted = dbProvider.convertDatabaseResource(res, serverResource);
|
||||
}
|
||||
}
|
||||
if (converted) {
|
||||
convertedResources.push(converted);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return convertedResources;
|
||||
}
|
||||
|
||||
public getProviderFromResourceType(type: string, kind?: string):
|
||||
[provider: azureResource.IAzureResourceTreeDataProvider, category: ResourceCategory] {
|
||||
if (type === azureResource.AzureResourceType.cosmosDbAccount && kind === mongoDbKind) {
|
||||
return [this.getRegisteredTreeDataProviderInstance(COSMOSDB_MONGO_PROVIDER_ID), ResourceCategory.Server];
|
||||
} else if (type === azureResource.AzureResourceType.sqlDatabase || type === azureResource.AzureResourceType.sqlSynapseSqlDatabase) {
|
||||
return [this.getRegisteredTreeDataProviderInstance(DATABASE_PROVIDER_ID), ResourceCategory.Database];
|
||||
} else if (type === azureResource.AzureResourceType.sqlServer && kind !== analyticsKind) {
|
||||
return [this.getRegisteredTreeDataProviderInstance(DATABASE_SERVER_PROVIDER_ID), ResourceCategory.Server];
|
||||
} else if (type === azureResource.AzureResourceType.kustoClusters) {
|
||||
return [this.getRegisteredTreeDataProviderInstance(KUSTO_PROVIDER_ID), ResourceCategory.Server];
|
||||
} else if (type === azureResource.AzureResourceType.logAnalytics) {
|
||||
return [this.getRegisteredTreeDataProviderInstance(AZURE_MONITOR_PROVIDER_ID), ResourceCategory.Server];
|
||||
} else if (type === azureResource.AzureResourceType.mysqlFlexibleServer) {
|
||||
return [this.getRegisteredTreeDataProviderInstance(MYSQL_FLEXIBLE_SERVER_PROVIDER_ID), ResourceCategory.Server];
|
||||
} else if (type === azureResource.AzureResourceType.postgresServer) {
|
||||
return [this.getRegisteredTreeDataProviderInstance(POSTGRES_SERVER_PROVIDER_ID), ResourceCategory.Server];
|
||||
} else if (type === azureResource.AzureResourceType.azureArcPostgresServer) {
|
||||
return [this.getRegisteredTreeDataProviderInstance(POSTGRES_ARC_SERVER_PROVIDER_ID), ResourceCategory.Server];
|
||||
} else if (type === azureResource.AzureResourceType.sqlManagedInstance) {
|
||||
return [this.getRegisteredTreeDataProviderInstance(SQLINSTANCE_PROVIDER_ID), ResourceCategory.Server];
|
||||
} else if (type === azureResource.AzureResourceType.azureArcSqlManagedInstance) {
|
||||
return [this.getRegisteredTreeDataProviderInstance(SQLINSTANCE_ARC_PROVIDER_ID), ResourceCategory.Server];
|
||||
} else if (type === azureResource.AzureResourceType.sqlSynapseSqlPool) {
|
||||
return [this.getRegisteredTreeDataProviderInstance(SYNAPSE_SQL_POOL_PROVIDER_ID), ResourceCategory.Database];
|
||||
} else if (type === azureResource.AzureResourceType.sqlSynapseWorkspace) {
|
||||
return [this.getRegisteredTreeDataProviderInstance(SYNAPSE_WORKSPACE_PROVIDER_ID), ResourceCategory.Server];
|
||||
}
|
||||
Logger.error(`Type provider not registered: ${type}`);
|
||||
throw new Error(localize('azurecore.unregisteredProviderType', 'Unrecognized Provider resource type: {0}', type));
|
||||
}
|
||||
|
||||
public getProviderFromResourceId(id: string): azureResource.IAzureResourceTreeDataProvider {
|
||||
if (id.startsWith(AzureResourcePrefixes.cosmosdb)) {
|
||||
return this.getRegisteredTreeDataProviderInstance(COSMOSDB_MONGO_PROVIDER_ID);
|
||||
} else if (id.startsWith(AzureResourcePrefixes.database)) {
|
||||
return this.getRegisteredTreeDataProviderInstance(DATABASE_PROVIDER_ID);
|
||||
} else if (id.startsWith(AzureResourcePrefixes.databaseServer)) {
|
||||
return this.getRegisteredTreeDataProviderInstance(DATABASE_SERVER_PROVIDER_ID);
|
||||
} else if (id.startsWith(AzureResourcePrefixes.kusto)) {
|
||||
return this.getRegisteredTreeDataProviderInstance(KUSTO_PROVIDER_ID);
|
||||
} else if (id.startsWith(AzureResourcePrefixes.logAnalytics)) {
|
||||
return this.getRegisteredTreeDataProviderInstance(AZURE_MONITOR_PROVIDER_ID);
|
||||
} else if (id.startsWith(AzureResourcePrefixes.mySqlFlexibleServer)) {
|
||||
return this.getRegisteredTreeDataProviderInstance(MYSQL_FLEXIBLE_SERVER_PROVIDER_ID);
|
||||
} else if (id.startsWith(AzureResourcePrefixes.postgresServer)) {
|
||||
return this.getRegisteredTreeDataProviderInstance(POSTGRES_SERVER_PROVIDER_ID);
|
||||
} else if (id.startsWith(AzureResourcePrefixes.postgresServerArc)) {
|
||||
return this.getRegisteredTreeDataProviderInstance(POSTGRES_ARC_SERVER_PROVIDER_ID);
|
||||
} else if (id.startsWith(AzureResourcePrefixes.sqlInstance)) {
|
||||
return this.getRegisteredTreeDataProviderInstance(SQLINSTANCE_PROVIDER_ID);
|
||||
} else if (id.startsWith(AzureResourcePrefixes.sqlInstanceArc)) {
|
||||
return this.getRegisteredTreeDataProviderInstance(SQLINSTANCE_ARC_PROVIDER_ID);
|
||||
} else if (id.startsWith(AzureResourcePrefixes.synapseSqlPool)) {
|
||||
return this.getRegisteredTreeDataProviderInstance(SYNAPSE_SQL_POOL_PROVIDER_ID);
|
||||
} else if (id.startsWith(AzureResourcePrefixes.synapseWorkspace)) {
|
||||
return this.getRegisteredTreeDataProviderInstance(SYNAPSE_WORKSPACE_PROVIDER_ID);
|
||||
}
|
||||
Logger.error(`Unrecognized provider prefix for id: ${id}`);
|
||||
throw new Error(localize('azurecore.unregisteredProvider', 'Unrecognized Provider resource: {0}', id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resource Id format:
|
||||
* '/subscriptions/<subscriptionid>/resourceGroups/<resourcegroupname>/providers/Microsoft.Sql/servers/<servername>/databases/<dbname>'
|
||||
* We find server with it's name in the same subscription, as resource groups can still be different.
|
||||
*/
|
||||
private getServerResource(resource: UniversalGraphData, allResources: UniversalGraphData[]): UniversalGraphData | undefined {
|
||||
const resourceParts = resource.id.split('/');
|
||||
const serverNameIndex = resourceParts.length - 3;
|
||||
const subscriptionId = resourceParts[2];
|
||||
return allResources.find(res => res.name === resourceParts[serverNameIndex]
|
||||
&& res.subscriptionId === subscriptionId) ?? undefined;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import * as msRest from '@azure/ms-rest-js';
|
||||
|
||||
import { AzureResourceErrorMessageUtil } from '../../utils';
|
||||
import { GraphData } from '../../interfaces';
|
||||
import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
|
||||
import { AzureAccount, azureResource } from 'azurecore';
|
||||
import { Logger } from '../../../utils/Logger';
|
||||
import { AzureResourceUniversalService } from './universalService';
|
||||
|
||||
export class AzureResourceUniversalTreeDataProvider<S extends GraphData, D extends GraphData>
|
||||
extends ResourceTreeDataProviderBase<S, D> implements azureResource.IAzureUniversalTreeDataProvider {
|
||||
|
||||
public constructor(
|
||||
private universalService: azureResource.IAzureResourceService,
|
||||
) {
|
||||
super(universalService);
|
||||
}
|
||||
|
||||
public override getService(): azureResource.IAzureResourceService {
|
||||
return this.universalService;
|
||||
}
|
||||
|
||||
public override getChildren(element: azureResource.IAzureResourceNode): Promise<azureResource.IAzureResourceNode[]> {
|
||||
throw new Error('Method not supported for universal provider.');
|
||||
}
|
||||
|
||||
public getTreeItemForResource(resource: azureResource.AzureResource, account: AzureAccount): azdata.TreeItem {
|
||||
let service: AzureResourceUniversalService = this.universalService as AzureResourceUniversalService;
|
||||
let provider = service.getRegisteredTreeDataProviderInstance(resource.provider!);
|
||||
provider.browseConnectionMode = this.browseConnectionMode;
|
||||
return provider.getTreeItemForResource(resource, account);
|
||||
}
|
||||
|
||||
public async getRootChildren(): Promise<azdata.TreeItem[]> {
|
||||
throw new Error('Method not supported');
|
||||
}
|
||||
|
||||
public async getAllChildren(account: AzureAccount, subscriptions: azureResource.AzureResourceSubscription[]): Promise<azureResource.IAzureResourceNode[]> {
|
||||
try {
|
||||
let resources: azureResource.AzureResource[] = await this.getAllResources(account, subscriptions);
|
||||
return resources.map((resource) => <azureResource.IAzureResourceNode>{
|
||||
account: account,
|
||||
subscription: resource.subscription,
|
||||
tenantId: resource.tenant,
|
||||
treeItem: this.getTreeItemForResource(resource, account)
|
||||
}).sort((a, b) => (<any>a.treeItem.label).localeCompare(b.treeItem.label));
|
||||
} catch (error) {
|
||||
Logger.error(AzureResourceErrorMessageUtil.getErrorMessage(error));
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private async getAllResources(account: AzureAccount, subscriptions: azureResource.AzureResourceSubscription[]): Promise<azureResource.AzureResource[]> {
|
||||
let resources: azureResource.AzureResource[] = [];
|
||||
for (const tenant of account.properties.tenants) {
|
||||
const subs = subscriptions.filter(sub => sub.tenant === tenant.id);
|
||||
if (subs && subs.length > 0) {
|
||||
const response = await azdata.accounts.getAccountSecurityToken(account, tenant.id, azdata.AzureResource.ResourceManagement);
|
||||
if (!response) {
|
||||
throw new Error(`Did not receive security token when getting resources for account ${account.displayInfo.displayName}`);
|
||||
}
|
||||
const credential = new msRest.TokenCredentials(response.token, response.tokenType);
|
||||
resources = resources.concat(await this.universalService.getResources(subs, credential, account));
|
||||
}
|
||||
}
|
||||
return resources;
|
||||
}
|
||||
}
|
||||
@@ -3,18 +3,20 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { extensions, TreeItem } from 'vscode';
|
||||
import { extensions } from 'vscode';
|
||||
import * as azdata from 'azdata';
|
||||
|
||||
import { IAzureResourceNodeWithProviderId } from './interfaces';
|
||||
import { AzureAccount, azureResource } from 'azurecore';
|
||||
import { UNIVERSAL_PROVIDER_ID } from '../constants';
|
||||
|
||||
export class AzureResourceService {
|
||||
private _areResourceProvidersLoaded: boolean = false;
|
||||
private _resourceProviders: { [resourceProviderId: string]: azureResource.IAzureResourceProvider } = {};
|
||||
private _treeDataProviders: { [resourceProviderId: string]: azureResource.IAzureResourceTreeDataProvider } = {};
|
||||
private _universalProvider: azureResource.IAzureUniversalResourceProvider | undefined = undefined;
|
||||
|
||||
public constructor() {
|
||||
}
|
||||
public constructor() { }
|
||||
|
||||
public async listResourceProviderIds(): Promise<string[]> {
|
||||
await this.ensureResourceProvidersRegistered();
|
||||
@@ -22,6 +24,11 @@ export class AzureResourceService {
|
||||
return Object.keys(this._resourceProviders);
|
||||
}
|
||||
|
||||
public async getResourceProviders(): Promise<{ [resourceProviderId: string]: azureResource.IAzureResourceProvider }> {
|
||||
await this.ensureResourceProvidersRegistered();
|
||||
return this._resourceProviders;
|
||||
}
|
||||
|
||||
public registerResourceProvider(resourceProvider: azureResource.IAzureResourceProvider): void {
|
||||
this.doRegisterResourceProvider(resourceProvider);
|
||||
}
|
||||
@@ -35,13 +42,11 @@ export class AzureResourceService {
|
||||
public async getRootChildren(resourceProviderId: string, account: AzureAccount, subscription: azureResource.AzureResourceSubscription): Promise<IAzureResourceNodeWithProviderId[]> {
|
||||
await this.ensureResourceProvidersRegistered();
|
||||
|
||||
if (!(resourceProviderId in this._resourceProviders)) {
|
||||
if (!(resourceProviderId in this._resourceProviders) && resourceProviderId !== UNIVERSAL_PROVIDER_ID) {
|
||||
throw new Error(`Azure resource provider doesn't exist. Id: ${resourceProviderId}`);
|
||||
}
|
||||
|
||||
const treeDataProvider = this._treeDataProviders[resourceProviderId];
|
||||
const rootChildren = await treeDataProvider.getRootChildren();
|
||||
|
||||
const rootChildren = <azdata.TreeItem[]>await this._treeDataProviders[resourceProviderId]?.getRootChildren();
|
||||
return rootChildren.map(rootChild => {
|
||||
return {
|
||||
resourceProviderId,
|
||||
@@ -58,13 +63,13 @@ export class AzureResourceService {
|
||||
public async getChildren(resourceProviderId: string, element: azureResource.IAzureResourceNode, browseConnectionMode: boolean = false): Promise<IAzureResourceNodeWithProviderId[]> {
|
||||
await this.ensureResourceProvidersRegistered();
|
||||
|
||||
if (!(resourceProviderId in this._resourceProviders)) {
|
||||
if (!(resourceProviderId in this._resourceProviders) && resourceProviderId !== UNIVERSAL_PROVIDER_ID) {
|
||||
throw new Error(`Azure resource provider doesn't exist. Id: ${resourceProviderId}`);
|
||||
}
|
||||
|
||||
const treeDataProvider = this._treeDataProviders[resourceProviderId];
|
||||
const treeDataProvider = <azureResource.IAzureResourceTreeDataProvider>this._treeDataProviders[resourceProviderId];
|
||||
treeDataProvider.browseConnectionMode = browseConnectionMode;
|
||||
const children = await treeDataProvider.getChildren(element);
|
||||
const children = <azureResource.IAzureResourceNode[]>await treeDataProvider.getChildren(element);
|
||||
|
||||
return children.map((child) => <IAzureResourceNodeWithProviderId>{
|
||||
resourceProviderId: resourceProviderId,
|
||||
@@ -72,15 +77,16 @@ export class AzureResourceService {
|
||||
});
|
||||
}
|
||||
|
||||
public async getTreeItem(resourceProviderId: string, element: azureResource.IAzureResourceNode): Promise<TreeItem> {
|
||||
public async getAllChildren(account: AzureAccount, subscriptions: azureResource.AzureResourceSubscription[], browseConnectionMode: boolean = false): Promise<IAzureResourceNodeWithProviderId[]> {
|
||||
await this.ensureResourceProvidersRegistered();
|
||||
const treeDataProvider = <azureResource.IAzureUniversalTreeDataProvider>this._universalProvider?.getTreeDataProvider();
|
||||
treeDataProvider.browseConnectionMode = browseConnectionMode;
|
||||
const children = <azureResource.IAzureResourceNode[]>await treeDataProvider.getAllChildren(account, subscriptions);
|
||||
|
||||
if (!(resourceProviderId in this._resourceProviders)) {
|
||||
throw new Error(`Azure resource provider doesn't exist. Id: ${resourceProviderId}`);
|
||||
}
|
||||
|
||||
const treeDataProvider = this._treeDataProviders[resourceProviderId];
|
||||
return treeDataProvider.getResourceTreeItem(element);
|
||||
return children.map((child) => <IAzureResourceNodeWithProviderId>{
|
||||
resourceProviderId: UNIVERSAL_PROVIDER_ID,
|
||||
resourceNode: child
|
||||
});
|
||||
}
|
||||
|
||||
public get areResourceProvidersLoaded(): boolean {
|
||||
@@ -107,11 +113,14 @@ export class AzureResourceService {
|
||||
|
||||
if (extension.exports && extension.exports.provideResources) {
|
||||
for (const resourceProvider of <azureResource.IAzureResourceProvider[]>extension.exports.provideResources()) {
|
||||
if (resourceProvider) {
|
||||
if (resourceProvider && resourceProvider.providerId !== UNIVERSAL_PROVIDER_ID) {
|
||||
this.doRegisterResourceProvider(resourceProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (extension.exports && extension.exports.getUniversalProvider) {
|
||||
this._universalProvider = <azureResource.IAzureUniversalResourceProvider>extension.exports.getUniversalProvider();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,5 +131,4 @@ export class AzureResourceService {
|
||||
this._resourceProviders[resourceProvider.providerId] = resourceProvider;
|
||||
this._treeDataProviders[resourceProvider.providerId] = resourceProvider.getTreeDataProvider();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ export class AzureResourceResourceTreeNode extends TreeNode {
|
||||
}
|
||||
|
||||
public getTreeItem(): TreeItem | Promise<TreeItem> {
|
||||
return this._resourceService.getTreeItem(this.resourceNodeWithProviderId.resourceProviderId, this.resourceNodeWithProviderId.resourceNode);
|
||||
return this.resourceNodeWithProviderId.resourceNode.treeItem;
|
||||
}
|
||||
|
||||
public getNodeInfo(): NodeInfo {
|
||||
|
||||
@@ -63,7 +63,6 @@ export class ConnectionDialogTreeProvider implements vscode.TreeDataProvider<Tre
|
||||
for (const account of accounts) {
|
||||
try {
|
||||
const accountNode = new FlatAccountTreeNode(account, this.appContext, this);
|
||||
await accountNode.updateLabel();
|
||||
accountNodes.push(accountNode);
|
||||
}
|
||||
catch (error) {
|
||||
|
||||
@@ -43,8 +43,7 @@ export class FlatAccountTreeNode extends AzureResourceContainerTreeNodeBase {
|
||||
this.treeChangeHandler.notifyNodeChanged(this);
|
||||
});
|
||||
|
||||
this._loader.onLoadingStatusChanged(async () => {
|
||||
await this.updateLabel();
|
||||
this._loader.onLoadingStatusChanged(() => {
|
||||
this.treeChangeHandler.notifyNodeChanged(this);
|
||||
});
|
||||
}
|
||||
@@ -69,6 +68,7 @@ export class FlatAccountTreeNode extends AzureResourceContainerTreeNodeBase {
|
||||
|
||||
public async getChildren(): Promise<TreeNode[]> {
|
||||
if (this._isClearingCache) {
|
||||
await this.updateLabel();
|
||||
this._loader.start().catch(err => console.error('Error loading Azure FlatAccountTreeNodes ', err));
|
||||
this._isClearingCache = false;
|
||||
return [];
|
||||
@@ -183,7 +183,6 @@ class FlatAccountTreeNodeLoader {
|
||||
try {
|
||||
|
||||
// Authenticate to tenants to filter out subscriptions that are not accessible.
|
||||
|
||||
let tenants = this._account.properties.tenants;
|
||||
// Filter out tenants that we can't authenticate to.
|
||||
tenants = tenants.filter(async tenant => {
|
||||
@@ -209,21 +208,13 @@ class FlatAccountTreeNodeLoader {
|
||||
});
|
||||
}
|
||||
|
||||
const resourceProviderIds = await this._resourceService.listResourceProviderIds();
|
||||
for (const subscription of subscriptions) {
|
||||
for (const providerId of resourceProviderIds) {
|
||||
const resourceTypes = await this._resourceService.getRootChildren(providerId, this._account, subscription);
|
||||
for (const resourceType of resourceTypes) {
|
||||
const resources = await this._resourceService.getChildren(providerId, resourceType.resourceNode, true);
|
||||
if (resources?.length > 0) {
|
||||
this._nodes.push(...resources.map(dr => new AzureResourceResourceTreeNode(dr, this._accountNode, this.appContext)));
|
||||
this._nodes = this.nodes.sort((a, b) => {
|
||||
return a.getNodeInfo().label.localeCompare(b.getNodeInfo().label);
|
||||
});
|
||||
newNodesAvailable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
const resources = await this._resourceService.getAllChildren(this._account, subscriptions, true);
|
||||
if (resources?.length > 0) {
|
||||
this._nodes.push(...resources.map(dr => new AzureResourceResourceTreeNode(dr, this._accountNode, this.appContext)));
|
||||
this._nodes = this.nodes.sort((a, b) => {
|
||||
return a.getNodeInfo().label.localeCompare(b.getNodeInfo().label);
|
||||
});
|
||||
newNodesAvailable = true;
|
||||
}
|
||||
// Create "No Resources Found" message node if no resources found under azure account.
|
||||
if (this._nodes.length === 0) {
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
import * as Constants from '../constants';
|
||||
import { ResourceGraphClient } from '@azure/arm-resourcegraph';
|
||||
import { TokenCredentials } from '@azure/ms-rest-js';
|
||||
import * as azdata from 'azdata';
|
||||
import { AzureRestResponse, GetResourceGroupsResult, GetSubscriptionsResult, ResourceQueryResult, GetBlobContainersResult, GetFileSharesResult, HttpRequestMethod, GetLocationsResult, GetManagedDatabasesResult, CreateResourceGroupResult, GetBlobsResult, GetStorageAccountAccessKeyResult, AzureAccount, azureResource, AzureAccountProviderMetadata, AzureNetworkResponse } from 'azurecore';
|
||||
import { EOL } from 'os';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { AppContext } from '../appContext';
|
||||
import { invalidAzureAccount, invalidTenant, unableToFetchTokenError } from '../localizedConstants';
|
||||
import { AzureResourceServiceNames } from './constants';
|
||||
@@ -16,12 +18,36 @@ import { IAzureResourceSubscriptionFilterService, IAzureResourceSubscriptionServ
|
||||
import { AzureResourceGroupService } from './providers/resourceGroup/resourceGroupService';
|
||||
import { BlobServiceClient, StorageSharedKeyCredential } from '@azure/storage-blob';
|
||||
import providerSettings from '../account-provider/providerSettings';
|
||||
import * as Constants from '../constants';
|
||||
import { getProxyEnabledHttpClient } from '../utils';
|
||||
import { HttpClient } from '../account-provider/auths/httpClient';
|
||||
import { NetworkRequestOptions } from '@azure/msal-common';
|
||||
import { ErrorResponseBody } from '@azure/arm-subscriptions/esm/models';
|
||||
import { TenantIgnoredError } from '../utils/TenantIgnoredError';
|
||||
import { AzureMonitorResourceService } from './providers/azuremonitor/azuremonitorService';
|
||||
import { AzureMonitorTreeDataProvider } from './providers/azuremonitor/azuremonitorTreeDataProvider';
|
||||
import { CosmosDbMongoService } from './providers/cosmosdb/mongo/cosmosDbMongoService';
|
||||
import { CosmosDbMongoTreeDataProvider } from './providers/cosmosdb/mongo/cosmosDbMongoTreeDataProvider';
|
||||
import { AzureResourceDatabaseService } from './providers/database/databaseService';
|
||||
import { AzureResourceDatabaseTreeDataProvider } from './providers/database/databaseTreeDataProvider';
|
||||
import { AzureResourceDatabaseServerService } from './providers/databaseServer/databaseServerService';
|
||||
import { AzureResourceDatabaseServerTreeDataProvider } from './providers/databaseServer/databaseServerTreeDataProvider';
|
||||
import { KustoResourceService } from './providers/kusto/kustoService';
|
||||
import { KustoTreeDataProvider } from './providers/kusto/kustoTreeDataProvider';
|
||||
import { MysqlFlexibleServerService } from './providers/mysqlFlexibleServer/mysqlFlexibleServerService';
|
||||
import { MysqlFlexibleServerTreeDataProvider } from './providers/mysqlFlexibleServer/mysqlFlexibleServerTreeDataProvider';
|
||||
import { PostgresServerArcService } from './providers/postgresArcServer/postgresArcServerService';
|
||||
import { PostgresServerArcTreeDataProvider } from './providers/postgresArcServer/postgresArcServerTreeDataProvider';
|
||||
import { PostgresServerService } from './providers/postgresServer/postgresServerService';
|
||||
import { PostgresServerTreeDataProvider } from './providers/postgresServer/postgresServerTreeDataProvider';
|
||||
import { ResourceProvider } from './providers/resourceProvider';
|
||||
import { SqlInstanceResourceService } from './providers/sqlinstance/sqlInstanceService';
|
||||
import { SqlInstanceTreeDataProvider } from './providers/sqlinstance/sqlInstanceTreeDataProvider';
|
||||
import { SqlInstanceArcResourceService } from './providers/sqlinstanceArc/sqlInstanceArcService';
|
||||
import { SqlInstanceArcTreeDataProvider } from './providers/sqlinstanceArc/sqlInstanceArcTreeDataProvider';
|
||||
import { AzureResourceSynapseService } from './providers/synapseSqlPool/synapseSqlPoolService';
|
||||
import { AzureResourceSynapseSqlPoolTreeDataProvider } from './providers/synapseSqlPool/synapseSqlPoolTreeDataProvider';
|
||||
import { AzureResourceSynapseWorkspaceService } from './providers/synapseWorkspace/synapseWorkspaceService';
|
||||
import { AzureResourceSynapseWorkspaceTreeDataProvider } from './providers/synapseWorkspace/synapseWorkspaceTreeDataProvider';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -233,6 +259,30 @@ export async function getLocations(appContext: AppContext, account?: AzureAccoun
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getAllResourceProviders(extensionContext: vscode.ExtensionContext): azureResource.IAzureResourceProvider[] {
|
||||
const arcFeaturedEnabled = vscode.workspace.getConfiguration(Constants.AzureSection).get(Constants.EnableArcFeaturesSection);
|
||||
const providers: azureResource.IAzureResourceProvider[] = [
|
||||
new ResourceProvider(Constants.AZURE_MONITOR_PROVIDER_ID, new AzureMonitorTreeDataProvider(new AzureMonitorResourceService(), extensionContext)),
|
||||
new ResourceProvider(Constants.COSMOSDB_MONGO_PROVIDER_ID, new CosmosDbMongoTreeDataProvider(new CosmosDbMongoService(), extensionContext)),
|
||||
new ResourceProvider(Constants.DATABASE_PROVIDER_ID, new AzureResourceDatabaseTreeDataProvider(new AzureResourceDatabaseService(), extensionContext)),
|
||||
new ResourceProvider(Constants.DATABASE_SERVER_PROVIDER_ID, new AzureResourceDatabaseServerTreeDataProvider(new AzureResourceDatabaseServerService(), extensionContext)),
|
||||
new ResourceProvider(Constants.KUSTO_PROVIDER_ID, new KustoTreeDataProvider(new KustoResourceService(), extensionContext)),
|
||||
new ResourceProvider(Constants.MYSQL_FLEXIBLE_SERVER_PROVIDER_ID, new MysqlFlexibleServerTreeDataProvider(new MysqlFlexibleServerService(), extensionContext)),
|
||||
new ResourceProvider(Constants.POSTGRES_SERVER_PROVIDER_ID, new PostgresServerTreeDataProvider(new PostgresServerService(), extensionContext)),
|
||||
new ResourceProvider(Constants.SQLINSTANCE_PROVIDER_ID, new SqlInstanceTreeDataProvider(new SqlInstanceResourceService(), extensionContext)),
|
||||
new ResourceProvider(Constants.SYNAPSE_SQL_POOL_PROVIDER_ID, new AzureResourceSynapseSqlPoolTreeDataProvider(new AzureResourceSynapseService(), extensionContext)),
|
||||
new ResourceProvider(Constants.SYNAPSE_WORKSPACE_PROVIDER_ID, new AzureResourceSynapseWorkspaceTreeDataProvider(new AzureResourceSynapseWorkspaceService(), extensionContext)),
|
||||
];
|
||||
|
||||
if (arcFeaturedEnabled) {
|
||||
providers.push(
|
||||
new ResourceProvider(Constants.SQLINSTANCE_ARC_PROVIDER_ID, new SqlInstanceArcTreeDataProvider(new SqlInstanceArcResourceService(), extensionContext)),
|
||||
new ResourceProvider(Constants.POSTGRES_ARC_SERVER_PROVIDER_ID, new PostgresServerArcTreeDataProvider(new PostgresServerArcService(), extensionContext))
|
||||
);
|
||||
}
|
||||
return providers;
|
||||
}
|
||||
|
||||
export async function runResourceQuery<T extends azureResource.AzureGraphResource>(
|
||||
account: AzureAccount,
|
||||
subscriptions: azureResource.AzureResourceSubscription[],
|
||||
|
||||
27
extensions/azurecore/src/azurecore.d.ts
vendored
27
extensions/azurecore/src/azurecore.d.ts
vendored
@@ -6,6 +6,7 @@
|
||||
declare module 'azurecore' {
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import * as msRest from '@azure/ms-rest-js';
|
||||
import { BlobItem } from '@azure/storage-blob';
|
||||
|
||||
/**
|
||||
@@ -327,6 +328,7 @@ declare module 'azurecore' {
|
||||
getRegionDisplayName(region?: string): string;
|
||||
getProviderMetadataForAccount(account: AzureAccount): AzureAccountProviderMetadata;
|
||||
provideResources(): azureResource.IAzureResourceProvider[];
|
||||
getUniversalProvider(): azureResource.IAzureUniversalResourceProvider;
|
||||
runGraphQuery<T extends azureResource.AzureGraphResource>(account: AzureAccount, subscriptions: azureResource.AzureResourceSubscription[], ignoreErrors: boolean, query: string): Promise<ResourceQueryResult<T>>;
|
||||
/**
|
||||
* Event emitted when MSAL cache encryption keys are updated in credential store.
|
||||
@@ -383,11 +385,23 @@ declare module 'azurecore' {
|
||||
mysqlFlexibleServer = 'microsoft.dbformysql/flexibleservers'
|
||||
}
|
||||
|
||||
export interface IAzureUniversalTreeDataProvider extends IAzureResourceTreeDataProvider {
|
||||
/**
|
||||
* Gets all the children for user account for provided subscription list.
|
||||
*/
|
||||
getAllChildren(account: AzureAccount, subscriptions: azureResource.AzureResourceSubscription[]): Promise<IAzureResourceNode[]>;
|
||||
}
|
||||
|
||||
export interface IAzureUniversalResourceProvider extends IAzureResourceProvider {
|
||||
getTreeDataProvider(): IAzureUniversalTreeDataProvider;
|
||||
}
|
||||
|
||||
export interface IAzureResourceProvider extends azdata.DataProvider {
|
||||
getTreeDataProvider(): IAzureResourceTreeDataProvider;
|
||||
}
|
||||
|
||||
export interface IAzureResourceTreeDataProvider {
|
||||
getService(): azureResource.IAzureResourceService;
|
||||
/**
|
||||
* Gets the root tree item nodes for this provider - these will be used as
|
||||
* direct children of the Account node in the Azure tree view.
|
||||
@@ -399,10 +413,11 @@ declare module 'azurecore' {
|
||||
*/
|
||||
getChildren(element: IAzureResourceNode): Promise<IAzureResourceNode[]>;
|
||||
/**
|
||||
* Gets the tree item to display for a given {@link IAzureResourceNode}
|
||||
* @param element The resource node to get the TreeItem for
|
||||
* Converts resource to VS Code treeItem
|
||||
* @param resource Azure resource to convert.
|
||||
* @param account User account
|
||||
*/
|
||||
getResourceTreeItem(element: IAzureResourceNode): Promise<azdata.TreeItem>;
|
||||
getTreeItemForResource(resource: azureResource.AzureResource, account: AzureAccount): vscode.TreeItem;
|
||||
browseConnectionMode: boolean;
|
||||
}
|
||||
|
||||
@@ -422,10 +437,16 @@ declare module 'azurecore' {
|
||||
name: string;
|
||||
id: string;
|
||||
subscription: IAzureSubscriptionInfo;
|
||||
provider?: string,
|
||||
resourceGroup?: string;
|
||||
tenant?: string;
|
||||
}
|
||||
|
||||
export interface IAzureResourceService {
|
||||
queryFilter: string;
|
||||
getResources(subscriptions: AzureResourceSubscription[], credential: msRest.ServiceClientCredentials, account: AzureAccount): Promise<AzureResource[]>;
|
||||
}
|
||||
|
||||
export interface AzureResourceSubscription extends Omit<AzureResource, 'subscription'> {
|
||||
}
|
||||
|
||||
|
||||
@@ -134,3 +134,18 @@ export enum Platform {
|
||||
Mac = 'darwin',
|
||||
Linux = 'linux'
|
||||
}
|
||||
|
||||
/////////////// Azure Resource provider Ids
|
||||
export const AZURE_MONITOR_PROVIDER_ID = 'azure.resource.providers.azureMonitor';
|
||||
export const COSMOSDB_MONGO_PROVIDER_ID = 'azure.resource.providers.cosmosDbMongo';
|
||||
export const DATABASE_PROVIDER_ID = 'azure.resource.providers.database';
|
||||
export const DATABASE_SERVER_PROVIDER_ID = 'azure.resource.providers.databaseServer';
|
||||
export const KUSTO_PROVIDER_ID = 'azure.resource.providers.azureDataExplorer';
|
||||
export const MYSQL_FLEXIBLE_SERVER_PROVIDER_ID = 'azure.resource.providers.mysqlFlexibleServer';
|
||||
export const POSTGRES_ARC_SERVER_PROVIDER_ID = 'azure.resource.providers.postgresArcServer';
|
||||
export const POSTGRES_SERVER_PROVIDER_ID = 'azure.resource.providers.postgresServer';
|
||||
export const SQLINSTANCE_PROVIDER_ID = 'azure.resource.providers.sqlInstance';
|
||||
export const SQLINSTANCE_ARC_PROVIDER_ID = 'azure.resource.providers.sqlInstanceArc';
|
||||
export const SYNAPSE_SQL_POOL_PROVIDER_ID = 'azure.resource.providers.synapseSqlPool';
|
||||
export const SYNAPSE_WORKSPACE_PROVIDER_ID = 'azure.resource.providers.synapseWorkspace';
|
||||
export const UNIVERSAL_PROVIDER_ID = 'azure.resource.providers.universal';
|
||||
|
||||
@@ -11,11 +11,6 @@ import * as os from 'os';
|
||||
|
||||
import { AppContext } from './appContext';
|
||||
import { AzureAccountProviderService } from './account-provider/azureAccountProviderService';
|
||||
|
||||
import { AzureResourceDatabaseServerProvider } from './azureResource/providers/databaseServer/databaseServerProvider';
|
||||
import { AzureResourceDatabaseServerService } from './azureResource/providers/databaseServer/databaseServerService';
|
||||
import { AzureResourceDatabaseProvider } from './azureResource/providers/database/databaseProvider';
|
||||
import { AzureResourceDatabaseService } from './azureResource/providers/database/databaseService';
|
||||
import { AzureResourceService } from './azureResource/resourceService';
|
||||
import { IAzureResourceCacheService, IAzureResourceSubscriptionService, IAzureResourceSubscriptionFilterService, IAzureTerminalService } from './azureResource/interfaces';
|
||||
import { AzureResourceServiceNames } from './azureResource/constants';
|
||||
@@ -24,23 +19,7 @@ import { AzureResourceSubscriptionFilterService } from './azureResource/services
|
||||
import { AzureResourceCacheService } from './azureResource/services/cacheService';
|
||||
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 { AzureMonitorResourceService } from './azureResource/providers/azuremonitor/azuremonitorService';
|
||||
import { AzureMonitorProvider } from './azureResource/providers/azuremonitor/azuremonitorProvider';
|
||||
import { PostgresServerProvider } from './azureResource/providers/postgresServer/postgresServerProvider';
|
||||
import { PostgresServerService } from './azureResource/providers/postgresServer/postgresServerService';
|
||||
import { AzureTerminalService } from './azureResource/services/terminalService';
|
||||
import { SqlInstanceArcProvider } from './azureResource/providers/sqlinstanceArc/sqlInstanceArcProvider';
|
||||
import { SqlInstanceArcResourceService } from './azureResource/providers/sqlinstanceArc/sqlInstanceArcService';
|
||||
import { PostgresServerArcProvider } from './azureResource/providers/postgresArcServer/postgresServerProvider';
|
||||
import { PostgresServerArcService } from './azureResource/providers/postgresArcServer/postgresServerService';
|
||||
import { CosmosDbMongoProvider } from './azureResource/providers/cosmosdb/mongo/cosmosDbMongoProvider';
|
||||
import { CosmosDbMongoService } from './azureResource/providers/cosmosdb/mongo/cosmosDbMongoService';
|
||||
import { MysqlFlexibleServerProvider } from './azureResource/providers/mysqlFlexibleServer/mysqlFlexibleServerProvider';
|
||||
import { MysqlFlexibleServerService } from './azureResource/providers/mysqlFlexibleServer/mysqlFlexibleServerService';
|
||||
import * as azurecore from 'azurecore';
|
||||
import * as azureResourceUtils from './azureResource/utils';
|
||||
import * as utils from './utils';
|
||||
@@ -50,10 +29,11 @@ import { AzureResourceGroupService } from './azureResource/providers/resourceGro
|
||||
import { Logger } from './utils/Logger';
|
||||
import { ConnectionDialogTreeProvider } from './azureResource/tree/connectionDialogTreeProvider';
|
||||
import { AzureDataGridProvider } from './azureDataGridProvider';
|
||||
import { AzureResourceSynapseSqlPoolProvider } from './azureResource/providers/synapseSqlPool/synapseSqlPoolProvider';
|
||||
import { AzureResourceSynapseWorkspaceProvider } from './azureResource/providers/synapseWorkspace/synapseWorkspaceProvider';
|
||||
import { AzureResourceSynapseWorkspaceService } from './azureResource/providers/synapseWorkspace/synapseWorkspaceService';
|
||||
import { AzureResourceSynapseService } from './azureResource/providers/synapseSqlPool/synapseSqlPoolService';
|
||||
// import { AzureResourceUniversalService } from './azureResource/providers/universal/universalService';
|
||||
import { AzureResourceUniversalService } from './azureResource/providers/universal/universalService';
|
||||
import { AzureResourceUniversalTreeDataProvider } from './azureResource/providers/universal/universalTreeDataProvider';
|
||||
import { AzureResourceUniversalResourceProvider } from './azureResource/providers/universal/universalProvider';
|
||||
// import { AzureResourceUniversalTreeDataProvider } from './azureResource/providers/universal/universalTreeDataProvider';
|
||||
|
||||
let extensionContext: vscode.ExtensionContext;
|
||||
|
||||
@@ -151,26 +131,15 @@ export async function activate(context: vscode.ExtensionContext): Promise<azurec
|
||||
return azureResourceUtils.getLocations(appContext, account, subscription, ignoreErrors);
|
||||
},
|
||||
provideResources(): azurecore.azureResource.IAzureResourceProvider[] {
|
||||
const arcFeaturedEnabled = vscode.workspace.getConfiguration(Constants.AzureSection).get(Constants.EnableArcFeaturesSection);
|
||||
const providers: azurecore.azureResource.IAzureResourceProvider[] = [
|
||||
new KustoProvider(new KustoResourceService(), extensionContext),
|
||||
new AzureMonitorProvider(new AzureMonitorResourceService(), extensionContext),
|
||||
new AzureResourceDatabaseServerProvider(new AzureResourceDatabaseServerService(), extensionContext),
|
||||
new AzureResourceDatabaseProvider(new AzureResourceDatabaseService(), extensionContext),
|
||||
new AzureResourceSynapseSqlPoolProvider(new AzureResourceSynapseService(), extensionContext),
|
||||
new AzureResourceSynapseWorkspaceProvider(new AzureResourceSynapseWorkspaceService(), extensionContext),
|
||||
new SqlInstanceProvider(new SqlInstanceResourceService(), extensionContext),
|
||||
new PostgresServerProvider(new PostgresServerService(), extensionContext),
|
||||
new CosmosDbMongoProvider(new CosmosDbMongoService(), extensionContext),
|
||||
new MysqlFlexibleServerProvider(new MysqlFlexibleServerService(), extensionContext)
|
||||
];
|
||||
if (arcFeaturedEnabled) {
|
||||
providers.push(
|
||||
new SqlInstanceArcProvider(new SqlInstanceArcResourceService(), extensionContext),
|
||||
new PostgresServerArcProvider(new PostgresServerArcService(), extensionContext)
|
||||
);
|
||||
}
|
||||
return providers;
|
||||
return azureResourceUtils.getAllResourceProviders(extensionContext);
|
||||
},
|
||||
getUniversalProvider(): azurecore.azureResource.IAzureUniversalResourceProvider {
|
||||
let providers = azureResourceUtils.getAllResourceProviders(extensionContext);
|
||||
let treeDataProviders = new Map<string, azurecore.azureResource.IAzureResourceTreeDataProvider>();
|
||||
providers.forEach(provider => {
|
||||
treeDataProviders.set(provider.providerId, provider.getTreeDataProvider());
|
||||
})
|
||||
return new AzureResourceUniversalResourceProvider(Constants.UNIVERSAL_PROVIDER_ID, new AzureResourceUniversalTreeDataProvider(new AzureResourceUniversalService(treeDataProviders)));
|
||||
},
|
||||
getSqlManagedInstances(account: azurecore.AzureAccount,
|
||||
subscriptions: azurecore.azureResource.AzureResourceSubscription[],
|
||||
|
||||
@@ -12,12 +12,12 @@ import 'mocha';
|
||||
|
||||
import { AzureResourceDatabaseTreeDataProvider } from '../../../../azureResource/providers/database/databaseTreeDataProvider';
|
||||
import { AzureResourceItemType } from '../../../../azureResource/constants';
|
||||
import { IAzureResourceService } from '../../../../azureResource/interfaces';
|
||||
import { AzureAccount, azureResource } from 'azurecore';
|
||||
import settings from '../../../../account-provider/providerSettings';
|
||||
import { DATABASE_PROVIDER_ID } from '../../../../constants';
|
||||
|
||||
// Mock services
|
||||
let mockDatabaseService: TypeMoq.IMock<IAzureResourceService<azureResource.AzureResourceDatabase>>;
|
||||
let mockDatabaseService: TypeMoq.IMock<azureResource.IAzureResourceService>;
|
||||
let mockExtensionContext: TypeMoq.IMock<vscode.ExtensionContext>;
|
||||
|
||||
// Mock test data
|
||||
@@ -76,6 +76,7 @@ const mockDatabases: azureResource.AzureResourceDatabase[] = [
|
||||
{
|
||||
name: 'mock database 1',
|
||||
id: 'mock-id-1',
|
||||
provider: DATABASE_PROVIDER_ID,
|
||||
serverName: 'mock database server 1',
|
||||
serverFullName: 'mock database server full name 1',
|
||||
loginName: 'mock login',
|
||||
@@ -88,6 +89,7 @@ const mockDatabases: azureResource.AzureResourceDatabase[] = [
|
||||
{
|
||||
name: 'mock database 2',
|
||||
id: 'mock-id-2',
|
||||
provider: DATABASE_PROVIDER_ID,
|
||||
serverName: 'mock database server 2',
|
||||
serverFullName: 'mock database server full name 2',
|
||||
loginName: 'mock login',
|
||||
@@ -101,14 +103,12 @@ const mockDatabases: azureResource.AzureResourceDatabase[] = [
|
||||
|
||||
describe('AzureResourceDatabaseTreeDataProvider.info', function (): void {
|
||||
beforeEach(() => {
|
||||
mockDatabaseService = TypeMoq.Mock.ofType<IAzureResourceService<azureResource.AzureResourceDatabase>>();
|
||||
mockDatabaseService = TypeMoq.Mock.ofType<azureResource.IAzureResourceService>();
|
||||
mockExtensionContext = TypeMoq.Mock.ofType<vscode.ExtensionContext>();
|
||||
});
|
||||
|
||||
it('Should be correct when created.', async function (): Promise<void> {
|
||||
const treeDataProvider = new AzureResourceDatabaseTreeDataProvider(mockDatabaseService.object, mockExtensionContext.object);
|
||||
|
||||
const treeItem = await treeDataProvider.getResourceTreeItem(mockResourceRootNode);
|
||||
const treeItem = mockResourceRootNode.treeItem;
|
||||
should(treeItem.id).equal(mockResourceRootNode.treeItem.id);
|
||||
should(treeItem.label).equal(mockResourceRootNode.treeItem.label);
|
||||
should(treeItem.collapsibleState).equal(mockResourceRootNode.treeItem.collapsibleState);
|
||||
@@ -118,7 +118,7 @@ describe('AzureResourceDatabaseTreeDataProvider.info', function (): void {
|
||||
|
||||
describe('AzureResourceDatabaseTreeDataProvider.getChildren', function (): void {
|
||||
beforeEach(() => {
|
||||
mockDatabaseService = TypeMoq.Mock.ofType<IAzureResourceService<azureResource.AzureResourceDatabase>>();
|
||||
mockDatabaseService = TypeMoq.Mock.ofType<azureResource.IAzureResourceService>();
|
||||
mockExtensionContext = TypeMoq.Mock.ofType<vscode.ExtensionContext>();
|
||||
|
||||
sinon.stub(azdata.accounts, 'getAccountSecurityToken').returns(Promise.resolve(mockToken));
|
||||
@@ -160,7 +160,7 @@ describe('AzureResourceDatabaseTreeDataProvider.getChildren', function (): void
|
||||
should(child.account).equal(mockAccount);
|
||||
should(child.subscription).equal(mockSubscription);
|
||||
should(child.tenantId).equal(mockTenantId);
|
||||
should(child.treeItem.id).equal(`databaseServer_${database.serverFullName}.database_${database.name}`);
|
||||
should(child.treeItem.id).equal(`databaseServer_${mockAccount.key.accountId}${database.serverFullName}.database_${database.id}`);
|
||||
should(child.treeItem.label).equal(`${database.name} (${database.serverName})`);
|
||||
should(child.treeItem.collapsibleState).equal(vscode.TreeItemCollapsibleState.Collapsed);
|
||||
should(child.treeItem.contextValue).equal(AzureResourceItemType.database);
|
||||
|
||||
@@ -12,13 +12,13 @@ import 'mocha';
|
||||
|
||||
import { AzureResourceDatabaseServerTreeDataProvider } from '../../../../azureResource/providers/databaseServer/databaseServerTreeDataProvider';
|
||||
import { AzureResourceItemType } from '../../../../azureResource/constants';
|
||||
import { IAzureResourceService } from '../../../../azureResource/interfaces';
|
||||
|
||||
// Mock services
|
||||
let mockDatabaseServerService: TypeMoq.IMock<IAzureResourceService<azureResource.AzureResourceDatabaseServer>>;
|
||||
let mockDatabaseServerService: TypeMoq.IMock<azureResource.IAzureResourceService>;
|
||||
let mockExtensionContext: TypeMoq.IMock<vscode.ExtensionContext>;
|
||||
import settings from '../../../../account-provider/providerSettings';
|
||||
import { AzureAccount, azureResource } from 'azurecore';
|
||||
import { DATABASE_SERVER_PROVIDER_ID } from '../../../../constants';
|
||||
|
||||
// Mock test data
|
||||
const mockAccount: AzureAccount = {
|
||||
@@ -75,6 +75,7 @@ const mockDatabaseServers: azureResource.AzureResourceDatabaseServer[] = [
|
||||
{
|
||||
name: 'mock database server 1',
|
||||
id: 'mock-id-1',
|
||||
provider: DATABASE_SERVER_PROVIDER_ID,
|
||||
fullName: 'mock database server full name 1',
|
||||
loginName: 'mock login',
|
||||
defaultDatabaseName: 'master',
|
||||
@@ -87,6 +88,7 @@ const mockDatabaseServers: azureResource.AzureResourceDatabaseServer[] = [
|
||||
{
|
||||
name: 'mock database server 2',
|
||||
id: 'mock-id-2',
|
||||
provider: DATABASE_SERVER_PROVIDER_ID,
|
||||
fullName: 'mock database server full name 2',
|
||||
loginName: 'mock login',
|
||||
defaultDatabaseName: 'master',
|
||||
@@ -100,14 +102,12 @@ const mockDatabaseServers: azureResource.AzureResourceDatabaseServer[] = [
|
||||
|
||||
describe('AzureResourceDatabaseServerTreeDataProvider.info', function (): void {
|
||||
beforeEach(() => {
|
||||
mockDatabaseServerService = TypeMoq.Mock.ofType<IAzureResourceService<azureResource.AzureResourceDatabaseServer>>();
|
||||
mockDatabaseServerService = TypeMoq.Mock.ofType<azureResource.IAzureResourceService>();
|
||||
mockExtensionContext = TypeMoq.Mock.ofType<vscode.ExtensionContext>();
|
||||
});
|
||||
|
||||
it('Should be correct when created.', async function (): Promise<void> {
|
||||
const treeDataProvider = new AzureResourceDatabaseServerTreeDataProvider(mockDatabaseServerService.object, mockExtensionContext.object);
|
||||
|
||||
const treeItem = await treeDataProvider.getResourceTreeItem(mockResourceRootNode);
|
||||
const treeItem = mockResourceRootNode.treeItem;
|
||||
should(treeItem.id).equal(mockResourceRootNode.treeItem.id);
|
||||
should(treeItem.label).equal(mockResourceRootNode.treeItem.label);
|
||||
should(treeItem.collapsibleState).equal(mockResourceRootNode.treeItem.collapsibleState);
|
||||
@@ -117,7 +117,7 @@ describe('AzureResourceDatabaseServerTreeDataProvider.info', function (): void {
|
||||
|
||||
describe('AzureResourceDatabaseServerTreeDataProvider.getChildren', function (): void {
|
||||
beforeEach(() => {
|
||||
mockDatabaseServerService = TypeMoq.Mock.ofType<IAzureResourceService<azureResource.AzureResourceDatabaseServer>>();
|
||||
mockDatabaseServerService = TypeMoq.Mock.ofType<azureResource.IAzureResourceService>();
|
||||
mockExtensionContext = TypeMoq.Mock.ofType<vscode.ExtensionContext>();
|
||||
|
||||
sinon.stub(azdata.accounts, 'getAccountSecurityToken').returns(Promise.resolve(mockToken));
|
||||
@@ -159,7 +159,7 @@ describe('AzureResourceDatabaseServerTreeDataProvider.getChildren', function ():
|
||||
should(child.account).equal(mockAccount);
|
||||
should(child.subscription).equal(mockSubscription);
|
||||
should(child.tenantId).equal(mockTenantId);
|
||||
should(child.treeItem.id).equal(`databaseServer_${databaseServer.id}`);
|
||||
should(child.treeItem.id).equal(`databaseServer_${mockAccount.key.accountId}${databaseServer.id}`);
|
||||
should(child.treeItem.label).equal(databaseServer.name);
|
||||
should(child.treeItem.collapsibleState).equal(vscode.TreeItemCollapsibleState.Collapsed);
|
||||
should(child.treeItem.contextValue).equal(AzureResourceItemType.databaseServer);
|
||||
|
||||
@@ -58,14 +58,12 @@ describe('AzureResourceService.listResourceProviderIds', function (): void {
|
||||
beforeEach(() => {
|
||||
mockResourceTreeDataProvider1 = TypeMoq.Mock.ofType<azureResource.IAzureResourceTreeDataProvider>();
|
||||
mockResourceTreeDataProvider1.setup((o) => o.getRootChildren()).returns(() => Promise.resolve([TypeMoq.Mock.ofType<azdata.TreeItem>().object]));
|
||||
mockResourceTreeDataProvider1.setup((o) => o.getResourceTreeItem(TypeMoq.It.isAny())).returns(() => Promise.resolve(TypeMoq.It.isAny()));
|
||||
mockResourceProvider1 = TypeMoq.Mock.ofType<azureResource.IAzureResourceProvider>();
|
||||
mockResourceProvider1.setup((o) => o.providerId).returns(() => 'mockResourceProvider1');
|
||||
mockResourceProvider1.setup((o) => o.getTreeDataProvider()).returns(() => mockResourceTreeDataProvider1.object);
|
||||
|
||||
mockResourceTreeDataProvider2 = TypeMoq.Mock.ofType<azureResource.IAzureResourceTreeDataProvider>();
|
||||
mockResourceTreeDataProvider2.setup((o) => o.getRootChildren()).returns(() => Promise.resolve([TypeMoq.Mock.ofType<azdata.TreeItem>().object]));
|
||||
mockResourceTreeDataProvider2.setup((o) => o.getResourceTreeItem(TypeMoq.It.isAny())).returns(() => Promise.resolve(TypeMoq.It.isAny()));
|
||||
mockResourceProvider2 = TypeMoq.Mock.ofType<azureResource.IAzureResourceProvider>();
|
||||
mockResourceProvider2.setup((o) => o.providerId).returns(() => 'mockResourceProvider2');
|
||||
mockResourceProvider2.setup((o) => o.getTreeDataProvider()).returns(() => mockResourceTreeDataProvider2.object);
|
||||
@@ -95,7 +93,6 @@ describe('AzureResourceService.getRootChildren', function (): void {
|
||||
beforeEach(() => {
|
||||
mockResourceTreeDataProvider1 = TypeMoq.Mock.ofType<azureResource.IAzureResourceTreeDataProvider>();
|
||||
mockResourceTreeDataProvider1.setup((o) => o.getRootChildren()).returns(() => Promise.resolve([TypeMoq.Mock.ofType<azdata.TreeItem>().object]));
|
||||
mockResourceTreeDataProvider1.setup((o) => o.getResourceTreeItem(TypeMoq.It.isAny())).returns(() => Promise.resolve(TypeMoq.It.isAny()));
|
||||
mockResourceProvider1 = TypeMoq.Mock.ofType<azureResource.IAzureResourceProvider>();
|
||||
mockResourceProvider1.setup((o) => o.providerId).returns(() => 'mockResourceProvider1');
|
||||
mockResourceProvider1.setup((o) => o.getTreeDataProvider()).returns(() => mockResourceTreeDataProvider1.object);
|
||||
@@ -129,7 +126,6 @@ describe('AzureResourceService.getChildren', function (): void {
|
||||
mockResourceTreeDataProvider1 = TypeMoq.Mock.ofType<azureResource.IAzureResourceTreeDataProvider>();
|
||||
mockResourceTreeDataProvider1.setup((o) => o.getRootChildren()).returns(() => Promise.resolve([TypeMoq.Mock.ofType<azdata.TreeItem>().object]));
|
||||
mockResourceTreeDataProvider1.setup((o) => o.getChildren(TypeMoq.It.isAny())).returns(() => Promise.resolve([TypeMoq.Mock.ofType<azureResource.IAzureResourceNode>().object]));
|
||||
mockResourceTreeDataProvider1.setup((o) => o.getResourceTreeItem(TypeMoq.It.isAny())).returns(() => Promise.resolve(TypeMoq.It.isAny()));
|
||||
mockResourceProvider1 = TypeMoq.Mock.ofType<azureResource.IAzureResourceProvider>();
|
||||
mockResourceProvider1.setup((o) => o.providerId).returns(() => 'mockResourceProvider1');
|
||||
mockResourceProvider1.setup((o) => o.getTreeDataProvider()).returns(() => mockResourceTreeDataProvider1.object);
|
||||
@@ -156,36 +152,3 @@ describe('AzureResourceService.getChildren', function (): void {
|
||||
fail();
|
||||
});
|
||||
});
|
||||
|
||||
describe('AzureResourceService.getTreeItem', function (): void {
|
||||
beforeEach(() => {
|
||||
mockResourceTreeDataProvider1 = TypeMoq.Mock.ofType<azureResource.IAzureResourceTreeDataProvider>();
|
||||
mockResourceTreeDataProvider1.setup((o) => o.getRootChildren()).returns(() => Promise.resolve([TypeMoq.Mock.ofType<azdata.TreeItem>().object]));
|
||||
mockResourceTreeDataProvider1.setup((o) => o.getChildren(TypeMoq.It.isAny())).returns(() => Promise.resolve([TypeMoq.Mock.ofType<azureResource.IAzureResourceNode>().object]));
|
||||
mockResourceTreeDataProvider1.setup((o) => o.getResourceTreeItem(TypeMoq.It.isAny())).returns(() => Promise.resolve(TypeMoq.It.isAny()));
|
||||
mockResourceProvider1 = TypeMoq.Mock.ofType<azureResource.IAzureResourceProvider>();
|
||||
mockResourceProvider1.setup((o) => o.providerId).returns(() => 'mockResourceProvider1');
|
||||
mockResourceProvider1.setup((o) => o.getTreeDataProvider()).returns(() => mockResourceTreeDataProvider1.object);
|
||||
|
||||
resourceService.clearResourceProviders();
|
||||
resourceService.registerResourceProvider(mockResourceProvider1.object);
|
||||
resourceService.areResourceProvidersLoaded = true;
|
||||
});
|
||||
|
||||
it('Should be correct when provider id is correct.', async function (): Promise<void> {
|
||||
const treeItem = await resourceService.getTreeItem(mockResourceProvider1.object.providerId, TypeMoq.It.isAny());
|
||||
should(treeItem).Object();
|
||||
});
|
||||
|
||||
it('Should throw exceptions when provider id is incorrect.', async function (): Promise<void> {
|
||||
const providerId = 'non_existent_provider_id';
|
||||
try {
|
||||
await resourceService.getRootChildren(providerId, mockAccount, mockSubscription);
|
||||
} catch (error) {
|
||||
should(error.message).equal(`Azure resource provider doesn't exist. Id: ${providerId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
fail();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -101,7 +101,6 @@ let appContext: AppContext;
|
||||
describe('AzureResourceResourceTreeNode.info', function (): void {
|
||||
beforeEach(() => {
|
||||
mockResourceTreeDataProvider = TypeMoq.Mock.ofType<azureResource.IAzureResourceTreeDataProvider>();
|
||||
mockResourceTreeDataProvider.setup((o) => o.getResourceTreeItem(mockResourceRootNode)).returns(() => Promise.resolve(mockResourceRootNode.treeItem));
|
||||
mockResourceTreeDataProvider.setup((o) => o.getChildren(mockResourceRootNode)).returns(() => Promise.resolve(mockResourceNodes));
|
||||
|
||||
mockResourceProvider = TypeMoq.Mock.ofType<azureResource.IAzureResourceProvider>();
|
||||
|
||||
@@ -61,7 +61,7 @@ let mockResourceProvider2: TypeMoq.IMock<azureResource.IAzureResourceProvider>;
|
||||
|
||||
const resourceService: AzureResourceService = new AzureResourceService();
|
||||
|
||||
describe('AzureResourceSubscriptionTreeNode.info', function(): void {
|
||||
describe('AzureResourceSubscriptionTreeNode.info', function (): void {
|
||||
beforeEach(() => {
|
||||
mockExtensionContext = TypeMoq.Mock.ofType<vscode.ExtensionContext>();
|
||||
mockCacheService = TypeMoq.Mock.ofType<IAzureResourceCacheService>();
|
||||
@@ -95,7 +95,7 @@ describe('AzureResourceSubscriptionTreeNode.info', function(): void {
|
||||
|
||||
});
|
||||
|
||||
it('Should be correct when created.', async function(): Promise<void> {
|
||||
it('Should be correct when created.', async function (): Promise<void> {
|
||||
const subscriptionTreeNode = new AzureResourceSubscriptionTreeNode(mockAccount, mockSubscription, mockTenantId, appContext, mockTreeChangeHandler.object, TypeMoq.Mock.ofType<TreeNode>().object);
|
||||
|
||||
should(subscriptionTreeNode.nodePathValue).equal(`account_${mockAccount.key.accountId}.subscription_${mockSubscription.id}.tenant_${mockTenantId}`);
|
||||
@@ -113,7 +113,7 @@ describe('AzureResourceSubscriptionTreeNode.info', function(): void {
|
||||
});
|
||||
});
|
||||
|
||||
describe('AzureResourceSubscriptionTreeNode.getChildren', function(): void {
|
||||
describe('AzureResourceSubscriptionTreeNode.getChildren', function (): void {
|
||||
beforeEach(() => {
|
||||
mockExtensionContext = TypeMoq.Mock.ofType<vscode.ExtensionContext>();
|
||||
mockCacheService = TypeMoq.Mock.ofType<IAzureResourceCacheService>();
|
||||
@@ -123,8 +123,7 @@ describe('AzureResourceSubscriptionTreeNode.getChildren', function(): void {
|
||||
mockTreeChangeHandler = TypeMoq.Mock.ofType<IAzureResourceTreeChangeHandler>();
|
||||
|
||||
mockResourceTreeDataProvider1 = TypeMoq.Mock.ofType<azureResource.IAzureResourceTreeDataProvider>();
|
||||
mockResourceTreeDataProvider1.setup((o) => o.getRootChildren()).returns(() => Promise.resolve([{ label: 'Item1'}] as azdata.TreeItem[]));
|
||||
mockResourceTreeDataProvider1.setup((o) => o.getResourceTreeItem(TypeMoq.It.isAny())).returns(() => Promise.resolve(TypeMoq.It.isAny()));
|
||||
mockResourceTreeDataProvider1.setup((o) => o.getRootChildren()).returns(() => Promise.resolve([{ label: 'Item1' }] as azdata.TreeItem[]));
|
||||
|
||||
mockResourceProvider1 = TypeMoq.Mock.ofType<azureResource.IAzureResourceProvider>();
|
||||
mockResourceProvider1.setup((o) => o.providerId).returns(() => 'mockResourceProvider1');
|
||||
@@ -132,7 +131,6 @@ describe('AzureResourceSubscriptionTreeNode.getChildren', function(): void {
|
||||
|
||||
mockResourceTreeDataProvider2 = TypeMoq.Mock.ofType<azureResource.IAzureResourceTreeDataProvider>();
|
||||
mockResourceTreeDataProvider2.setup((o) => o.getRootChildren()).returns(() => Promise.resolve([{ label: 'Item2' }] as azdata.TreeItem[]));
|
||||
mockResourceTreeDataProvider2.setup((o) => o.getResourceTreeItem(TypeMoq.It.isAny())).returns(() => Promise.resolve(TypeMoq.It.isAny()));
|
||||
mockResourceProvider2 = TypeMoq.Mock.ofType<azureResource.IAzureResourceProvider>();
|
||||
mockResourceProvider2.setup((o) => o.providerId).returns(() => 'mockResourceProvider2');
|
||||
mockResourceProvider2.setup((o) => o.getTreeDataProvider()).returns(() => mockResourceTreeDataProvider2.object);
|
||||
@@ -148,7 +146,7 @@ describe('AzureResourceSubscriptionTreeNode.getChildren', function(): void {
|
||||
|
||||
});
|
||||
|
||||
it('Should return resource containers.', async function(): Promise<void> {
|
||||
it('Should return resource containers.', async function (): Promise<void> {
|
||||
const subscriptionTreeNode = new AzureResourceSubscriptionTreeNode(mockAccount, mockSubscription, mockTenantId, appContext, mockTreeChangeHandler.object, TypeMoq.Mock.ofType<TreeNode>().object);
|
||||
const children = await subscriptionTreeNode.getChildren();
|
||||
|
||||
|
||||
@@ -61,6 +61,9 @@ export class AzurecoreApiStub implements azurecore.IExtension {
|
||||
provideResources(): azurecore.azureResource.IAzureResourceProvider[] {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
getUniversalProvider(): azurecore.azureResource.IAzureUniversalResourceProvider {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
onEncryptionKeysUpdated: any
|
||||
getEncryptionKeys(): Promise<azurecore.CacheEncryptionKeys> {
|
||||
throw new Error('Method not implemented.');
|
||||
|
||||
Reference in New Issue
Block a user