Add Arc Resources to Azure view (#9271)

* Initial work

* Add setting change handler

* Fix tests

* Update loc names and add preview tag

* Remove TODOs
This commit is contained in:
Charles Gagnon
2020-02-24 08:15:27 -08:00
committed by GitHub
parent de5f1eb780
commit 10b681b3c8
20 changed files with 347 additions and 22 deletions

View File

@@ -41,6 +41,17 @@
"description": "%config.enablePublicCloudDescription%" "description": "%config.enablePublicCloudDescription%"
} }
} }
},
{
"type": "object",
"title": "Azure",
"properties": {
"azure.enableArcFeatures": {
"type": "boolean",
"default": false,
"description": "%config.enableArcFeatures%"
}
}
} }
], ],
"account-type": [ "account-type": [

View File

@@ -20,5 +20,6 @@
"config.enablePublicCloudDescription": "Should Azure public cloud integration be enabled", "config.enablePublicCloudDescription": "Should Azure public cloud integration be enabled",
"config.enableUsGovCloudDescription": "Should US Government Azure cloud (Fairfax) integration be enabled", "config.enableUsGovCloudDescription": "Should US Government Azure cloud (Fairfax) integration be enabled",
"config.enableChinaCloudDescription": "Should Azure China integration be enabled", "config.enableChinaCloudDescription": "Should Azure China integration be enabled",
"config.enableGermanyCloudDescription": "Should Azure Germany integration be enabled" "config.enableGermanyCloudDescription": "Should Azure Germany integration be enabled",
"config.enableArcFeatures": "Should features related to Azure Arc be enabled (preview)"
} }

View File

@@ -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 * as constants from '../constants';
import * as azdata from 'azdata'; import * as azdata from 'azdata';
import * as events from 'events'; import * as events from 'events';
import * as nls from 'vscode-nls'; import * as nls from 'vscode-nls';
@@ -13,6 +12,7 @@ import CredentialServiceTokenCache from './tokenCache';
import providerSettings from './providerSettings'; import providerSettings from './providerSettings';
import { AzureAccountProvider as AzureAccountProvider } from './azureAccountProvider2'; import { AzureAccountProvider as AzureAccountProvider } from './azureAccountProvider2';
import { AzureAccountProviderMetadata, ProviderSettings } from './interfaces'; import { AzureAccountProviderMetadata, ProviderSettings } from './interfaces';
import * as loc from '../localizedConstants';
let localize = nls.loadMessageBundle(); let localize = nls.loadMessageBundle();
@@ -78,11 +78,11 @@ export class AzureAccountProviderService implements vscode.Disposable {
.then( .then(
() => { () => {
let message = localize('clearTokenCacheSuccess', "Token cache successfully cleared"); let message = localize('clearTokenCacheSuccess', "Token cache successfully cleared");
vscode.window.showInformationMessage(`${constants.extensionName}: ${message}`); vscode.window.showInformationMessage(`${loc.extensionName}: ${message}`);
}, },
err => { err => {
let message = localize('clearTokenCacheFailure', "Failed to clear token cache"); let message = localize('clearTokenCacheFailure', "Failed to clear token cache");
vscode.window.showErrorMessage(`${constants.extensionName}: ${message}: ${err}`); vscode.window.showErrorMessage(`${loc.extensionName}: ${message}: ${err}`);
}); });
} }

View File

@@ -138,6 +138,10 @@ export class ApiWrapper {
return this.getConfiguration(constants.extensionConfigSectionName); return this.getConfiguration(constants.extensionConfigSectionName);
} }
public get onDidChangeConfiguration(): vscode.Event<vscode.ConfigurationChangeEvent> {
return vscode.workspace.onDidChangeConfiguration;
}
/** /**
* Parse uri * Parse uri
*/ */

View File

