diff --git a/extensions/azurecore/extension.webpack.config.js b/extensions/azurecore/extension.webpack.config.js index 99cf5567f3..5975878968 100644 --- a/extensions/azurecore/extension.webpack.config.js +++ b/extensions/azurecore/extension.webpack.config.js @@ -15,7 +15,8 @@ module.exports = withDefaults({ extension: './src/extension.ts' }, externals: { - 'ms-rest': 'commonjs ms-rest', + '@azure/ms-rest-azure-js': 'commonjs @azure/ms-rest-azure-js', + '@azure/ms-rest-js': 'commonjs @azure/ms-rest-js', 'request': 'commonjs request' } }); diff --git a/extensions/azurecore/package.json b/extensions/azurecore/package.json index c38845dfd7..214e909b21 100644 --- a/extensions/azurecore/package.json +++ b/extensions/azurecore/package.json @@ -173,10 +173,9 @@ "hasAzureResourceProviders": true }, "dependencies": { + "@azure/arm-resourcegraph": "^2.0.0", + "@azure/arm-subscriptions": "1.0.0", "adal-node": "^0.1.28", - "azure-arm-resource": "^7.0.0", - "azure-arm-sql": "^5.0.1", - "ms-rest": "^2.5.0", "request": "2.88.0", "vscode-nls": "^4.0.0" }, @@ -184,9 +183,9 @@ "@types/mocha": "^5.2.5", "@types/node": "^10.12.12", "@types/request": "^2.48.1", + "mocha": "^5.2.0", "mocha-junit-reporter": "^1.17.0", "mocha-multi-reporters": "^1.1.7", - "mocha": "^5.2.0", "should": "^13.2.1", "typemoq": "^2.1.0", "vscode": "1.1.26" diff --git a/extensions/azurecore/src/azureResource/commands.ts b/extensions/azurecore/src/azureResource/commands.ts index 00a156e8a6..3d8e0ef71e 100644 --- a/extensions/azurecore/src/azureResource/commands.ts +++ b/extensions/azurecore/src/azureResource/commands.ts @@ -6,11 +6,11 @@ import { window, QuickPickItem } from 'vscode'; import * as azdata from 'azdata'; -import { TokenCredentials } from 'ms-rest'; -import { AppContext } from '../appContext'; +import { TokenCredentials } from '@azure/ms-rest-js'; import * as nls from 'vscode-nls'; const localize = nls.loadMessageBundle(); +import { AppContext } from '../appContext'; import { azureResource } from './azure-resource'; import { TreeNode } from './treeNode'; import { AzureResourceCredentialError } from './errors'; @@ -46,7 +46,11 @@ export function registerAzureResourceCommands(appContext: AppContext, tree: Azur } } - let selectedSubscriptions = (await subscriptionFilterService.getSelectedSubscriptions(accountNode.account)) || []; + let selectedSubscriptions = await subscriptionFilterService.getSelectedSubscriptions(accountNode.account); + if (!selectedSubscriptions) { + selectedSubscriptions = []; + } + const selectedSubscriptionIds: string[] = []; if (selectedSubscriptions.length > 0) { selectedSubscriptionIds.push(...selectedSubscriptions.map((subscription) => subscription.id)); @@ -67,9 +71,9 @@ export function registerAzureResourceCommands(appContext: AppContext, tree: Azur }; }).sort((a, b) => a.label.localeCompare(b.label)); - const selectedSubscriptionQuickPickItems = (await window.showQuickPick(subscriptionQuickPickItems, { canPickMany: true })); + const selectedSubscriptionQuickPickItems = await window.showQuickPick(subscriptionQuickPickItems, { canPickMany: true }); if (selectedSubscriptionQuickPickItems && selectedSubscriptionQuickPickItems.length > 0) { - tree.refresh(node, false); + await tree.refresh(node, false); selectedSubscriptions = selectedSubscriptionQuickPickItems.map((subscriptionItem) => subscriptionItem.subscription); await subscriptionFilterService.saveSelectedSubscriptions(accountNode.account, selectedSubscriptions); @@ -79,7 +83,7 @@ export function registerAzureResourceCommands(appContext: AppContext, tree: Azur appContext.apiWrapper.registerCommand('azure.resource.refreshall', () => tree.notifyNodeChanged(undefined)); appContext.apiWrapper.registerCommand('azure.resource.refresh', async (node?: TreeNode) => { - tree.refresh(node, true); + await tree.refresh(node, true); }); appContext.apiWrapper.registerCommand('azure.resource.signin', async (node?: TreeNode) => { diff --git a/extensions/azurecore/src/azureResource/interfaces.ts b/extensions/azurecore/src/azureResource/interfaces.ts index b9cc4b5696..4b571e256a 100644 --- a/extensions/azurecore/src/azureResource/interfaces.ts +++ b/extensions/azurecore/src/azureResource/interfaces.ts @@ -3,9 +3,8 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; +import * as msRest from '@azure/ms-rest-js'; -import { ServiceClientCredentials } from 'ms-rest'; import { Account, DidChangeAccountsParams } from 'azdata'; import { Event } from 'vscode'; @@ -13,17 +12,15 @@ import { azureResource } from './azure-resource'; export interface IAzureResourceAccountService { getAccounts(): Promise; - readonly onDidChangeAccounts: Event; } export interface IAzureResourceSubscriptionService { - getSubscriptions(account: Account, credential: ServiceClientCredentials): Promise; + getSubscriptions(account: Account, credential: msRest.ServiceClientCredentials): Promise; } export interface IAzureResourceSubscriptionFilterService { getSelectedSubscriptions(account: Account): Promise; - saveSelectedSubscriptions(account: Account, selectedSubscriptions: azureResource.AzureResourceSubscription[]): Promise; } @@ -50,7 +47,7 @@ export interface AzureSqlResource { } export interface IAzureResourceService { - getResources(subscription: azureResource.AzureResourceSubscription, credential: ServiceClientCredentials): Promise; + getResources(subscription: azureResource.AzureResourceSubscription, credential: msRest.ServiceClientCredentials): Promise; } @@ -60,6 +57,7 @@ export interface AzureResourceDatabase extends AzureSqlResource { } export interface AzureResourceDatabaseServer extends AzureSqlResource { + id?: string; fullName: string; defaultDatabaseName: string; } diff --git a/extensions/azurecore/src/azureResource/providers/database/databaseService.ts b/extensions/azurecore/src/azureResource/providers/database/databaseService.ts index 9b9e0f1960..6864832407 100644 --- a/extensions/azurecore/src/azureResource/providers/database/databaseService.ts +++ b/extensions/azurecore/src/azureResource/providers/database/databaseService.ts @@ -3,35 +3,56 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ServiceClientCredentials } from 'ms-rest'; -import { SqlManagementClient } from 'azure-arm-sql'; - +import { ServiceClientCredentials } from '@azure/ms-rest-js'; import { azureResource } from '../../azure-resource'; import { IAzureResourceService, AzureResourceDatabase } from '../../interfaces'; +import { serversQuery, DbServerGraphData } from '../databaseServer/databaseServerService'; +import { ResourceGraphClient } from '@azure/arm-resourcegraph'; +import { queryGraphResources, GraphData } from '../resourceTreeDataProviderBase'; +interface DatabaseGraphData extends GraphData { + kind: string; +} export class AzureResourceDatabaseService implements IAzureResourceService { public async getResources(subscription: azureResource.AzureResourceSubscription, credential: ServiceClientCredentials): Promise { const databases: AzureResourceDatabase[] = []; - const sqlManagementClient = new SqlManagementClient(credential, subscription.id); - const svrs = await sqlManagementClient.servers.list(); - for (const svr of svrs) { - // Extract resource group name from svr.id - const svrIdRegExp = new RegExp(`\/subscriptions\/${subscription.id}\/resourceGroups\/(.+)\/providers\/Microsoft\.Sql\/servers\/${svr.name}`); - if (!svrIdRegExp.test(svr.id)) { - continue; + const resourceClient = new ResourceGraphClient(credential); + + // Query servers and databases in parallel (start both promises before waiting on the 1st) + let serverQueryPromise = queryGraphResources(resourceClient, subscription.id, serversQuery); + let dbQueryPromise = queryGraphResources(resourceClient, subscription.id, 'where type == "microsoft.sql/servers/databases"'); + let servers: DbServerGraphData[] = await serverQueryPromise as DbServerGraphData[]; + let dbByGraph: DatabaseGraphData[] = await dbQueryPromise as DatabaseGraphData[]; + + // 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(); + servers.forEach(s => { + 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 + const svrIdRegExp = new RegExp(`\/subscriptions\/${subscription.id}\/resourceGroups\/(.+)\/providers\/Microsoft\.Sql\/servers\/(.+)\/databases\/.+`); + + dbByGraph.forEach(db => { + // Filter master DBs, and for all others find their server to get login info + let serversForRg = rgMap.get(db.resourceGroup); + if (serversForRg && !db.kind.endsWith('system') && svrIdRegExp.test(db.id)) { + const founds = svrIdRegExp.exec(db.id); + const serverName = founds[2]; + let server = servers.find(s => s.name === serverName); + if (server) { + databases.push({ + name: db.name, + serverName: server.name, + serverFullName: server.properties.fullyQualifiedDomainName, + loginName: server.properties.administratorLogin + }); + } } - - const founds = svrIdRegExp.exec(svr.id); - const resouceGroup = founds[1]; - - const dbs = await sqlManagementClient.databases.listByServer(resouceGroup, svr.name); - dbs.forEach((db) => databases.push({ - name: db.name, - serverName: svr.name, - serverFullName: svr.fullyQualifiedDomainName, - loginName: svr.administratorLogin - })); - } + }); return databases; } diff --git a/extensions/azurecore/src/azureResource/providers/databaseServer/databaseServerService.ts b/extensions/azurecore/src/azureResource/providers/databaseServer/databaseServerService.ts index be12c12d18..aadb05c1bc 100644 --- a/extensions/azurecore/src/azureResource/providers/databaseServer/databaseServerService.ts +++ b/extensions/azurecore/src/azureResource/providers/databaseServer/databaseServerService.ts @@ -3,26 +3,33 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ServiceClientCredentials } from 'ms-rest'; -import { SqlManagementClient } from 'azure-arm-sql'; -import { azureResource } from '../../azure-resource'; -import { IAzureResourceService, AzureResourceDatabaseServer } from '../../interfaces'; +import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase'; +import { AzureResourceDatabaseServer } from '../../interfaces'; -export class AzureResourceDatabaseServerService implements IAzureResourceService { - public async getResources(subscription: azureResource.AzureResourceSubscription, credential: ServiceClientCredentials): Promise { - const databaseServers: AzureResourceDatabaseServer[] = []; - const sqlManagementClient = new SqlManagementClient(credential, subscription.id); - const svrs = await sqlManagementClient.servers.list(); +export interface DbServerGraphData extends GraphData { + properties: { + fullyQualifiedDomainName: string; + administratorLogin: string; + }; +} - svrs.forEach((svr) => databaseServers.push({ - name: svr.name, - fullName: svr.fullyQualifiedDomainName, - loginName: svr.administratorLogin, +export const serversQuery = 'where type == "microsoft.sql/servers"'; + +export class AzureResourceDatabaseServerService extends ResourceServiceBase { + + protected get query(): string { + return serversQuery; + } + + protected convertResource(resource: DbServerGraphData): AzureResourceDatabaseServer { + return { + id: resource.id, + name: resource.name, + fullName: resource.properties.fullyQualifiedDomainName, + loginName: resource.properties.administratorLogin, defaultDatabaseName: 'master' - })); - - return databaseServers; + }; } } diff --git a/extensions/azurecore/src/azureResource/providers/databaseServer/databaseServerTreeDataProvider.ts b/extensions/azurecore/src/azureResource/providers/databaseServer/databaseServerTreeDataProvider.ts index f5eed277c6..340585a018 100644 --- a/extensions/azurecore/src/azureResource/providers/databaseServer/databaseServerTreeDataProvider.ts +++ b/extensions/azurecore/src/azureResource/providers/databaseServer/databaseServerTreeDataProvider.ts @@ -30,7 +30,7 @@ export class AzureResourceDatabaseServerTreeDataProvider extends ResourceTreeDat protected getTreeItemForResource(databaseServer: AzureResourceDatabaseServer): TreeItem { return { - id: `databaseServer_${databaseServer.name}`, + id: `databaseServer_${databaseServer.id ? databaseServer.id : databaseServer.name}`, label: databaseServer.name, iconPath: { dark: this._extensionContext.asAbsolutePath('resources/dark/sql_server_inverse.svg'), diff --git a/extensions/azurecore/src/azureResource/providers/postgresServer/postgresServerProvider.ts b/extensions/azurecore/src/azureResource/providers/postgresServer/postgresServerProvider.ts new file mode 100644 index 0000000000..d3b79954a0 --- /dev/null +++ b/extensions/azurecore/src/azureResource/providers/postgresServer/postgresServerProvider.ts @@ -0,0 +1,28 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { ApiWrapper } from '../../../apiWrapper'; + +import { azureResource } from '../../azure-resource'; +import { IAzureResourceService, AzureResourceDatabaseServer } from '../../interfaces'; +import { PostgresServerTreeDataProvider as PostgresServerTreeDataProvider } from './postgresServerTreeDataProvider'; + +export class PostgresServerProvider implements azureResource.IAzureResourceProvider { + public constructor( + private _databaseServerService: IAzureResourceService, + private _apiWrapper: ApiWrapper, + private _extensionContext: ExtensionContext + ) { + } + + public getTreeDataProvider(): azureResource.IAzureResourceTreeDataProvider { + return new PostgresServerTreeDataProvider(this._databaseServerService, this._apiWrapper, this._extensionContext); + } + + public get providerId(): string { + return 'azure.resource.providers.postgresServer'; + } +} diff --git a/extensions/azurecore/src/azureResource/providers/postgresServer/postgresServerService.ts b/extensions/azurecore/src/azureResource/providers/postgresServer/postgresServerService.ts new file mode 100644 index 0000000000..ac8a031bf8 --- /dev/null +++ b/extensions/azurecore/src/azureResource/providers/postgresServer/postgresServerService.ts @@ -0,0 +1,35 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + +import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase'; +import { AzureResourceDatabaseServer } from '../../interfaces'; + + +export interface DbServerGraphData extends GraphData { + properties: { + fullyQualifiedDomainName: string; + administratorLogin: string; + }; +} + +export const serversQuery = 'where type == "microsoft.dbforpostgresql/servers"'; + +export class PostgresServerService extends ResourceServiceBase { + + protected get query(): string { + return serversQuery; + } + + protected convertResource(resource: DbServerGraphData): AzureResourceDatabaseServer { + return { + id: resource.id, + name: resource.name, + fullName: resource.properties.fullyQualifiedDomainName, + loginName: resource.properties.administratorLogin, + defaultDatabaseName: 'postgres' + }; + } +} diff --git a/extensions/azurecore/src/azureResource/providers/postgresServer/postgresServerTreeDataProvider.ts b/extensions/azurecore/src/azureResource/providers/postgresServer/postgresServerTreeDataProvider.ts new file mode 100644 index 0000000000..64a851ef0c --- /dev/null +++ b/extensions/azurecore/src/azureResource/providers/postgresServer/postgresServerTreeDataProvider.ts @@ -0,0 +1,82 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { TreeItemCollapsibleState, ExtensionContext } from 'vscode'; +import * as nls from 'vscode-nls'; +const localize = nls.loadMessageBundle(); + +import { AzureResourceItemType } from '../../constants'; +import { ApiWrapper } from '../../../apiWrapper'; +import { generateGuid } from '../../utils'; +import { IAzureResourceService, AzureResourceDatabaseServer } from '../../interfaces'; +import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase'; +import { azureResource } from '../../azure-resource'; + +export class PostgresServerTreeDataProvider extends ResourceTreeDataProviderBase { + 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 Servers"); + + public constructor( + databaseServerService: IAzureResourceService, + apiWrapper: ApiWrapper, + private _extensionContext: ExtensionContext + ) { + super(databaseServerService, apiWrapper); + } + + + protected getTreeItemForResource(databaseServer: AzureResourceDatabaseServer): TreeItem { + return { + id: `databaseServer_${databaseServer.id ? databaseServer.id : databaseServer.name}`, + label: databaseServer.name, + // TODO: should get PGSQL-specific icons (also needed in that extension) + iconPath: { + dark: this._extensionContext.asAbsolutePath('resources/dark/sql_server_inverse.svg'), + light: this._extensionContext.asAbsolutePath('resources/light/sql_server.svg') + }, + collapsibleState: TreeItemCollapsibleState.Collapsed, + contextValue: AzureResourceItemType.databaseServer, + payload: { + id: generateGuid(), + connectionName: undefined, + serverName: databaseServer.fullName, + databaseName: databaseServer.defaultDatabaseName, + userName: `${databaseServer.loginName}@${databaseServer.fullName}`, + password: '', + authenticationType: 'SqlLogin', + savePassword: true, + groupFullName: '', + groupId: '', + providerName: 'PGSQL', + saveProfile: false, + options: { + // Set default for SSL or will get error complaining about it not being set correctly + 'sslmode': 'require' + } + }, + childProvider: 'PGSQL', + type: ExtensionNodeType.Server + }; + } + + protected createContainerNode(): azureResource.IAzureResourceNode { + return { + account: undefined, + subscription: undefined, + tenantId: undefined, + treeItem: { + id: PostgresServerTreeDataProvider.containerId, + label: PostgresServerTreeDataProvider.containerLabel, + iconPath: { + dark: this._extensionContext.asAbsolutePath('resources/dark/folder_inverse.svg'), + light: this._extensionContext.asAbsolutePath('resources/light/folder.svg') + }, + collapsibleState: TreeItemCollapsibleState.Collapsed, + contextValue: AzureResourceItemType.databaseServerContainer + } + }; + } +} diff --git a/extensions/azurecore/src/azureResource/providers/resourceTreeDataProviderBase.ts b/extensions/azurecore/src/azureResource/providers/resourceTreeDataProviderBase.ts index f14c95975b..195f985742 100644 --- a/extensions/azurecore/src/azureResource/providers/resourceTreeDataProviderBase.ts +++ b/extensions/azurecore/src/azureResource/providers/resourceTreeDataProviderBase.ts @@ -4,17 +4,19 @@ *--------------------------------------------------------------------------------------------*/ import { AzureResource, TreeItem } from 'azdata'; -import { TokenCredentials } from 'ms-rest'; +import * as msRest from '@azure/ms-rest-js'; import { azureResource } from '../azure-resource'; import { ApiWrapper } from '../../apiWrapper'; import { IAzureResourceService, AzureSqlResource } from '../interfaces'; +import { AzureResourceErrorMessageUtil } from '../utils'; +import { ResourceGraphClient } from '@azure/arm-resourcegraph'; export abstract class ResourceTreeDataProviderBase implements azureResource.IAzureResourceTreeDataProvider { public constructor( protected _resourceService: IAzureResourceService, - protected _apiWrapper: ApiWrapper, + protected _apiWrapper: ApiWrapper ) { } @@ -23,24 +25,94 @@ export abstract class ResourceTreeDataProviderBase i } public async getChildren(element?: azureResource.IAzureResourceNode): Promise { - if (!element) { - return [this.createContainerNode()]; - } + try { + if (!element) { + return [this.createContainerNode()]; + } + let resources: T[] = await this.getResources(element); + + return resources.map((resource) => { + account: element.account, + subscription: element.subscription, + tenantId: element.tenantId, + treeItem: this.getTreeItemForResource(resource) + }).sort((a, b) => a.treeItem.label.localeCompare(b.treeItem.label)); + } catch (error) { + console.log(AzureResourceErrorMessageUtil.getErrorMessage(error)); + throw error; + } + } + + private async getResources(element: azureResource.IAzureResourceNode): Promise { const tokens = await this._apiWrapper.getSecurityToken(element.account, AzureResource.ResourceManagement); - const credential = new TokenCredentials(tokens[element.tenantId].token, tokens[element.tenantId].tokenType); + const credential = new msRest.TokenCredentials(tokens[element.tenantId].token, tokens[element.tenantId].tokenType); const resources: T[] = await this._resourceService.getResources(element.subscription, credential) || []; - - return resources.map((resource) => { - account: element.account, - subscription: element.subscription, - tenantId: element.tenantId, - treeItem: this.getTreeItemForResource(resource) - }).sort((a, b) => a.treeItem.label.localeCompare(b.treeItem.label)); + return resources; } protected abstract getTreeItemForResource(resource: T): TreeItem; protected abstract createContainerNode(): azureResource.IAzureResourceNode; } + +export interface GraphData { + id: string; + name: string; + location: string; + type: string; + resourceGroup: string; +} + + +export async function queryGraphResources(resourceClient: ResourceGraphClient, subId: string, resourceQuery: string): Promise { + const allResources: T[] = []; + let totalProcessed = 0; + let doQuery = async (skipToken?: string) => { + const response = await resourceClient.resources({ + subscriptions: [subId], + query: resourceQuery, + options: { + resultFormat: 'objectArray', + skipToken: skipToken + } + }); + const resources: T[] = response.data; + totalProcessed += resources.length; + allResources.push(...resources); + if (response.skipToken && totalProcessed < response.totalRecords) { + await doQuery(response.skipToken); + } + }; + await doQuery(); + return allResources; +} + +export abstract class ResourceServiceBase implements IAzureResourceService { + constructor() { + } + + protected abstract get query(): string; + + public async getResources(subscription: azureResource.AzureResourceSubscription, credential: msRest.ServiceClientCredentials): Promise { + const convertedResources: U[] = []; + const resourceClient = new ResourceGraphClient(credential); + let graphResources = await queryGraphResources(resourceClient, subscription.id, this.query); + let ids = new Set(); + graphResources.forEach((res) => { + if (!ids.has(res.id)) { + ids.add(res.id); + let converted = this.convertResource(res); + convertedResources.push(converted); + } + }); + + return convertedResources; + } + + protected abstract convertResource(resource: T): U; +} + + + diff --git a/extensions/azurecore/src/azureResource/providers/sqlinstance/sqlInstanceService.ts b/extensions/azurecore/src/azureResource/providers/sqlinstance/sqlInstanceService.ts index 83aa8f22b7..3af8658749 100644 --- a/extensions/azurecore/src/azureResource/providers/sqlinstance/sqlInstanceService.ts +++ b/extensions/azurecore/src/azureResource/providers/sqlinstance/sqlInstanceService.ts @@ -3,25 +3,31 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ServiceClientCredentials as OldSc } from 'ms-rest'; -import { SqlManagementClient } from 'azure-arm-sql'; +import { AzureResourceDatabaseServer } from '../../interfaces'; +import { ResourceServiceBase, GraphData } from '../resourceTreeDataProviderBase'; -import { azureResource } from '../../azure-resource'; -import { IAzureResourceService, AzureResourceDatabaseServer } from '../../interfaces'; +export interface SqlInstanceGraphData extends GraphData { + properties: { + fullyQualifiedDomainName: string; + administratorLogin: string; + }; +} -export class SqlInstanceResourceService implements IAzureResourceService { - public async getResources(subscription: azureResource.AzureResourceSubscription, credential: OldSc): Promise { - const databaseServers: AzureResourceDatabaseServer[] = []; - const sqlManagementClient = new SqlManagementClient(credential, subscription.id); - const svrs = await sqlManagementClient.managedInstances.list(); +const instanceQuery = 'where type == "microsoft.sql/managedinstances"'; - svrs.forEach((svr) => databaseServers.push({ - name: svr.name, - fullName: svr.fullyQualifiedDomainName, - loginName: svr.administratorLogin, +export class SqlInstanceResourceService extends ResourceServiceBase { + + protected get query(): string { + return instanceQuery; + } + + protected convertResource(resource: SqlInstanceGraphData): AzureResourceDatabaseServer { + return { + id: resource.id, + name: resource.name, + fullName: resource.properties.fullyQualifiedDomainName, + loginName: resource.properties.administratorLogin, defaultDatabaseName: 'master' - })); - - return databaseServers; + }; } } diff --git a/extensions/azurecore/src/azureResource/providers/sqlinstance/sqlInstanceTreeDataProvider.ts b/extensions/azurecore/src/azureResource/providers/sqlinstance/sqlInstanceTreeDataProvider.ts index 14516a683f..a4942d0fea 100644 --- a/extensions/azurecore/src/azureResource/providers/sqlinstance/sqlInstanceTreeDataProvider.ts +++ b/extensions/azurecore/src/azureResource/providers/sqlinstance/sqlInstanceTreeDataProvider.ts @@ -17,7 +17,7 @@ import { azureResource } from '../../azure-resource'; export class SqlInstanceTreeDataProvider extends ResourceTreeDataProviderBase { private static readonly containerId = 'azure.resource.providers.sqlInstanceContainer'; - private static readonly containerLabel = localize('azure.resource.providers.sqlInstanceContainerLabel', "SQL Instances"); + private static readonly containerLabel = localize('azure.resource.providers.sqlInstanceContainerLabel', "SQL Managed Instances"); public constructor( databaseServerService: IAzureResourceService, @@ -30,7 +30,7 @@ export class SqlInstanceTreeDataProvider extends ResourceTreeDataProviderBase { const subscriptions: azureResource.AzureResourceSubscription[] = []; - const subClient = new SubscriptionClient.SubscriptionClient(credential); + const subClient = new SubscriptionClient(credential); const subs = await subClient.subscriptions.list(); subs.forEach((sub) => subscriptions.push({ id: sub.subscriptionId, diff --git a/extensions/azurecore/src/azureResource/tree/accountTreeNode.ts b/extensions/azurecore/src/azureResource/tree/accountTreeNode.ts index cf84497772..4d4568a258 100644 --- a/extensions/azurecore/src/azureResource/tree/accountTreeNode.ts +++ b/extensions/azurecore/src/azureResource/tree/accountTreeNode.ts @@ -5,11 +5,12 @@ import { TreeItem, TreeItemCollapsibleState } from 'vscode'; import { Account, NodeInfo, AzureResource } from 'azdata'; -import { TokenCredentials } from 'ms-rest'; -import { AppContext } from '../../appContext'; +import { TokenCredentials } from '@azure/ms-rest-js'; + import * as nls from 'vscode-nls'; const localize = nls.loadMessageBundle(); +import { AppContext } from '../../appContext'; import { azureResource } from '../azure-resource'; import { TreeNode } from '../treeNode'; import { AzureResourceCredentialError } from '../errors'; diff --git a/extensions/azurecore/src/azureResource/tree/subscriptionTreeNode.ts b/extensions/azurecore/src/azureResource/tree/subscriptionTreeNode.ts index 02130cbff5..f5189bdfd4 100644 --- a/extensions/azurecore/src/azureResource/tree/subscriptionTreeNode.ts +++ b/extensions/azurecore/src/azureResource/tree/subscriptionTreeNode.ts @@ -3,8 +3,6 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import { TreeItem, TreeItemCollapsibleState } from 'vscode'; import { Account, NodeInfo } from 'azdata'; import { AppContext } from '../../appContext'; diff --git a/extensions/azurecore/src/extension.ts b/extensions/azurecore/src/extension.ts index 17bd5af621..db68a1bb53 100644 --- a/extensions/azurecore/src/extension.ts +++ b/extensions/azurecore/src/extension.ts @@ -29,6 +29,8 @@ import { registerAzureResourceCommands } from './azureResource/commands'; import { AzureResourceTreeProvider } from './azureResource/tree/treeProvider'; import { SqlInstanceResourceService } from './azureResource/providers/sqlinstance/sqlInstanceService'; import { SqlInstanceProvider } from './azureResource/providers/sqlinstance/sqlInstanceProvider'; +import { PostgresServerProvider } from './azureResource/providers/postgresServer/postgresServerProvider'; +import { PostgresServerService } from './azureResource/providers/postgresServer/postgresServerService'; let extensionContext: vscode.ExtensionContext; @@ -65,7 +67,7 @@ export async function activate(context: vscode.ExtensionContext) { } // Create the provider service and activate - initAzureAccountProvider(extensionContext, storagePath); + initAzureAccountProvider(extensionContext, storagePath).catch((err) => console.log(err)); registerAzureServices(appContext); const azureResourceTree = new AzureResourceTreeProvider(appContext); @@ -77,7 +79,8 @@ export async function activate(context: vscode.ExtensionContext) { return [ new AzureResourceDatabaseServerProvider(new AzureResourceDatabaseServerService(), apiWrapper, extensionContext), new AzureResourceDatabaseProvider(new AzureResourceDatabaseService(), apiWrapper, extensionContext), - new SqlInstanceProvider(new SqlInstanceResourceService(), apiWrapper, extensionContext) + new SqlInstanceProvider(new SqlInstanceResourceService(), apiWrapper, extensionContext), + new PostgresServerProvider(new PostgresServerService(), apiWrapper, extensionContext) ]; } }; diff --git a/extensions/azurecore/src/test/azureResource/resourceService.test.ts b/extensions/azurecore/src/test/azureResource/resourceService.test.ts index 898ffe4670..b256b8f6d7 100644 --- a/extensions/azurecore/src/test/azureResource/resourceService.test.ts +++ b/extensions/azurecore/src/test/azureResource/resourceService.test.ts @@ -3,8 +3,6 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import * as should from 'should'; import * as TypeMoq from 'typemoq'; import * as azdata from 'azdata'; @@ -179,4 +177,4 @@ describe('AzureResourceService.getTreeItem', function(): void { fail(); }); -}); \ No newline at end of file +}); diff --git a/extensions/azurecore/src/test/azureResource/resourceTreeNode.test.ts b/extensions/azurecore/src/test/azureResource/resourceTreeNode.test.ts index 8e75f7b1ca..f1c6761d7e 100644 --- a/extensions/azurecore/src/test/azureResource/resourceTreeNode.test.ts +++ b/extensions/azurecore/src/test/azureResource/resourceTreeNode.test.ts @@ -3,8 +3,6 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import * as should from 'should'; import * as TypeMoq from 'typemoq'; import * as azdata from 'azdata'; diff --git a/extensions/azurecore/src/test/azureResource/tree/accountTreeNode.test.ts b/extensions/azurecore/src/test/azureResource/tree/accountTreeNode.test.ts index 0f34fa7856..6b3ce58f44 100644 --- a/extensions/azurecore/src/test/azureResource/tree/accountTreeNode.test.ts +++ b/extensions/azurecore/src/test/azureResource/tree/accountTreeNode.test.ts @@ -8,7 +8,7 @@ import * as TypeMoq from 'typemoq'; import * as azdata from 'azdata'; import * as vscode from 'vscode'; import 'mocha'; -import { TokenCredentials } from 'ms-rest'; +import { TokenCredentials } from '@azure/ms-rest-js'; import { AppContext } from '../../../appContext'; import { azureResource } from '../../../azureResource/azure-resource'; @@ -343,4 +343,4 @@ describe('AzureResourceAccountTreeNode.clearCache', function (): void { accountTreeNode.clearCache(); should(accountTreeNode.isClearingCache).true(); }); -}); \ No newline at end of file +}); diff --git a/extensions/azurecore/yarn.lock b/extensions/azurecore/yarn.lock index 7e73a74cf4..c0821a2321 100644 --- a/extensions/azurecore/yarn.lock +++ b/extensions/azurecore/yarn.lock @@ -2,6 +2,46 @@ # yarn lockfile v1 +"@azure/arm-resourcegraph@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@azure/arm-resourcegraph/-/arm-resourcegraph-2.0.0.tgz#f766e4a0b4285c114d25e98f22f8c260fe042469" + integrity sha512-6tWBlHlqlqUlNP0Ob+6x6uH37YICbgXg03UiVWr9Yno060KJ/0BPwlSfTgjvLkBiyXnutPb6HpH5/+GMUICzYQ== + dependencies: + "@azure/ms-rest-azure-js" "^1.3.2" + "@azure/ms-rest-js" "^1.8.1" + tslib "^1.9.3" + +"@azure/arm-subscriptions@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@azure/arm-subscriptions/-/arm-subscriptions-1.0.0.tgz#ab65a5cd4d8b8c878ff6621428f29137b84eb1d6" + integrity sha512-DoZFcF+ePkGhrxQ4X/LxBoWipqpkZIt9g+itXJ4HaQNExn0hNO27Cs6kNZYpIdCs5Zu+2DbjRs2i8OqG3QbE9w== + dependencies: + "@azure/ms-rest-azure-js" "^1.1.0" + "@azure/ms-rest-js" "^1.1.0" + tslib "^1.9.3" + +"@azure/ms-rest-azure-js@^1.1.0", "@azure/ms-rest-azure-js@^1.3.2": + version "1.3.8" + resolved "https://registry.yarnpkg.com/@azure/ms-rest-azure-js/-/ms-rest-azure-js-1.3.8.tgz#96b518223d3baa2496b2981bc07288b3d887486e" + integrity sha512-AHLfDTCyIH6wBK6+CpImI6sc9mLZ17ZgUrTx3Rhwv+3Mb3Z73BxormkarfR6Stb6scrBYitxJ27FXyndXlGAYg== + dependencies: + "@azure/ms-rest-js" "^1.8.10" + tslib "^1.9.3" + +"@azure/ms-rest-js@^1.1.0", "@azure/ms-rest-js@^1.8.1", "@azure/ms-rest-js@^1.8.10": + version "1.8.13" + resolved "https://registry.yarnpkg.com/@azure/ms-rest-js/-/ms-rest-js-1.8.13.tgz#ed0cd86469697378cd39d79d5589e877a3bc87a6" + integrity sha512-jAa6Y2XrvwbEqkaEXDHK+ReNo0WnCPS+LgQ1dRAJUUNxK4CghF5u+SXsVtPENritilVE7FVteqsLOtlhTk+haA== + dependencies: + "@types/tunnel" "0.0.0" + axios "^0.19.0" + form-data "^2.3.2" + tough-cookie "^2.4.3" + tslib "^1.9.2" + tunnel "0.0.6" + uuid "^3.2.1" + xml2js "^0.4.19" + "@types/caseless@*": version "0.12.2" resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.2.tgz#f65d3d6389e01eeb458bd54dc8f52b95a9463bc8" @@ -44,6 +84,13 @@ resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-2.3.5.tgz#9da44ed75571999b65c37b60c9b2b88db54c585d" integrity sha512-SCcK7mvGi3+ZNz833RRjFIxrn4gI1PPR3NtuIS+6vMkvmsGjosqTJwRt5bAEFLRz+wtJMWv8+uOnZf2hi2QXTg== +"@types/tunnel@0.0.0": + version "0.0.0" + resolved "https://registry.yarnpkg.com/@types/tunnel/-/tunnel-0.0.0.tgz#c2a42943ee63c90652a5557b8c4e56cda77f944e" + integrity sha512-FGDp0iBRiBdPjOgjJmn1NH0KDLN+Z8fRmo+9J7XGBhubq1DPrGrbmG4UTlGzrpbCpesMqD0sWkzi27EYkOMHyg== + dependencies: + "@types/node" "*" + adal-node@^0.1.28: version "0.1.28" resolved "https://registry.yarnpkg.com/adal-node/-/adal-node-0.1.28.tgz#468c4bb3ebbd96b1270669f4b9cba4e0065ea485" @@ -157,13 +204,6 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= -async@2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4" - integrity sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw== - dependencies: - lodash "^4.14.0" - async@>=0.6.0: version "2.6.1" resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" @@ -186,21 +226,13 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== -azure-arm-resource@^7.0.0: - version "7.3.0" - resolved "https://registry.yarnpkg.com/azure-arm-resource/-/azure-arm-resource-7.3.0.tgz#b45c4b4ab48719c00b9a2554cce6c2cb014a6d6f" - integrity sha512-2K+ps1Iwa4PBQFwdCn1X8kAVIRLH5M7nlNZtfOWaYd7DXJ131qJpwW8ul6gKZgG7DAI3PBodrGsHFvPdgA+AzQ== +axios@^0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.0.tgz#8e09bff3d9122e133f7b8101c8fbdd00ed3d2ab8" + integrity sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ== dependencies: - ms-rest "^2.3.3" - ms-rest-azure "^2.5.5" - -azure-arm-sql@^5.0.1: - version "5.6.0" - resolved "https://registry.yarnpkg.com/azure-arm-sql/-/azure-arm-sql-5.6.0.tgz#9a2a88c70ef1924ee8f7f351ec7eaf28482a6dae" - integrity sha512-j1T2Cdbs/fV55a4Rz72KdtxIwyCt7BXPIjHnv5q1j2tbvCofd5v6hRqYbyLlIhtdxY4ygrPet8UmfTgUt4RA6w== - dependencies: - ms-rest "^2.3.3" - ms-rest-azure "^2.5.5" + follow-redirects "1.5.10" + is-buffer "^2.0.2" balanced-match@^1.0.0: version "1.0.0" @@ -364,7 +396,7 @@ date-utils@*: resolved "https://registry.yarnpkg.com/date-utils/-/date-utils-1.2.21.tgz#61fb16cdc1274b3c9acaaffe9fc69df8720a2b64" integrity sha1-YfsWzcEnSzyayq/+n8ad+HIKK2Q= -debug@3.1.0: +debug@3.1.0, debug@=3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== @@ -392,7 +424,7 @@ deep-assign@^1.0.0: dependencies: is-obj "^1.0.0" -define-properties@^1.1.2: +define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== @@ -451,6 +483,31 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: dependencies: once "^1.4.0" +es-abstract@^1.5.1: + version "1.16.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d" + integrity sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg== + dependencies: + es-to-primitive "^1.2.0" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.0" + is-callable "^1.1.4" + is-regex "^1.0.4" + object-inspect "^1.6.0" + object-keys "^1.1.1" + string.prototype.trimleft "^2.1.0" + string.prototype.trimright "^2.1.0" + +es-to-primitive@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" + integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + escape-string-regexp@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -529,11 +586,27 @@ flush-write-stream@^1.0.2: inherits "^2.0.3" readable-stream "^2.3.6" +follow-redirects@1.5.10: + version "1.5.10" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" + integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ== + dependencies: + debug "=3.1.0" + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= +form-data@^2.3.2: + version "2.5.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" + integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + form-data@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" @@ -735,7 +808,7 @@ has-symbols@^1.0.0: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= -has@^1.0.3: +has@^1.0.1, has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== @@ -777,11 +850,26 @@ is-absolute@^1.0.0: is-relative "^1.0.0" is-windows "^1.0.1" -is-buffer@^1.1.5, is-buffer@^1.1.6, is-buffer@~1.1.1: +is-buffer@^1.1.5, is-buffer@~1.1.1: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== +is-buffer@^2.0.2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" + integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== + +is-callable@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= + is-extglob@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -804,6 +892,13 @@ is-obj@^1.0.0: resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= +is-regex@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= + dependencies: + has "^1.0.1" + is-relative@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" @@ -811,10 +906,12 @@ is-relative@^1.0.0: dependencies: is-unc-path "^1.0.0" -is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= +is-symbol@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" + integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== + dependencies: + has-symbols "^1.0.0" is-typedarray@~1.0.0: version "1.0.0" @@ -934,16 +1031,16 @@ lead@^1.0.0: dependencies: flush-write-stream "^1.0.2" -lodash@^4.14.0, lodash@^4.17.10, lodash@^4.17.4: - version "4.17.11" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" - integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== - lodash@^4.16.4: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== +lodash@^4.17.10, lodash@^4.17.4: + version "4.17.11" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" + integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== + map-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.0.7.tgz#8a1f07896d82b10926bd3744a2420009f88974a8" @@ -1046,37 +1143,6 @@ mocha@^5.2.0: mkdirp "0.5.1" supports-color "5.4.0" -moment@^2.21.0, moment@^2.22.2: - version "2.24.0" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" - integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== - -ms-rest-azure@^2.5.5: - version "2.6.0" - resolved "https://registry.yarnpkg.com/ms-rest-azure/-/ms-rest-azure-2.6.0.tgz#2098efec529eecfa0c6e215b69143abcaba12140" - integrity sha512-J6386a9krZ4VtU7CRt+Ypgo9RGf8+d3gjMBkH7zbkM4zzkhbbMOYiPRaZ+bHZcfihkKLlktTgA6rjshTjF329A== - dependencies: - adal-node "^0.1.28" - async "2.6.0" - moment "^2.22.2" - ms-rest "^2.3.2" - request "^2.88.0" - uuid "^3.2.1" - -ms-rest@^2.3.2, ms-rest@^2.3.3, ms-rest@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/ms-rest/-/ms-rest-2.5.0.tgz#d483c003f7de7703ade6bc19c3b4319affac2687" - integrity sha512-QUTg9CsmWpofDO0MR37z8B28/T9ObpQ+FM23GGDMKXw8KYDJ3cEBdK6dJTDDrtSoZG3U+S/vdmSEwJ7FNj6Kog== - dependencies: - duplexer "^0.1.1" - is-buffer "^1.1.6" - is-stream "^1.1.0" - moment "^2.21.0" - request "^2.88.0" - through "^2.3.8" - tunnel "0.0.5" - uuid "^3.2.1" - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -1124,7 +1190,12 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-keys@^1.0.11, object-keys@^1.0.12: +object-inspect@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" + integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== + +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -1139,6 +1210,14 @@ object.assign@^4.0.4: has-symbols "^1.0.0" object-keys "^1.0.11" +object.getownpropertydescriptors@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" + integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= + dependencies: + define-properties "^1.1.2" + es-abstract "^1.5.1" + once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -1206,6 +1285,11 @@ psl@^1.1.24: resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184" integrity sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw== +psl@^1.1.28: + version "1.4.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2" + integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw== + pump@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" @@ -1228,7 +1312,7 @@ punycode@^1.4.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= -punycode@^2.1.0: +punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== @@ -1360,6 +1444,11 @@ safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +sax@>=0.6.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + semver@^5.4.1: version "5.7.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" @@ -1488,6 +1577,22 @@ streamifier@~0.1.1: resolved "https://registry.yarnpkg.com/streamifier/-/streamifier-0.1.1.tgz#97e98d8fa4d105d62a2691d1dc07e820db8dfc4f" integrity sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8= +string.prototype.trimleft@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" + integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string.prototype.trimright@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" + integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" @@ -1574,6 +1679,14 @@ to-through@^2.0.0: dependencies: through2 "^2.0.3" +tough-cookie@^2.4.3: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + tough-cookie@~2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" @@ -1582,6 +1695,11 @@ tough-cookie@~2.4.3: psl "^1.1.24" punycode "^1.4.1" +tslib@^1.9.2, tslib@^1.9.3: + version "1.10.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" + integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -1589,10 +1707,10 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" -tunnel@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.5.tgz#d1532254749ed36620fcd1010865495a1fa9d0ae" - integrity sha512-gj5sdqherx4VZKMcBA4vewER7zdK25Td+z1npBqpbDys4eJrLx+SlYjJvq1bDXs2irkuJM5pf8ktaEQVipkrbA== +tunnel@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" + integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" @@ -1646,6 +1764,14 @@ util-deprecate@~1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= +util.promisify@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" + integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== + dependencies: + define-properties "^1.1.2" + object.getownpropertydescriptors "^2.0.3" + uuid@^3.1.0, uuid@^3.2.1, uuid@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" @@ -1768,11 +1894,25 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= +xml2js@^0.4.19: + version "0.4.22" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.22.tgz#4fa2d846ec803237de86f30aa9b5f70b6600de02" + integrity sha512-MWTbxAQqclRSTnehWWe5nMKzI3VmJ8ltiJEco8akcC6j3miOhjjfzKum5sId+CWhfxdOs/1xauYr8/ZDBtQiRw== + dependencies: + sax ">=0.6.0" + util.promisify "~1.0.0" + xmlbuilder "~11.0.0" + xml@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5" integrity sha1-eLpyAgApxbyHuKgaPPzXS0ovweU= +xmlbuilder@~11.0.0: + version "11.0.1" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" + integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== + "xmldom@>= 0.1.x": version "0.1.27" resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9"