mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Introduce Azure Synapse Analytics and Dedicated SQL Pools azure nodes (#21471)
This commit is contained in:
@@ -288,22 +288,22 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "azure.resource.azureview.refresh",
|
"command": "azure.resource.azureview.refresh",
|
||||||
"when": "viewItem =~ /^azure\\.resource\\.itemType\\.(?:account|subscription|databaseContainer|databaseServerContainer)$/",
|
"when": "viewItem =~ /^azure\\.resource\\.itemType\\.(?:account|subscription|databaseContainer|databaseServerContainer|synapseSqlPoolContainer|synapseWorkspaceContainer)$/",
|
||||||
"group": "inline"
|
"group": "inline"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "azure.resource.azureview.refresh",
|
"command": "azure.resource.azureview.refresh",
|
||||||
"when": "viewItem =~ /^azure\\.resource\\.itemType\\.(?:account|subscription|databaseContainer|databaseServerContainer)$/",
|
"when": "viewItem =~ /^azure\\.resource\\.itemType\\.(?:account|subscription|databaseContainer|databaseServerContainer|synapseSqlPoolContainer|synapseWorkspaceContainer)$/",
|
||||||
"group": "azurecore"
|
"group": "azurecore"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "azure.resource.connectsqlserver",
|
"command": "azure.resource.connectsqlserver",
|
||||||
"when": "viewItem == azure.resource.itemType.databaseServer || viewItem == azure.resource.itemType.database || viewItem == azure.resource.itemType.sqlInstance",
|
"when": "viewItem =~ /^azure\\.resource\\.itemType\\.(?:database|databaseServer|synapseSqlPool|synapseWorkspace|sqlInstance)$/",
|
||||||
"group": "inline"
|
"group": "inline"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "azure.resource.connectsqlserver",
|
"command": "azure.resource.connectsqlserver",
|
||||||
"when": "viewItem == azure.resource.itemType.databaseServer || viewItem == azure.resource.itemType.database || viewItem == azure.resource.itemType.sqlInstance",
|
"when": "viewItem =~ /^azure\\.resource\\.itemType\\.(?:database|databaseServer|synapseSqlPool|synapseWorkspace|sqlInstance)$/",
|
||||||
"group": "azurecore"
|
"group": "azurecore"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import * as utils from './utils';
|
|||||||
const typesClause = [
|
const typesClause = [
|
||||||
azureResource.AzureResourceType.sqlDatabase,
|
azureResource.AzureResourceType.sqlDatabase,
|
||||||
azureResource.AzureResourceType.sqlServer,
|
azureResource.AzureResourceType.sqlServer,
|
||||||
|
azureResource.AzureResourceType.sqlSynapseWorkspace,
|
||||||
|
azureResource.AzureResourceType.sqlSynapseSqlPool,
|
||||||
azureResource.AzureResourceType.sqlManagedInstance,
|
azureResource.AzureResourceType.sqlManagedInstance,
|
||||||
azureResource.AzureResourceType.postgresServer,
|
azureResource.AzureResourceType.postgresServer,
|
||||||
azureResource.AzureResourceType.azureArcService,
|
azureResource.AzureResourceType.azureArcService,
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ export enum AzureResourceItemType {
|
|||||||
database = 'azure.resource.itemType.database',
|
database = 'azure.resource.itemType.database',
|
||||||
databaseServerContainer = 'azure.resource.itemType.databaseServerContainer',
|
databaseServerContainer = 'azure.resource.itemType.databaseServerContainer',
|
||||||
databaseServer = 'azure.resource.itemType.databaseServer',
|
databaseServer = 'azure.resource.itemType.databaseServer',
|
||||||
|
synapseSqlPoolContainer = 'azure.resource.itemType.synapseSqlPoolContainer',
|
||||||
|
synapseSqlPool = 'azure.resource.itemType.synapseSqlPool',
|
||||||
|
synapseWorkspaceContainer = 'azure.resource.itemType.synapseWorkspaceContainer',
|
||||||
|
synapseWorkspace = 'azure.resource.itemType.synapseWorkspace',
|
||||||
azureDataExplorerContainer = 'azure.resource.itemType.azureDataExplorerContainer',
|
azureDataExplorerContainer = 'azure.resource.itemType.azureDataExplorerContainer',
|
||||||
azureDataExplorer = 'azure.resource.itemType.azureDataExplorer',
|
azureDataExplorer = 'azure.resource.itemType.azureDataExplorer',
|
||||||
sqlInstance = 'azure.resource.itemType.sqlInstance',
|
sqlInstance = 'azure.resource.itemType.sqlInstance',
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { azureResource } from 'azurecore';
|
import { azureResource } from 'azurecore';
|
||||||
|
import { logAnalyticsQuery } from '../queryStringConstants';
|
||||||
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
|
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
|
||||||
|
|
||||||
export interface AzureMonitorGraphData extends GraphData {
|
export interface AzureMonitorGraphData extends GraphData {
|
||||||
@@ -15,12 +16,10 @@ export interface AzureMonitorGraphData extends GraphData {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const instanceQuery = `where type == "${azureResource.AzureResourceType.logAnalytics}"`;
|
|
||||||
|
|
||||||
export class AzureMonitorResourceService extends ResourceServiceBase<AzureMonitorGraphData, azureResource.AzureResourceDatabaseServer> {
|
export class AzureMonitorResourceService extends ResourceServiceBase<AzureMonitorGraphData, azureResource.AzureResourceDatabaseServer> {
|
||||||
|
|
||||||
protected get query(): string {
|
protected get query(): string {
|
||||||
return instanceQuery;
|
return logAnalyticsQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected convertResource(resource: AzureMonitorGraphData): azureResource.AzureResourceDatabaseServer {
|
protected convertResource(resource: AzureMonitorGraphData): azureResource.AzureResourceDatabaseServer {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
import { ResourceServiceBase, GraphData } from '../../resourceTreeDataProviderBase';
|
import { ResourceServiceBase, GraphData } from '../../resourceTreeDataProviderBase';
|
||||||
import { azureResource } from 'azurecore';
|
import { azureResource } from 'azurecore';
|
||||||
|
import { cosmosMongoDbQuery } from '../../queryStringConstants';
|
||||||
|
|
||||||
|
|
||||||
interface DbServerGraphData extends GraphData {
|
interface DbServerGraphData extends GraphData {
|
||||||
@@ -15,12 +16,10 @@ interface DbServerGraphData extends GraphData {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const serversQuery = `where type == "${azureResource.AzureResourceType.cosmosDbAccount}" and kind == "MongoDB"`;
|
|
||||||
|
|
||||||
export class CosmosDbMongoService extends ResourceServiceBase<DbServerGraphData, azureResource.AzureResourceDatabaseServer> {
|
export class CosmosDbMongoService extends ResourceServiceBase<DbServerGraphData, azureResource.AzureResourceDatabaseServer> {
|
||||||
|
|
||||||
protected get query(): string {
|
protected get query(): string {
|
||||||
return serversQuery;
|
return cosmosMongoDbQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected convertResource(resource: DbServerGraphData): azureResource.AzureResourceDatabaseServer {
|
protected convertResource(resource: DbServerGraphData): azureResource.AzureResourceDatabaseServer {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
import { ExtensionContext } from 'vscode';
|
import { ExtensionContext } from 'vscode';
|
||||||
|
|
||||||
import { azureResource } from 'azurecore';
|
import { azureResource } from 'azurecore';
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
import { ServiceClientCredentials } from '@azure/ms-rest-js';
|
import { ServiceClientCredentials } from '@azure/ms-rest-js';
|
||||||
import { IAzureResourceService } from '../../interfaces';
|
import { IAzureResourceService } from '../../interfaces';
|
||||||
import { DbServerGraphData, SynapseWorkspaceGraphData } from '../databaseServer/databaseServerService';
|
import { DbServerGraphData } from '../databaseServer/databaseServerService';
|
||||||
import { synapseWorkspacesQuery, sqlServersQuery } from '../databaseServer/serverQueryStrings';
|
import { sqlServerQuery, sqlDatabaseQuery } from '../queryStringConstants';
|
||||||
import { ResourceGraphClient } from '@azure/arm-resourcegraph';
|
import { ResourceGraphClient } from '@azure/arm-resourcegraph';
|
||||||
import { queryGraphResources, GraphData } from '../resourceTreeDataProviderBase';
|
import { queryGraphResources, GraphData } from '../resourceTreeDataProviderBase';
|
||||||
import { AzureAccount, azureResource } from 'azurecore';
|
import { AzureAccount, azureResource } from 'azurecore';
|
||||||
@@ -19,69 +19,43 @@ export class AzureResourceDatabaseService implements IAzureResourceService<azure
|
|||||||
const databases: azureResource.AzureResourceDatabase[] = [];
|
const databases: azureResource.AzureResourceDatabase[] = [];
|
||||||
const resourceClient = new ResourceGraphClient(credential, { baseUri: account.properties.providerSettings.settings.armResource.endpoint });
|
const resourceClient = new ResourceGraphClient(credential, { baseUri: account.properties.providerSettings.settings.armResource.endpoint });
|
||||||
|
|
||||||
// Query servers, synapse workspaces, and databases in parallel (start all promises before waiting on the 1st)
|
// Query servers and databases in parallel (start all promises before waiting on the 1st)
|
||||||
let servers: DbServerGraphData[];
|
let serverQueryPromise = queryGraphResources<GraphData>(resourceClient, subscriptions, sqlServerQuery);
|
||||||
let synapseWorkspaces: SynapseWorkspaceGraphData[];
|
let dbQueryPromise = queryGraphResources<GraphData>(resourceClient, subscriptions, sqlDatabaseQuery);
|
||||||
let combined: (DbServerGraphData | SynapseWorkspaceGraphData)[] = [];
|
let servers: DbServerGraphData[] = await serverQueryPromise as DbServerGraphData[];
|
||||||
/**
|
|
||||||
* We need to get the list of servers minus the Synapse Workspaces,
|
|
||||||
* then we need to make another query to get them.
|
|
||||||
*
|
|
||||||
* This is done because the first query provides invalid endpoints for Synapse Workspaces
|
|
||||||
* While the second one provides them as one of its properties.
|
|
||||||
*
|
|
||||||
* They have to be processed in different ways as their structure differs
|
|
||||||
* in terms of properties. (See databaseServer/databaseServerService.ts for more info)
|
|
||||||
*
|
|
||||||
* Queries must be made separately due to union not being recognized by resourceGraph resource calls
|
|
||||||
*/
|
|
||||||
let synapseQueryPromise = queryGraphResources<GraphData>(resourceClient, subscriptions, synapseWorkspacesQuery);
|
|
||||||
let serverQueryPromise = queryGraphResources<GraphData>(resourceClient, subscriptions, sqlServersQuery);
|
|
||||||
let dbQueryPromise = queryGraphResources<GraphData>(resourceClient, subscriptions, `where type == "${azureResource.AzureResourceType.sqlDatabase}"`);
|
|
||||||
servers = await serverQueryPromise as DbServerGraphData[];
|
|
||||||
synapseWorkspaces = await synapseQueryPromise as SynapseWorkspaceGraphData[];
|
|
||||||
let dbByGraph: DatabaseGraphData[] = await dbQueryPromise as DatabaseGraphData[];
|
let dbByGraph: DatabaseGraphData[] = await dbQueryPromise as DatabaseGraphData[];
|
||||||
combined = combined.concat(servers).concat(synapseWorkspaces);
|
|
||||||
|
|
||||||
// Group servers by resource group, then merge DB results with servers so we
|
// Group servers by resource group, then merge DB results with servers so we
|
||||||
// can get the login name and server fully qualified name to use for connections
|
// can get the login name and server fully qualified name to use for connections
|
||||||
let rgMap = new Map<string, (DbServerGraphData | SynapseWorkspaceGraphData)[]>();
|
let rgMap = new Map<string, (DbServerGraphData)[]>();
|
||||||
combined.forEach(s => {
|
servers.forEach(s => {
|
||||||
if ((s as SynapseWorkspaceGraphData).properties.connectivityEndpoints) {
|
let serversForRg = rgMap.get(s.resourceGroup) || [];
|
||||||
// If the resource is a Synapse Workspace, we need to use the managedResourceGroupName
|
serversForRg.push(s);
|
||||||
// (any SQL pools inside will use this instead of the regular resource group associated with the workspace itself).
|
rgMap.set(s.resourceGroup, serversForRg);
|
||||||
let serversForRg = rgMap.get((s as SynapseWorkspaceGraphData).properties.managedResourceGroupName) || [];
|
|
||||||
serversForRg.push(s as SynapseWorkspaceGraphData);
|
|
||||||
rgMap.set((s as SynapseWorkspaceGraphData).properties.managedResourceGroupName, serversForRg);
|
|
||||||
} else {
|
|
||||||
let serversForRg = rgMap.get(s.resourceGroup) || [];
|
|
||||||
serversForRg.push(s);
|
|
||||||
rgMap.set(s.resourceGroup, serversForRg);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Match database ID. When calling exec [0] is full match, [1] is resource group name, [2] is server name
|
// Match database ID. When calling exec [0] is full match, [1] is resource group name, [2] is server name
|
||||||
const svrIdRegExp = new RegExp(`\/subscriptions\/.+\/resourceGroups\/(.+)\/providers\/Microsoft\.Sql\/servers\/(.+)\/databases\/.+`);
|
const svrIdRegExp = new RegExp(`\/subscriptions\/.+\/resourceGroups\/(.+)\/providers\/Microsoft\.Sql\/servers\/(.+)\/databases\/.+`);
|
||||||
|
const synapseDBRegExp = new RegExp(`\/subscriptions\/.+\/resourceGroups\/(.+)\/providers\/Microsoft\.Synapse\/workspaces\/(.+)\/databases\/.+`);
|
||||||
|
|
||||||
dbByGraph.forEach(db => {
|
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 info
|
||||||
let serversForRg = rgMap.get(db.resourceGroup);
|
let serversForRg = rgMap.get(db.resourceGroup);
|
||||||
if (serversForRg && !db.kind.endsWith('system') && svrIdRegExp.test(db.id)) {
|
if (serversForRg && !db.kind.endsWith('system') && (svrIdRegExp.test(db.id) || synapseDBRegExp.test(db.id))) {
|
||||||
const founds = svrIdRegExp.exec(db.id);
|
const founds = svrIdRegExp.exec(db.id) ?? synapseDBRegExp.exec(db.id);
|
||||||
if (!founds) {
|
if (!founds) {
|
||||||
console.warn(`Could not parse server name from ID ${db.id}`);
|
console.warn(`Could not parse server name from ID ${db.id}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const serverName = founds[2];
|
const serverName = founds[2];
|
||||||
let server = combined.find(s => s.name === serverName);
|
let server = servers.find(s => s.name === serverName);
|
||||||
if (server) {
|
if (server) {
|
||||||
databases.push({
|
databases.push({
|
||||||
name: db.name,
|
name: db.name,
|
||||||
id: db.id,
|
id: db.id,
|
||||||
serverName: server.name,
|
serverName: server.name,
|
||||||
// Determine if server object is for Synapse Workspace or not and get the needed property from the correct place.
|
serverFullName: server.properties.fullyQualifiedDomainName,
|
||||||
serverFullName: (server as SynapseWorkspaceGraphData).properties.connectivityEndpoints?.sql ?? (server as DbServerGraphData).properties.fullyQualifiedDomainName,
|
loginName: server.properties.administratorLogin,
|
||||||
loginName: (server as SynapseWorkspaceGraphData).properties.sqlAdministratorLogin ?? (server as DbServerGraphData).properties.administratorLogin,
|
|
||||||
subscription: {
|
subscription: {
|
||||||
id: db.subscriptionId,
|
id: db.subscriptionId,
|
||||||
name: (subscriptions.find(sub => sub.id === db.subscriptionId))?.name || ''
|
name: (subscriptions.find(sub => sub.id === db.subscriptionId))?.name || ''
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
import { ServiceClientCredentials } from '@azure/ms-rest-js';
|
import { ServiceClientCredentials } from '@azure/ms-rest-js';
|
||||||
import { ResourceGraphClient } from '@azure/arm-resourcegraph';
|
import { ResourceGraphClient } from '@azure/arm-resourcegraph';
|
||||||
import { GraphData, queryGraphResources } from '../resourceTreeDataProviderBase';
|
import { GraphData, queryGraphResources } from '../resourceTreeDataProviderBase';
|
||||||
|
import { sqlServerQuery } from '../queryStringConstants';
|
||||||
import { azureResource, AzureAccount } from 'azurecore';
|
import { azureResource, AzureAccount } from 'azurecore';
|
||||||
import { sqlServersQuery, synapseWorkspacesQuery } from './serverQueryStrings';
|
|
||||||
import { IAzureResourceService } from '../../interfaces';
|
import { IAzureResourceService } from '../../interfaces';
|
||||||
|
|
||||||
export interface DbServerGraphData extends GraphData {
|
export interface DbServerGraphData extends GraphData {
|
||||||
@@ -17,54 +17,14 @@ export interface DbServerGraphData extends GraphData {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 AzureResourceDatabaseServerService implements IAzureResourceService<azureResource.AzureResourceDatabaseServer> {
|
export class AzureResourceDatabaseServerService implements IAzureResourceService<azureResource.AzureResourceDatabaseServer> {
|
||||||
|
|
||||||
protected get query(): string {
|
|
||||||
return sqlServersQuery;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getResources(subscriptions: azureResource.AzureResourceSubscription[], credential: ServiceClientCredentials, account: AzureAccount): Promise<azureResource.AzureResourceDatabaseServer[]> {
|
public async getResources(subscriptions: azureResource.AzureResourceSubscription[], credential: ServiceClientCredentials, account: AzureAccount): Promise<azureResource.AzureResourceDatabaseServer[]> {
|
||||||
const convertedResources: azureResource.AzureResourceDatabaseServer[] = [];
|
const convertedResources: azureResource.AzureResourceDatabaseServer[] = [];
|
||||||
const resourceClient = new ResourceGraphClient(credential, { baseUri: account.properties.providerSettings.settings.armResource.endpoint });
|
const resourceClient = new ResourceGraphClient(credential, { baseUri: account.properties.providerSettings.settings.armResource.endpoint });
|
||||||
/**
|
let serverGraphResources: DbServerGraphData[] = await queryGraphResources<DbServerGraphData>(resourceClient, subscriptions, sqlServerQuery);
|
||||||
* We need to get the list of servers minus the Synapse Workspaces,
|
|
||||||
* then we need to make another query to get them.
|
|
||||||
*
|
|
||||||
* This is done because the first query provides invalid endpoints for Synapse Workspaces
|
|
||||||
* While the second one provides them as one of its properties.
|
|
||||||
*
|
|
||||||
* They have to be processed in different ways by convertResource as their structure differs
|
|
||||||
* in terms of properties. (See above)
|
|
||||||
*
|
|
||||||
* Queries must be made separately due to union not being recognized by resourceGraph resource calls.
|
|
||||||
*/
|
|
||||||
let combinedGraphResources: (DbServerGraphData | SynapseWorkspaceGraphData)[] = [];
|
|
||||||
let serverGraphResources: DbServerGraphData[] = await queryGraphResources<DbServerGraphData>(resourceClient, subscriptions, this.query);
|
|
||||||
let synapseGraphResources: SynapseWorkspaceGraphData[] = await queryGraphResources<SynapseWorkspaceGraphData>(resourceClient, subscriptions, synapseWorkspacesQuery);
|
|
||||||
combinedGraphResources = combinedGraphResources.concat(serverGraphResources).concat(synapseGraphResources);
|
|
||||||
const ids = new Set<string>();
|
const ids = new Set<string>();
|
||||||
combinedGraphResources.forEach((res) => {
|
serverGraphResources.forEach((res) => {
|
||||||
if (!ids.has(res.id)) {
|
if (!ids.has(res.id)) {
|
||||||
ids.add(res.id);
|
ids.add(res.id);
|
||||||
res.subscriptionName = subscriptions.find(sub => sub.id === res.subscriptionId)?.name;
|
res.subscriptionName = subscriptions.find(sub => sub.id === res.subscriptionId)?.name;
|
||||||
@@ -76,14 +36,14 @@ export class AzureResourceDatabaseServerService implements IAzureResourceService
|
|||||||
return convertedResources;
|
return convertedResources;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected convertResource(resource: DbServerGraphData | SynapseWorkspaceGraphData): azureResource.AzureResourceDatabaseServer {
|
protected convertResource(resource: DbServerGraphData): azureResource.AzureResourceDatabaseServer {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: resource.id,
|
id: resource.id,
|
||||||
name: resource.name,
|
name: resource.name,
|
||||||
// Determine if resource object is for Synapse Workspace or not and get the needed property from the correct place.
|
// Determine if resource object is for Synapse Workspace or not and get the needed property from the correct place.
|
||||||
fullName: (resource as SynapseWorkspaceGraphData).properties.connectivityEndpoints?.sql ?? (resource as DbServerGraphData).properties.fullyQualifiedDomainName,
|
fullName: resource.properties.fullyQualifiedDomainName,
|
||||||
loginName: (resource as SynapseWorkspaceGraphData).properties.sqlAdministratorLogin ?? (resource as DbServerGraphData).properties.administratorLogin,
|
loginName: resource.properties.administratorLogin,
|
||||||
defaultDatabaseName: 'master',
|
defaultDatabaseName: 'master',
|
||||||
subscription: {
|
subscription: {
|
||||||
id: resource.subscriptionId,
|
id: resource.subscriptionId,
|
||||||
|
|||||||
@@ -1,18 +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 { azureResource } from 'azurecore';
|
|
||||||
/**
|
|
||||||
* Get list of Synapse Workspaces with information such as SQL connection endpoints.
|
|
||||||
*/
|
|
||||||
export const synapseWorkspacesQuery = `where type == "microsoft.synapse/workspaces"`;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Lists all Sql Servers except for Synapse Pool Servers
|
|
||||||
* (they have different properties and need to be handled separately,
|
|
||||||
* see databaseServerService.ts for more details)
|
|
||||||
*/
|
|
||||||
export const sqlServersQuery = `where type == "${azureResource.AzureResourceType.sqlServer}" and kind != "v12.0,analytics"`;
|
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { azureResource } from 'azurecore';
|
import { azureResource } from 'azurecore';
|
||||||
|
import { kustoClusterQuery } from '../queryStringConstants';
|
||||||
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
|
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
|
||||||
|
|
||||||
export interface KustoGraphData extends GraphData {
|
export interface KustoGraphData extends GraphData {
|
||||||
@@ -14,12 +15,10 @@ export interface KustoGraphData extends GraphData {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const instanceQuery = `where type == "${azureResource.AzureResourceType.kustoClusters}"`;
|
|
||||||
|
|
||||||
export class KustoResourceService extends ResourceServiceBase<KustoGraphData, azureResource.AzureResourceDatabaseServer> {
|
export class KustoResourceService extends ResourceServiceBase<KustoGraphData, azureResource.AzureResourceDatabaseServer> {
|
||||||
|
|
||||||
protected get query(): string {
|
protected get query(): string {
|
||||||
return instanceQuery;
|
return kustoClusterQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected convertResource(resource: KustoGraphData): azureResource.AzureResourceDatabaseServer {
|
protected convertResource(resource: KustoGraphData): azureResource.AzureResourceDatabaseServer {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
|
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
|
||||||
import { azureResource } from 'azurecore';
|
import { azureResource } from 'azurecore';
|
||||||
|
import { mysqlFlexibleServerQuery } from '../queryStringConstants';
|
||||||
|
|
||||||
|
|
||||||
interface DbServerGraphData extends GraphData {
|
interface DbServerGraphData extends GraphData {
|
||||||
@@ -15,12 +16,10 @@ interface DbServerGraphData extends GraphData {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const serversQuery = `where type == "${azureResource.AzureResourceType.mysqlFlexibleServer}"`;
|
|
||||||
|
|
||||||
export class MysqlFlexibleServerService extends ResourceServiceBase<DbServerGraphData, azureResource.AzureResourceDatabaseServer> {
|
export class MysqlFlexibleServerService extends ResourceServiceBase<DbServerGraphData, azureResource.AzureResourceDatabaseServer> {
|
||||||
|
|
||||||
protected get query(): string {
|
protected get query(): string {
|
||||||
return serversQuery;
|
return mysqlFlexibleServerQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected convertResource(resource: DbServerGraphData): azureResource.AzureResourceDatabaseServer {
|
protected convertResource(resource: DbServerGraphData): azureResource.AzureResourceDatabaseServer {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
|
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
|
||||||
import { azureResource } from 'azurecore';
|
import { azureResource } from 'azurecore';
|
||||||
|
import { postgresArcServerQuery } from '../queryStringConstants';
|
||||||
|
|
||||||
export interface PostgresArcServerGraphData extends GraphData {
|
export interface PostgresArcServerGraphData extends GraphData {
|
||||||
properties: {
|
properties: {
|
||||||
@@ -12,12 +13,10 @@ export interface PostgresArcServerGraphData extends GraphData {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const serversQuery = `where type == "${azureResource.AzureResourceType.azureArcPostgresServer}"`;
|
|
||||||
|
|
||||||
export class PostgresServerArcService extends ResourceServiceBase<PostgresArcServerGraphData, azureResource.AzureResourceDatabaseServer> {
|
export class PostgresServerArcService extends ResourceServiceBase<PostgresArcServerGraphData, azureResource.AzureResourceDatabaseServer> {
|
||||||
|
|
||||||
protected get query(): string {
|
protected get query(): string {
|
||||||
return serversQuery;
|
return postgresArcServerQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected convertResource(resource: PostgresArcServerGraphData): azureResource.AzureResourceDatabaseServer {
|
protected convertResource(resource: PostgresArcServerGraphData): azureResource.AzureResourceDatabaseServer {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
|
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
|
||||||
import { azureResource } from 'azurecore';
|
import { azureResource } from 'azurecore';
|
||||||
|
import { postgresServerQuery } from '../queryStringConstants';
|
||||||
|
|
||||||
interface DbServerGraphData extends GraphData {
|
interface DbServerGraphData extends GraphData {
|
||||||
properties: {
|
properties: {
|
||||||
@@ -15,12 +15,10 @@ interface DbServerGraphData extends GraphData {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const serversQuery = `where type == "${azureResource.AzureResourceType.postgresServer}"`;
|
|
||||||
|
|
||||||
export class PostgresServerService extends ResourceServiceBase<DbServerGraphData, azureResource.AzureResourceDatabaseServer> {
|
export class PostgresServerService extends ResourceServiceBase<DbServerGraphData, azureResource.AzureResourceDatabaseServer> {
|
||||||
|
|
||||||
protected get query(): string {
|
protected get query(): string {
|
||||||
return serversQuery;
|
return postgresServerQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected convertResource(resource: DbServerGraphData): azureResource.AzureResourceDatabaseServer {
|
protected convertResource(resource: DbServerGraphData): azureResource.AzureResourceDatabaseServer {
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists all SQL Databases and Synapse SQL Databases
|
||||||
|
*/
|
||||||
|
export const sqlDatabaseQuery = `where 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}"`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists all Synapse Dedicated SQL Pools
|
||||||
|
*/
|
||||||
|
export const synapseSqlPoolsQuery = `where 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"`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists all Azure Arc SQL Managed Instances
|
||||||
|
*/
|
||||||
|
export const sqlInstanceArcQuery = `where type == "${azureResource.AzureResourceType.azureArcSqlManagedInstance}"`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists all Azure SQL Managed Instances
|
||||||
|
*/
|
||||||
|
export const sqlInstanceQuery = `where type == "${azureResource.AzureResourceType.sqlManagedInstance}"`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists all resource containers and resource groups
|
||||||
|
*/
|
||||||
|
export const resourceGroupQuery = `ResourceContainers | where type=="${azureResource.AzureResourceType.resourceGroup}"`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists all postgreSQL servers
|
||||||
|
*/
|
||||||
|
export const postgresServerQuery = `where type == "${azureResource.AzureResourceType.postgresServer}"`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists all Azure Arc PostgreSQL servers
|
||||||
|
*/
|
||||||
|
export const postgresArcServerQuery = `where type == "${azureResource.AzureResourceType.azureArcPostgresServer}"`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists all MySQL Flexible servers
|
||||||
|
*/
|
||||||
|
export const mysqlFlexibleServerQuery = `where type == "${azureResource.AzureResourceType.mysqlFlexibleServer}"`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists all Kusto Clusters
|
||||||
|
*/
|
||||||
|
export const kustoClusterQuery = `where type == "${azureResource.AzureResourceType.kustoClusters}"`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists all Cosmos DB for MongoDB accounts
|
||||||
|
*/
|
||||||
|
export const cosmosMongoDbQuery = `where type == "${azureResource.AzureResourceType.cosmosDbAccount}" and kind == "MongoDB"`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists all Log Analytics workspaces
|
||||||
|
*/
|
||||||
|
export const logAnalyticsQuery = `where type == "${azureResource.AzureResourceType.logAnalytics}"`;
|
||||||
@@ -6,11 +6,12 @@
|
|||||||
import { DbServerGraphData } from '../databaseServer/databaseServerService';
|
import { DbServerGraphData } from '../databaseServer/databaseServerService';
|
||||||
import { azureResource } from 'azurecore';
|
import { azureResource } from 'azurecore';
|
||||||
import { ResourceServiceBase } from '../resourceTreeDataProviderBase';
|
import { ResourceServiceBase } from '../resourceTreeDataProviderBase';
|
||||||
|
import { resourceGroupQuery } from '../queryStringConstants';
|
||||||
|
|
||||||
export class AzureResourceGroupService extends ResourceServiceBase<DbServerGraphData, azureResource.AzureResourceResourceGroup> {
|
export class AzureResourceGroupService extends ResourceServiceBase<DbServerGraphData, azureResource.AzureResourceResourceGroup> {
|
||||||
|
|
||||||
protected get query(): string {
|
protected get query(): string {
|
||||||
return `ResourceContainers | where type=="${azureResource.AzureResourceType.resourceGroup}"`;
|
return resourceGroupQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected convertResource(resource: DbServerGraphData): azureResource.AzureResourceResourceGroup {
|
protected convertResource(resource: DbServerGraphData): azureResource.AzureResourceResourceGroup {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { azureResource } from 'azurecore';
|
import { azureResource } from 'azurecore';
|
||||||
|
import { sqlInstanceQuery } from '../queryStringConstants';
|
||||||
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
|
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
|
||||||
|
|
||||||
interface SqlInstanceGraphData extends GraphData {
|
interface SqlInstanceGraphData extends GraphData {
|
||||||
@@ -13,12 +14,10 @@ interface SqlInstanceGraphData extends GraphData {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const instanceQuery = `where type == "${azureResource.AzureResourceType.sqlManagedInstance}"`;
|
|
||||||
|
|
||||||
export class SqlInstanceResourceService extends ResourceServiceBase<SqlInstanceGraphData, azureResource.AzureResourceDatabaseServer> {
|
export class SqlInstanceResourceService extends ResourceServiceBase<SqlInstanceGraphData, azureResource.AzureResourceDatabaseServer> {
|
||||||
|
|
||||||
protected get query(): string {
|
protected get query(): string {
|
||||||
return instanceQuery;
|
return sqlInstanceQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected convertResource(resource: SqlInstanceGraphData): azureResource.AzureResourceDatabaseServer {
|
protected convertResource(resource: SqlInstanceGraphData): azureResource.AzureResourceDatabaseServer {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
|
import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase';
|
||||||
import { azureResource } from 'azurecore';
|
import { azureResource } from 'azurecore';
|
||||||
|
import { sqlInstanceArcQuery } from '../queryStringConstants';
|
||||||
|
|
||||||
export interface SqlInstanceArcGraphData extends GraphData {
|
export interface SqlInstanceArcGraphData extends GraphData {
|
||||||
properties: {
|
properties: {
|
||||||
@@ -13,11 +14,10 @@ export interface SqlInstanceArcGraphData extends GraphData {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const instanceQuery = `where type == "${azureResource.AzureResourceType.azureArcSqlManagedInstance}"`;
|
|
||||||
export class SqlInstanceArcResourceService extends ResourceServiceBase<SqlInstanceArcGraphData, azureResource.AzureResourceDatabaseServer> {
|
export class SqlInstanceArcResourceService extends ResourceServiceBase<SqlInstanceArcGraphData, azureResource.AzureResourceDatabaseServer> {
|
||||||
|
|
||||||
protected get query(): string {
|
protected get query(): string {
|
||||||
return instanceQuery;
|
return sqlInstanceArcQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected convertResource(resource: SqlInstanceArcGraphData): azureResource.AzureResourceDatabaseServer {
|
protected convertResource(resource: SqlInstanceArcGraphData): azureResource.AzureResourceDatabaseServer {
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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 { IAzureResourceService } from '../../interfaces';
|
||||||
|
import { SynapseWorkspaceGraphData } from '../synapseWorkspace/synapseWorkspaceService';
|
||||||
|
import { synapseWorkspacesQuery, synapseSqlPoolsQuery } from '../queryStringConstants';
|
||||||
|
import { ResourceGraphClient } from '@azure/arm-resourcegraph';
|
||||||
|
import { queryGraphResources, GraphData } from '../resourceTreeDataProviderBase';
|
||||||
|
import { AzureAccount, azureResource } from 'azurecore';
|
||||||
|
|
||||||
|
interface SynapseGraphData extends GraphData {
|
||||||
|
kind: string;
|
||||||
|
}
|
||||||
|
export class AzureResourceSynapseService 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 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 synapse = await synapseQueryPromise as SynapseGraphData[];
|
||||||
|
let synapseWorkspaceByGraph: SynapseWorkspaceGraphData[] = await synapseWorkspaceQueryPromise as SynapseWorkspaceGraphData[];
|
||||||
|
|
||||||
|
// Group servers by resource group, then merge DB results with servers so we
|
||||||
|
// can get the login name and server fully qualified name to use for connections
|
||||||
|
let rgMap = new Map<string, SynapseWorkspaceGraphData[]>();
|
||||||
|
synapseWorkspaceByGraph.forEach(s => {
|
||||||
|
// As the resource is a Synapse Workspace, we need to use the managedResourceGroupName
|
||||||
|
// (any SQL pools inside will use this instead of the regular resource group associated with the workspace itself).
|
||||||
|
let serversForRg = rgMap.get(s.properties.managedResourceGroupName) || [];
|
||||||
|
serversForRg.push(s);
|
||||||
|
rgMap.set(s.properties.managedResourceGroupName, serversForRg);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Match database ID. When calling exec [0] is full match, [1] is resource group name, [2] is server name
|
||||||
|
const svrIdRegExp = new RegExp(`\/subscriptions\/.+\/resourceGroups\/(.+)\/providers\/Microsoft\.Synapse\/workspaces\/(.+)\/sqlPools\/.+`);
|
||||||
|
|
||||||
|
synapse.forEach(db => {
|
||||||
|
// Filter master DBs, and for all others find their server to get login info
|
||||||
|
if (!db.kind.endsWith('system') && svrIdRegExp.test(db.id)) {
|
||||||
|
const founds = svrIdRegExp.exec(db.id);
|
||||||
|
if (!founds) {
|
||||||
|
console.warn(`Could not parse server name from ID ${db.id}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return databases;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { TreeItem, ExtensionNodeType } from 'azdata';
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
import * as nls from 'vscode-nls';
|
||||||
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
|
import { AzureResourceItemType, mssqlProvider } from '../../constants';
|
||||||
|
import { generateGuid } from '../../utils';
|
||||||
|
import { IAzureResourceService } from '../../interfaces';
|
||||||
|
import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
|
||||||
|
import { AzureAccount, azureResource } from 'azurecore';
|
||||||
|
|
||||||
|
export class AzureResourceSynapseSqlPoolTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabase> {
|
||||||
|
|
||||||
|
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>,
|
||||||
|
private _extensionContext: vscode.ExtensionContext
|
||||||
|
) {
|
||||||
|
super(synapseSqlPoolService);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getTreeItemForResource(synapse: azureResource.AzureResourceDatabase, account: AzureAccount): TreeItem {
|
||||||
|
return {
|
||||||
|
id: `synapseWorkspace_${synapse.serverFullName}.synapseSqlPool_${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'),
|
||||||
|
light: this._extensionContext.asAbsolutePath('resources/light/sql_database.svg')
|
||||||
|
},
|
||||||
|
collapsibleState: this.browseConnectionMode ? vscode.TreeItemCollapsibleState.None : vscode.TreeItemCollapsibleState.Collapsed,
|
||||||
|
contextValue: AzureResourceItemType.synapseSqlPool,
|
||||||
|
payload: {
|
||||||
|
id: generateGuid(),
|
||||||
|
connectionName: undefined,
|
||||||
|
serverName: synapse.serverFullName,
|
||||||
|
databaseName: synapse.name,
|
||||||
|
userName: synapse.loginName,
|
||||||
|
password: '',
|
||||||
|
authenticationType: '',
|
||||||
|
savePassword: true,
|
||||||
|
groupFullName: '',
|
||||||
|
groupId: '',
|
||||||
|
providerName: mssqlProvider,
|
||||||
|
saveProfile: false,
|
||||||
|
options: {},
|
||||||
|
azureAccount: account.key.accountId,
|
||||||
|
azureResourceId: synapse.id,
|
||||||
|
azureTenantId: synapse.tenant,
|
||||||
|
azurePortalEndpoint: account.properties.providerSettings.settings.portalEndpoint
|
||||||
|
},
|
||||||
|
childProvider: mssqlProvider,
|
||||||
|
type: ExtensionNodeType.Database
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getRootChildren(): Promise<TreeItem[]> {
|
||||||
|
return [{
|
||||||
|
id: AzureResourceSynapseSqlPoolTreeDataProvider.containerId,
|
||||||
|
label: AzureResourceSynapseSqlPoolTreeDataProvider.containerLabel,
|
||||||
|
iconPath: {
|
||||||
|
dark: this._extensionContext.asAbsolutePath('resources/dark/folder_inverse.svg'),
|
||||||
|
light: this._extensionContext.asAbsolutePath('resources/light/folder.svg')
|
||||||
|
},
|
||||||
|
collapsibleState: vscode.TreeItemCollapsibleState.Collapsed,
|
||||||
|
contextValue: AzureResourceItemType.synapseSqlPoolContainer
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { ExtensionContext } from 'vscode';
|
||||||
|
|
||||||
|
import { azureResource } from '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';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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 { GraphData, queryGraphResources } from '../resourceTreeDataProviderBase';
|
||||||
|
import { azureResource, AzureAccount } from 'azurecore';
|
||||||
|
import { IAzureResourceService } from '../../interfaces';
|
||||||
|
import { synapseWorkspacesQuery } from '../queryStringConstants';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 IAzureResourceService<azureResource.AzureResourceDatabaseServer> {
|
||||||
|
|
||||||
|
protected get query(): string {
|
||||||
|
return 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);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return convertedResources;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected convertResource(resource: SynapseWorkspaceGraphData): azureResource.AzureResourceDatabaseServer {
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: resource.id,
|
||||||
|
name: resource.name,
|
||||||
|
fullName: resource.properties.connectivityEndpoints?.sql,
|
||||||
|
loginName: resource.properties.sqlAdministratorLogin,
|
||||||
|
defaultDatabaseName: 'master',
|
||||||
|
subscription: {
|
||||||
|
id: resource.subscriptionId,
|
||||||
|
name: resource.subscriptionName || ''
|
||||||
|
},
|
||||||
|
tenant: resource.tenantId,
|
||||||
|
resourceGroup: resource.resourceGroup
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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 { ExtensionNodeType, TreeItem } from 'azdata';
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
import * as nls from 'vscode-nls';
|
||||||
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
|
import { AzureResourceItemType, mssqlProvider } from '../../constants';
|
||||||
|
import { generateGuid } from '../../utils';
|
||||||
|
import { IAzureResourceService } from '../../interfaces';
|
||||||
|
import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
|
||||||
|
import { AzureAccount, azureResource } from 'azurecore';
|
||||||
|
|
||||||
|
export class AzureResourceSynapseWorkspaceTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> {
|
||||||
|
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>,
|
||||||
|
private _extensionContext: vscode.ExtensionContext
|
||||||
|
) {
|
||||||
|
super(synapseWorkspaceService);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getTreeItemForResource(synapseWorkspace: azureResource.AzureResourceDatabaseServer, account: AzureAccount): TreeItem {
|
||||||
|
return {
|
||||||
|
id: `synapseWorkspace_${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'),
|
||||||
|
light: this._extensionContext.asAbsolutePath('resources/light/sql_server.svg')
|
||||||
|
},
|
||||||
|
collapsibleState: this.browseConnectionMode ? vscode.TreeItemCollapsibleState.None : vscode.TreeItemCollapsibleState.Collapsed,
|
||||||
|
contextValue: AzureResourceItemType.synapseWorkspace,
|
||||||
|
payload: {
|
||||||
|
id: generateGuid(),
|
||||||
|
connectionName: undefined,
|
||||||
|
serverName: synapseWorkspace.fullName,
|
||||||
|
databaseName: synapseWorkspace.defaultDatabaseName,
|
||||||
|
userName: synapseWorkspace.loginName,
|
||||||
|
password: '',
|
||||||
|
authenticationType: '',
|
||||||
|
savePassword: true,
|
||||||
|
groupFullName: '',
|
||||||
|
groupId: '',
|
||||||
|
providerName: mssqlProvider,
|
||||||
|
saveProfile: false,
|
||||||
|
options: {},
|
||||||
|
azureAccount: account.key.accountId,
|
||||||
|
azureTenantId: synapseWorkspace.tenant,
|
||||||
|
azureResourceId: synapseWorkspace.id,
|
||||||
|
azurePortalEndpoint: account.properties.providerSettings.settings.portalEndpoint
|
||||||
|
},
|
||||||
|
childProvider: mssqlProvider,
|
||||||
|
type: ExtensionNodeType.Server
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getRootChildren(): Promise<TreeItem[]> {
|
||||||
|
return [{
|
||||||
|
id: AzureResourceSynapseWorkspaceTreeDataProvider.containerId,
|
||||||
|
label: AzureResourceSynapseWorkspaceTreeDataProvider.containerLabel,
|
||||||
|
iconPath: {
|
||||||
|
dark: this._extensionContext.asAbsolutePath('resources/dark/folder_inverse.svg'),
|
||||||
|
light: this._extensionContext.asAbsolutePath('resources/light/folder.svg')
|
||||||
|
},
|
||||||
|
collapsibleState: vscode.TreeItemCollapsibleState.Collapsed,
|
||||||
|
contextValue: AzureResourceItemType.synapseWorkspaceContainer
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
6
extensions/azurecore/src/azurecore.d.ts
vendored
6
extensions/azurecore/src/azurecore.d.ts
vendored
@@ -337,7 +337,7 @@ declare module 'azurecore' {
|
|||||||
export namespace azureResource {
|
export namespace azureResource {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AzureCore core extension supports following resource types of Azure Resource Graph.
|
* AzureCore extension supports following resource types of Azure Resource Graph.
|
||||||
* To add more resources, please refer this guide: https://docs.microsoft.com/en-us/azure/governance/resource-graph/reference/supported-tables-resources
|
* To add more resources, please refer this guide: https://docs.microsoft.com/en-us/azure/governance/resource-graph/reference/supported-tables-resources
|
||||||
*/
|
*/
|
||||||
export const enum AzureResourceType {
|
export const enum AzureResourceType {
|
||||||
@@ -345,6 +345,9 @@ declare module 'azurecore' {
|
|||||||
sqlServer = 'microsoft.sql/servers',
|
sqlServer = 'microsoft.sql/servers',
|
||||||
sqlDatabase = 'microsoft.sql/servers/databases',
|
sqlDatabase = 'microsoft.sql/servers/databases',
|
||||||
sqlManagedInstance = 'microsoft.sql/managedinstances',
|
sqlManagedInstance = 'microsoft.sql/managedinstances',
|
||||||
|
sqlSynapseWorkspace = 'microsoft.synapse/workspaces', // (Synapse Analytics workspace)
|
||||||
|
sqlSynapseSqlPool = 'microsoft.synapse/workspaces/sqlpools', // (Dedicated SQL pools)
|
||||||
|
sqlSynapseSqlDatabase = 'microsoft.synapse/workspaces/sqldatabases', // (Synapse SQL databases)
|
||||||
azureArcSqlManagedInstance = 'microsoft.azuredata/sqlmanagedinstances',
|
azureArcSqlManagedInstance = 'microsoft.azuredata/sqlmanagedinstances',
|
||||||
virtualMachines = 'microsoft.compute/virtualmachines',
|
virtualMachines = 'microsoft.compute/virtualmachines',
|
||||||
kustoClusters = 'microsoft.kusto/clusters',
|
kustoClusters = 'microsoft.kusto/clusters',
|
||||||
@@ -491,6 +494,7 @@ declare module 'azurecore' {
|
|||||||
fullName: string;
|
fullName: string;
|
||||||
defaultDatabaseName: string;
|
defaultDatabaseName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BlobContainer extends AzureResource { }
|
export interface BlobContainer extends AzureResource { }
|
||||||
|
|
||||||
export interface FileShare extends AzureResource { }
|
export interface FileShare extends AzureResource { }
|
||||||
|
|||||||
@@ -50,6 +50,10 @@ import { AzureResourceGroupService } from './azureResource/providers/resourceGro
|
|||||||
import { Logger } from './utils/Logger';
|
import { Logger } from './utils/Logger';
|
||||||
import { ConnectionDialogTreeProvider } from './azureResource/tree/connectionDialogTreeProvider';
|
import { ConnectionDialogTreeProvider } from './azureResource/tree/connectionDialogTreeProvider';
|
||||||
import { AzureDataGridProvider } from './azureDataGridProvider';
|
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';
|
||||||
|
|
||||||
let extensionContext: vscode.ExtensionContext;
|
let extensionContext: vscode.ExtensionContext;
|
||||||
|
|
||||||
@@ -139,6 +143,8 @@ export async function activate(context: vscode.ExtensionContext): Promise<azurec
|
|||||||
new AzureMonitorProvider(new AzureMonitorResourceService(), extensionContext),
|
new AzureMonitorProvider(new AzureMonitorResourceService(), extensionContext),
|
||||||
new AzureResourceDatabaseServerProvider(new AzureResourceDatabaseServerService(), extensionContext),
|
new AzureResourceDatabaseServerProvider(new AzureResourceDatabaseServerService(), extensionContext),
|
||||||
new AzureResourceDatabaseProvider(new AzureResourceDatabaseService(), extensionContext),
|
new AzureResourceDatabaseProvider(new AzureResourceDatabaseService(), extensionContext),
|
||||||
|
new AzureResourceSynapseSqlPoolProvider(new AzureResourceSynapseService(), extensionContext),
|
||||||
|
new AzureResourceSynapseWorkspaceProvider(new AzureResourceSynapseWorkspaceService(), extensionContext),
|
||||||
new SqlInstanceProvider(new SqlInstanceResourceService(), extensionContext),
|
new SqlInstanceProvider(new SqlInstanceResourceService(), extensionContext),
|
||||||
new PostgresServerProvider(new PostgresServerService(), extensionContext),
|
new PostgresServerProvider(new PostgresServerService(), extensionContext),
|
||||||
new CosmosDbMongoProvider(new CosmosDbMongoService(), extensionContext),
|
new CosmosDbMongoProvider(new CosmosDbMongoService(), extensionContext),
|
||||||
|
|||||||
Reference in New Issue
Block a user