@@ -18,7 +18,7 @@ import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
export class AzureResourceDatabaseTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabase> { export class AzureResourceDatabaseTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabase> {
private static readonly containerId = 'azure.resource.providers.database.treeDataProvider.databaseContainer'; private static readonly containerId = 'azure.resource.providers.database.treeDataProvider.databaseContainer';
private static readonly containerLabel = localize('azure.resource.providers.database.treeDataProvider.databaseContainerLabel', "SQL Databases"); private static readonly containerLabel = localize('azure.resource.providers.database.treeDataProvider.databaseContainerLabel', "SQL database");
public constructor( public constructor(
databaseService: IAzureResourceService<azureResource.AzureResourceDatabase>, databaseService: IAzureResourceService<azureResource.AzureResourceDatabase>,

View File

@@ -17,7 +17,7 @@ import { azureResource } from '../../azure-resource';
export class AzureResourceDatabaseServerTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> { export class AzureResourceDatabaseServerTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> {
private static readonly containerId = 'azure.resource.providers.databaseServer.treeDataProvider.databaseServerContainer'; private static readonly containerId = 'azure.resource.providers.databaseServer.treeDataProvider.databaseServerContainer';
private static readonly containerLabel = localize('azure.resource.providers.databaseServer.treeDataProvider.databaseServerContainerLabel', "SQL Servers"); private static readonly containerLabel = localize('azure.resource.providers.databaseServer.treeDataProvider.databaseServerContainerLabel', "SQL server");
public constructor( public constructor(
databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>, databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,

View File

@@ -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 } from '../../interfaces';
import { PostgresServerArcTreeDataProvider as PostgresServerArcTreeDataProvider } from './postgresServerTreeDataProvider';
export class PostgresServerArcProvider implements azureResource.IAzureResourceProvider {
public constructor(
private _databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
private _apiWrapper: ApiWrapper,
private _extensionContext: ExtensionContext
) {
}
public getTreeDataProvider(): azureResource.IAzureResourceTreeDataProvider {
return new PostgresServerArcTreeDataProvider(this._databaseServerService, this._apiWrapper, this._extensionContext);
}
public get providerId(): string {
return 'azure.resource.providers.postgresArcServer';
}
}

View File

@@ -0,0 +1,32 @@
/*---------------------------------------------------------------------------------------------
* 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 { azureResource } from '../../azure-resource';
export interface PostgresArcServerGraphData extends GraphData {
properties: {
admin: string;
};
}
export const serversQuery = 'where type == "microsoft.azuredata/postgresinstances"';
export class PostgresServerArcService extends ResourceServiceBase<PostgresArcServerGraphData, azureResource.AzureResourceDatabaseServer> {
protected get query(): string {
return serversQuery;
}
protected convertResource(resource: PostgresArcServerGraphData): azureResource.AzureResourceDatabaseServer {
return {
id: resource.id,
name: resource.name,
fullName: resource.name,
loginName: resource.properties.admin,
defaultDatabaseName: 'postgres'
};
}
}

View File

@@ -0,0 +1,81 @@
/*---------------------------------------------------------------------------------------------
* 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 } from '../../interfaces';
import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
import { azureResource } from '../../azure-resource';
export class PostgresServerArcTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> {
private static readonly containerId = 'azure.resource.providers.postgresArcServer.treeDataProvider.postgresServerContainer';
private static readonly containerLabel = localize('azure.resource.providers.postgresArcServer.treeDataProvider.postgresServerContainerLabel', "PostgreSQL Hyperscale - Azure Arc");
public constructor(
databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
apiWrapper: ApiWrapper,
private _extensionContext: ExtensionContext
) {
super(databaseServerService, apiWrapper);
}
protected getTreeItemForResource(databaseServer: azureResource.AzureResourceDatabaseServer): TreeItem {
return {
id: `databaseServer_${databaseServer.id ? databaseServer.id : databaseServer.name}`,
label: databaseServer.name,
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: PostgresServerArcTreeDataProvider.containerId,
label: PostgresServerArcTreeDataProvider.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
}
};
}
}

View File

@@ -17,7 +17,7 @@ import { azureResource } from '../../azure-resource';
export class PostgresServerTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> { export class PostgresServerTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> {
private static readonly containerId = 'azure.resource.providers.databaseServer.treeDataProvider.postgresServerContainer'; 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"); private static readonly containerLabel = localize('azure.resource.providers.databaseServer.treeDataProvider.postgresServerContainerLabel', "Azure Database for PostgreSQL server");
public constructor( public constructor(
databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>, databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
@@ -32,7 +32,6 @@ export class PostgresServerTreeDataProvider extends ResourceTreeDataProviderBase
return { return {
id: `databaseServer_${databaseServer.id ? databaseServer.id : databaseServer.name}`, id: `databaseServer_${databaseServer.id ? databaseServer.id : databaseServer.name}`,
label: databaseServer.name, label: databaseServer.name,
// TODO: should get PGSQL-specific icons (also needed in that extension)
iconPath: { iconPath: {
dark: this._extensionContext.asAbsolutePath('resources/dark/sql_server_inverse.svg'), dark: this._extensionContext.asAbsolutePath('resources/dark/sql_server_inverse.svg'),
light: this._extensionContext.asAbsolutePath('resources/light/sql_server.svg') light: this._extensionContext.asAbsolutePath('resources/light/sql_server.svg')

View File

@@ -17,7 +17,7 @@ import { azureResource } from '../../azure-resource';
export class SqlInstanceTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> { export class SqlInstanceTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> {
private static readonly containerId = 'azure.resource.providers.sqlInstanceContainer'; private static readonly containerId = 'azure.resource.providers.sqlInstanceContainer';
private static readonly containerLabel = localize('azure.resource.providers.sqlInstanceContainerLabel', "SQL Managed Instances"); private static readonly containerLabel = localize('azure.resource.providers.sqlInstanceContainerLabel', "Azure SQL DB managed instance");
public constructor( public constructor(
databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>, databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,

View File

@@ -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 } from '../../interfaces';
import { SqlInstanceArcTreeDataProvider as SqlInstanceArcTreeDataProvider } from './sqlInstanceArcTreeDataProvider';
export class SqlInstanceArcProvider implements azureResource.IAzureResourceProvider {
public constructor(
private _service: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
private _apiWrapper: ApiWrapper,
private _extensionContext: ExtensionContext
) {
}
public getTreeDataProvider(): azureResource.IAzureResourceTreeDataProvider {
return new SqlInstanceArcTreeDataProvider(this._service, this._apiWrapper, this._extensionContext);
}
public get providerId(): string {
return 'azure.resource.providers.sqlInstanceArc';
}
}

View File

@@ -0,0 +1,32 @@
/*---------------------------------------------------------------------------------------------
* 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 { azureResource } from '../../azure-resource';
export interface SqlInstanceArcGraphData extends GraphData {
properties: {
admin: string;
hybridDataManager: string;
};
}
const instanceQuery = 'where type == "microsoft.azuredata/sqlinstances"';
export class SqlInstanceArcResourceService extends ResourceServiceBase<SqlInstanceArcGraphData, azureResource.AzureResourceDatabaseServer> {
protected get query(): string {
return instanceQuery;
}
protected convertResource(resource: SqlInstanceArcGraphData): azureResource.AzureResourceDatabaseServer {
return {
id: resource.id,
name: resource.name,
fullName: resource.name,
loginName: resource.properties.admin,
defaultDatabaseName: 'master'
};
}
}

View File

@@ -0,0 +1,78 @@
/*---------------------------------------------------------------------------------------------
* 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 } from '../../interfaces';
import { ResourceTreeDataProviderBase } from '../resourceTreeDataProviderBase';
import { azureResource } from '../../azure-resource';
export class SqlInstanceArcTreeDataProvider extends ResourceTreeDataProviderBase<azureResource.AzureResourceDatabaseServer> {
private static readonly containerId = 'azure.resource.providers.sqlInstanceArcContainer';
private static readonly containerLabel = localize('azure.resource.providers.sqlInstanceArcContainerLabel', "Azure SQL DB managed instance Azure Arc");
public constructor(
databaseServerService: IAzureResourceService<azureResource.AzureResourceDatabaseServer>,
apiWrapper: ApiWrapper,
private _extensionContext: ExtensionContext
) {
super(databaseServerService, apiWrapper);
}
protected getTreeItemForResource(databaseServer: azureResource.AzureResourceDatabaseServer): TreeItem {
return {
id: `sqlInstance_${databaseServer.id ? databaseServer.id : databaseServer.name}`,
label: databaseServer.name,
iconPath: {
dark: this._extensionContext.asAbsolutePath('resources/dark/sql_instance_inverse.svg'),
light: this._extensionContext.asAbsolutePath('resources/light/sql_instance.svg')
},
collapsibleState: TreeItemCollapsibleState.Collapsed,
contextValue: AzureResourceItemType.databaseServer,
payload: {
id: generateGuid(),
connectionName: undefined,
serverName: databaseServer.fullName,
databaseName: databaseServer.defaultDatabaseName,
userName: databaseServer.loginName,
password: '',
authenticationType: 'SqlLogin',
savePassword: true,
groupFullName: '',
groupId: '',
providerName: 'MSSQL',
saveProfile: false,
options: {}
},
childProvider: 'MSSQL',
type: ExtensionNodeType.Server
};
}
protected createContainerNode(): azureResource.IAzureResourceNode {
return {
account: undefined,
subscription: undefined,
tenantId: undefined,
treeItem: {
id: SqlInstanceArcTreeDataProvider.containerId,
label: SqlInstanceArcTreeDataProvider.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
}
};
}
}

View File

@@ -105,7 +105,9 @@ export class AzureResourceService {
if (extension.exports && extension.exports.provideResources) { if (extension.exports && extension.exports.provideResources) {
for (const resourceProvider of <azureResource.IAzureResourceProvider[]>extension.exports.provideResources()) { for (const resourceProvider of <azureResource.IAzureResourceProvider[]>extension.exports.provideResources()) {
this.doRegisterResourceProvider(resourceProvider); if (resourceProvider) {
this.doRegisterResourceProvider(resourceProvider);
}
} }
} }
} }

View File

@@ -3,15 +3,9 @@
* 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 * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
export const extensionConfigSectionName = 'azure'; export const extensionConfigSectionName = 'azure';
export const ViewType = 'view'; export const ViewType = 'view';
export enum BuiltInCommands { export enum BuiltInCommands {
SetContext = 'setContext' SetContext = 'setContext'
} }
export const extensionName = localize('extensionName', "Azure Accounts");

View File

@@ -7,7 +7,6 @@ import * as vscode from 'vscode';
import { promises as fs } from 'fs'; import { promises as fs } from 'fs';
import * as path from 'path'; import * as path from 'path';
import * as os from 'os'; import * as os from 'os';
import * as constants from './constants';
import { AppContext } from './appContext'; import { AppContext } from './appContext';
import { ApiWrapper } from './apiWrapper'; import { ApiWrapper } from './apiWrapper';
@@ -31,6 +30,12 @@ import { SqlInstanceResourceService } from './azureResource/providers/sqlinstanc
import { SqlInstanceProvider } from './azureResource/providers/sqlinstance/sqlInstanceProvider'; import { SqlInstanceProvider } from './azureResource/providers/sqlinstance/sqlInstanceProvider';
import { PostgresServerProvider } from './azureResource/providers/postgresServer/postgresServerProvider'; import { PostgresServerProvider } from './azureResource/providers/postgresServer/postgresServerProvider';
import { PostgresServerService } from './azureResource/providers/postgresServer/postgresServerService'; import { PostgresServerService } from './azureResource/providers/postgresServer/postgresServerService';
import { SqlInstanceArcProvider } from './azureResource/providers/sqlinstanceArc/sqlInstanceArcProvider';
import { SqlInstanceArcResourceService } from './azureResource/providers/sqlinstanceArc/sqlInstanceArcService';
import { PostgresServerArcProvider } from './azureResource/providers/postgresArcServer/postgresServerProvider';
import { PostgresServerArcService } from './azureResource/providers/postgresArcServer/postgresServerService';
import { azureResource } from './azureResource/azure-resource';
import * as loc from './localizedConstants';
let extensionContext: vscode.ExtensionContext; let extensionContext: vscode.ExtensionContext;
@@ -72,16 +77,25 @@ export async function activate(context: vscode.ExtensionContext) {
registerAzureServices(appContext); registerAzureServices(appContext);
const azureResourceTree = new AzureResourceTreeProvider(appContext); const azureResourceTree = new AzureResourceTreeProvider(appContext);
pushDisposable(apiWrapper.registerTreeDataProvider('azureResourceExplorer', azureResourceTree)); pushDisposable(apiWrapper.registerTreeDataProvider('azureResourceExplorer', azureResourceTree));
pushDisposable(apiWrapper.onDidChangeConfiguration(e => onDidChangeConfiguration(e, apiWrapper), this));
registerAzureResourceCommands(appContext, azureResourceTree); registerAzureResourceCommands(appContext, azureResourceTree);
return { return {
provideResources() { provideResources() {
return [ const arcFeaturedEnabled = apiWrapper.getExtensionConfiguration().get('enableArcFeatures');
const providers: azureResource.IAzureResourceProvider[] = [
new AzureResourceDatabaseServerProvider(new AzureResourceDatabaseServerService(), apiWrapper, extensionContext), new AzureResourceDatabaseServerProvider(new AzureResourceDatabaseServerService(), apiWrapper, extensionContext),
new AzureResourceDatabaseProvider(new AzureResourceDatabaseService(), 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) new PostgresServerProvider(new PostgresServerService(), apiWrapper, extensionContext),
]; ];
if (arcFeaturedEnabled) {
providers.push(
new SqlInstanceArcProvider(new SqlInstanceArcResourceService(), apiWrapper, extensionContext),
new PostgresServerArcProvider(new PostgresServerArcService(), apiWrapper, extensionContext)
);
}
return providers;
} }
}; };
} }
@@ -89,7 +103,7 @@ export async function activate(context: vscode.ExtensionContext) {
// Create the folder for storing the token caches // Create the folder for storing the token caches
async function findOrMakeStoragePath() { async function findOrMakeStoragePath() {
let defaultLogLocation = getDefaultLogLocation(); let defaultLogLocation = getDefaultLogLocation();
let storagePath = path.join(defaultLogLocation, constants.extensionName); let storagePath = path.join(defaultLogLocation, loc.extensionName);
try { try {
await fs.mkdir(defaultLogLocation, { recursive: true }); await fs.mkdir(defaultLogLocation, { recursive: true });
@@ -132,3 +146,12 @@ function registerAzureServices(appContext: AppContext): void {
appContext.registerService<IAzureResourceSubscriptionFilterService>(AzureResourceServiceNames.subscriptionFilterService, new AzureResourceSubscriptionFilterService(new AzureResourceCacheService(extensionContext))); appContext.registerService<IAzureResourceSubscriptionFilterService>(AzureResourceServiceNames.subscriptionFilterService, new AzureResourceSubscriptionFilterService(new AzureResourceCacheService(extensionContext)));
appContext.registerService<IAzureResourceTenantService>(AzureResourceServiceNames.tenantService, new AzureResourceTenantService()); appContext.registerService<IAzureResourceTenantService>(AzureResourceServiceNames.tenantService, new AzureResourceTenantService());
} }
async function onDidChangeConfiguration(e: vscode.ConfigurationChangeEvent, apiWrapper: ApiWrapper): Promise<void> {
if (e.affectsConfiguration('azure.enableArcFeatures')) {
const response = await apiWrapper.showInformationMessage(loc.requiresReload, loc.reload);
if (response === loc.reload) {
await apiWrapper.executeCommand('workbench.action.reloadWindow');
}
}
}

View File

@@ -0,0 +1,12 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
export const extensionName = localize('azurecore.extensionName', "Azure Accounts");
export const requiresReload = localize('azurecore.requiresReload', "Modifying this setting requires reloading the window for all changes to take effect.");
export const reload = localize('azurecore.reload', "Reload");

View File

@@ -121,7 +121,7 @@ describe('AzureResourceDatabaseTreeDataProvider.getChildren', function (): void
should(child.subscription).undefined(); should(child.subscription).undefined();
should(child.tenantId).undefined(); should(child.tenantId).undefined();
should(child.treeItem.id).equal('azure.resource.providers.database.treeDataProvider.databaseContainer'); should(child.treeItem.id).equal('azure.resource.providers.database.treeDataProvider.databaseContainer');
should(child.treeItem.label).equal('SQL Databases'); should(child.treeItem.label).equal('SQL database');
should(child.treeItem.collapsibleState).equal(vscode.TreeItemCollapsibleState.Collapsed); should(child.treeItem.collapsibleState).equal(vscode.TreeItemCollapsibleState.Collapsed);
should(child.treeItem.contextValue).equal('azure.resource.itemType.databaseContainer'); should(child.treeItem.contextValue).equal('azure.resource.itemType.databaseContainer');
}); });

View File

@@ -121,7 +121,7 @@ describe('AzureResourceDatabaseServerTreeDataProvider.getChildren', function ():
should(child.subscription).undefined(); should(child.subscription).undefined();
should(child.tenantId).undefined(); should(child.tenantId).undefined();
should(child.treeItem.id).equal('azure.resource.providers.databaseServer.treeDataProvider.databaseServerContainer'); should(child.treeItem.id).equal('azure.resource.providers.databaseServer.treeDataProvider.databaseServerContainer');
should(child.treeItem.label).equal('SQL Servers'); should(child.treeItem.label).equal('SQL server');
should(child.treeItem.collapsibleState).equal(vscode.TreeItemCollapsibleState.Collapsed); should(child.treeItem.collapsibleState).equal(vscode.TreeItemCollapsibleState.Collapsed);
should(child.treeItem.contextValue).equal('azure.resource.itemType.databaseServerContainer'); should(child.treeItem.contextValue).equal('azure.resource.itemType.databaseServerContainer');
}); });