Revert "Port the Azure Resource Explorer extension to core." (#2770)

* Revert "change how query plan is handled (#2735)"

This reverts commit 0693080630.

* Revert "center the icon (#2760)"

This reverts commit 75d27837c2.

* Revert "Alanren/edit data improvement (#2748)"

This reverts commit 597f29e90a.

* Revert "Port the Azure Resource Explorer extension to core. (#2701)"

This reverts commit a77bb50b9e.
This commit is contained in:
Karl Burtram
2018-10-05 12:40:56 -07:00
committed by GitHub
parent e672fbf6e2
commit 210447cd37
70 changed files with 5 additions and 3955 deletions

View File

@@ -1,120 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { window, QuickPickItem } from 'vscode';
import { IConnectionProfile } from 'sqlops';
import { generateGuid } from './utils';
import { ApiWrapper } from '../apiWrapper';
import { TreeNode } from '../treeNodes';
import { AzureResourceTreeProvider } from './tree/treeProvider';
import { AzureResourceDatabaseServerTreeNode } from './tree/databaseServerTreeNode';
import { AzureResourceDatabaseTreeNode } from './tree/databaseTreeNode';
import { AzureResourceAccountTreeNode } from './tree/accountTreeNode';
import { AzureResourceServicePool } from './servicePool';
import { AzureResourceSubscription } from './models';
export function registerAzureResourceCommands(apiWrapper: ApiWrapper, tree: AzureResourceTreeProvider): void {
apiWrapper.registerCommand('azureresource.selectsubscriptions', async (node?: TreeNode) => {
if (!(node instanceof AzureResourceAccountTreeNode)) {
return;
}
const accountNode = node as AzureResourceAccountTreeNode;
const servicePool = AzureResourceServicePool.getInstance();
let subscriptions = await accountNode.getCachedSubscriptions();
if (!subscriptions || subscriptions.length === 0) {
const credentials = await servicePool.credentialService.getCredentials(accountNode.account);
subscriptions = await servicePool.subscriptionService.getSubscriptions(accountNode.account, credentials);
}
const selectedSubscriptions = (await servicePool.subscriptionFilterService.getSelectedSubscriptions(accountNode.account)) || <AzureResourceSubscription[]>[];
const selectedSubscriptionIds: string[] = [];
if (selectedSubscriptions.length > 0) {
selectedSubscriptionIds.push(...selectedSubscriptions.map((subscription) => subscription.id));
} else {
// ALL subscriptions are selected by default
selectedSubscriptionIds.push(...subscriptions.map((subscription) => subscription.id));
}
interface SubscriptionQuickPickItem extends QuickPickItem {
subscription: AzureResourceSubscription;
}
const subscriptionItems: SubscriptionQuickPickItem[] = subscriptions.map((subscription) => {
return {
label: subscription.name,
picked: selectedSubscriptionIds.indexOf(subscription.id) !== -1,
subscription: subscription
};
});
const pickedSubscriptionItems = (await window.showQuickPick(subscriptionItems, { canPickMany: true }));
if (pickedSubscriptionItems && pickedSubscriptionItems.length > 0) {
tree.refresh(node, false);
const pickedSubscriptions = pickedSubscriptionItems.map((subscriptionItem) => subscriptionItem.subscription);
await servicePool.subscriptionFilterService.saveSelectedSubscriptions(accountNode.account, pickedSubscriptions);
}
});
apiWrapper.registerCommand('azureresource.refreshall', () => tree.notifyNodeChanged(undefined));
apiWrapper.registerCommand('azureresource.refresh', async (node?: TreeNode) => {
tree.refresh(node, true);
});
apiWrapper.registerCommand('azureresource.connectsqldb', async (node?: TreeNode) => {
let connectionProfile: IConnectionProfile = {
id: generateGuid(),
connectionName: undefined,
serverName: undefined,
databaseName: undefined,
userName: undefined,
password: '',
authenticationType: undefined,
savePassword: true,
groupFullName: '',
groupId: '',
providerName: undefined,
saveProfile: true,
options: {
}
};
if (node instanceof AzureResourceDatabaseServerTreeNode) {
let databaseServer = node.databaseServer;
connectionProfile.connectionName = `connection to '${databaseServer.defaultDatabaseName}' on '${databaseServer.fullName}'`;
connectionProfile.serverName = databaseServer.fullName;
connectionProfile.databaseName = databaseServer.defaultDatabaseName;
connectionProfile.userName = databaseServer.loginName;
connectionProfile.authenticationType = 'SqlLogin';
connectionProfile.providerName = 'MSSQL';
}
if (node instanceof AzureResourceDatabaseTreeNode) {
let database = node.database;
connectionProfile.connectionName = `connection to '${database.name}' on '${database.serverFullName}'`;
connectionProfile.serverName = database.serverFullName;
connectionProfile.databaseName = database.name;
connectionProfile.userName = database.loginName;
connectionProfile.authenticationType = 'SqlLogin';
connectionProfile.providerName = 'MSSQL';
}
const conn = await apiWrapper.openConnectionDialog(undefined, connectionProfile, { saveConnection: true, showDashboard: true });
if (conn) {
apiWrapper.executeCommand('workbench.view.connections');
}
});
apiWrapper.registerCommand('azureresource.signin', async (node?: TreeNode) => {
apiWrapper.executeCommand('sql.action.accounts.manageLinkedAccount');
});
}

View File

@@ -1,16 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
export enum AzureResourceItemType {
account = 'azureResource.itemType.account',
subscription = 'azureResource.itemType.subscription',
databaseContainer = 'azureResource.itemType.databaseContainer',
database = 'azureResource.itemType.database',
databaseServerContainer = 'azureResource.itemType.databaseServerContainer',
databaseServer = 'azureResource.itemType.databaseServer',
message = 'azureResource.itemType.message'
}

View File

@@ -1,15 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
export class AzureResourceCredentialError extends Error {
constructor(
message: string,
public innerError: Error
) {
super(message);
}
}

View File

@@ -1,54 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { ServiceClientCredentials } from 'ms-rest';
import { Account, DidChangeAccountsParams } from 'sqlops';
import { Event } from 'vscode';
import { AzureResourceSubscription, AzureResourceDatabaseServer, AzureResourceDatabase } from './models';
export interface IAzureResourceAccountService {
getAccounts(): Promise<Account[]>;
readonly onDidChangeAccounts: Event<DidChangeAccountsParams>;
}
export interface IAzureResourceCredentialService {
getCredentials(account: Account): Promise<ServiceClientCredentials[]>;
}
export interface IAzureResourceSubscriptionService {
getSubscriptions(account: Account, credentials: ServiceClientCredentials[]): Promise<AzureResourceSubscription[]>;
}
export interface IAzureResourceSubscriptionFilterService {
getSelectedSubscriptions(account: Account): Promise<AzureResourceSubscription[]>;
saveSelectedSubscriptions(account: Account, selectedSubscriptions: AzureResourceSubscription[]): Promise<void>;
}
export interface IAzureResourceDatabaseServerService {
getDatabaseServers(subscription: AzureResourceSubscription, credentials: ServiceClientCredentials[]): Promise<AzureResourceDatabaseServer[]>;
}
export interface IAzureResourceDatabaseService {
getDatabases(subscription: AzureResourceSubscription, credentials: ServiceClientCredentials[]): Promise<AzureResourceDatabase[]>;
}
export interface IAzureResourceCacheService {
get<T>(key: string): T | undefined;
update<T>(key: string, value: T): void;
}
export interface IAzureResourceContextService {
getAbsolutePath(relativePath: string): string;
executeCommand(commandId: string, ...args: any[]): void;
showErrorMessage(errorMessage: string): void;
}

View File

@@ -1,25 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
export interface AzureResourceSubscription {
id: string;
name: string;
}
export interface AzureResourceDatabaseServer {
name: string;
fullName: string;
loginName: string;
defaultDatabaseName: string;
}
export interface AzureResourceDatabase {
name: string;
serverName: string;
serverFullName: string;
loginName: string;
}

View File

@@ -1,35 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import {
IAzureResourceAccountService,
IAzureResourceCredentialService,
IAzureResourceSubscriptionService,
IAzureResourceSubscriptionFilterService,
IAzureResourceDatabaseService,
IAzureResourceDatabaseServerService,
IAzureResourceCacheService,
IAzureResourceContextService } from './interfaces';
export class AzureResourceServicePool {
private constructor() { }
public static getInstance(): AzureResourceServicePool {
return AzureResourceServicePool._instance;
}
public contextService: IAzureResourceContextService;
public cacheService: IAzureResourceCacheService;
public accountService: IAzureResourceAccountService;
public credentialService: IAzureResourceCredentialService;
public subscriptionService: IAzureResourceSubscriptionService;
public subscriptionFilterService: IAzureResourceSubscriptionFilterService;
public databaseService: IAzureResourceDatabaseService;
public databaseServerService: IAzureResourceDatabaseServerService;
private static readonly _instance = new AzureResourceServicePool();
}

View File

@@ -1,32 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { Event } from 'vscode';
import { Account, DidChangeAccountsParams } from 'sqlops';
import { ApiWrapper } from '../../apiWrapper';
import { IAzureResourceAccountService } from '../interfaces';
export class AzureResourceAccountService implements IAzureResourceAccountService {
public constructor(
apiWrapper: ApiWrapper
) {
this._apiWrapper = apiWrapper;
this._onDidChangeAccounts = this._apiWrapper.onDidChangeAccounts;
}
public async getAccounts(): Promise<Account[]> {
return await this._apiWrapper.getAllAccounts();
}
public get onDidChangeAccounts(): Event<DidChangeAccountsParams> {
return this._onDidChangeAccounts;
}
private _apiWrapper: ApiWrapper = undefined;
private _onDidChangeAccounts: Event<DidChangeAccountsParams> = undefined;
}

View File

@@ -1,25 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { ExtensionContext } from "vscode";
import { IAzureResourceCacheService } from "../interfaces";
export class AzureResourceCacheService implements IAzureResourceCacheService {
public constructor(
public readonly context: ExtensionContext
) {
}
public get<T>(key: string): T | undefined {
return this.context.workspaceState.get(key);
}
public update<T>(key: string, value: T): void {
this.context.workspaceState.update(key, value);
}
}

View File

@@ -1,36 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { ExtensionContext } from "vscode";
import { ApiWrapper } from "../../apiWrapper";
import { IAzureResourceContextService } from "../interfaces";
export class AzureResourceContextService implements IAzureResourceContextService {
public constructor(
context: ExtensionContext,
apiWrapper: ApiWrapper
) {
this._context = context;
this._apiWrapper = apiWrapper;
}
public getAbsolutePath(relativePath: string): string {
return this._context.asAbsolutePath(relativePath);
}
public executeCommand(commandId: string, ...args: any[]): void {
this._apiWrapper.executeCommand(commandId, args);
}
public showErrorMessage(errorMessage: string): void {
this._apiWrapper.showErrorMessage(errorMessage);
}
private _context: ExtensionContext = undefined;
private _apiWrapper: ApiWrapper = undefined;
}

View File

@@ -1,43 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { Account } from 'sqlops';
import { TokenCredentials, ServiceClientCredentials } from 'ms-rest';
import { ApiWrapper } from '../../apiWrapper';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import { IAzureResourceCredentialService } from '../interfaces';
import { AzureResourceCredentialError } from '../errors';
export class AzureResourceCredentialService implements IAzureResourceCredentialService {
public constructor(
apiWrapper: ApiWrapper
) {
this._apiWrapper = apiWrapper;
}
public async getCredentials(account: Account): Promise<ServiceClientCredentials[]> {
try {
let credentials: TokenCredentials[] = [];
let tokens = await this._apiWrapper.getSecurityToken(account);
for (let tenant of account.properties.tenants) {
let token = tokens[tenant.id].token;
let tokenType = tokens[tenant.id].tokenType;
credentials.push(new TokenCredentials(token, tokenType));
}
return credentials;
} catch (error) {
throw new AzureResourceCredentialError(localize('azureResource.services.credentialService.credentialError', 'Failed to get credential for account {0}. Please refresh the account.', account.key.accountId), error);
}
}
private _apiWrapper: ApiWrapper = undefined;
}

View File

@@ -1,39 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { ServiceClientCredentials } from 'ms-rest';
import { SqlManagementClient } from 'azure-arm-sql';
import { IAzureResourceDatabaseServerService } from '../interfaces';
import { AzureResourceSubscription, AzureResourceDatabaseServer } from '../models';
export class AzureResourceDatabaseServerService implements IAzureResourceDatabaseServerService {
public async getDatabaseServers(subscription: AzureResourceSubscription, credentials: ServiceClientCredentials[]): Promise<AzureResourceDatabaseServer[]> {
let databaseServers: AzureResourceDatabaseServer[] = [];
for (let cred of credentials) {
let sqlManagementClient = new SqlManagementClient(cred, subscription.id);
try {
let svrs = await sqlManagementClient.servers.list();
svrs.forEach((svr) => databaseServers.push({
name: svr.name,
fullName: svr.fullyQualifiedDomainName,
loginName: svr.administratorLogin,
defaultDatabaseName: 'master'
}));
} catch (error) {
if (error.code === 'InvalidAuthenticationTokenTenant' && error.statusCode === 401) {
/**
* There may be multiple tenants for an account and it may throw exceptions like following. Just swallow the exception here.
* The access token is from the wrong issuer. It must match one of the tenants associated with this subscription.
*/
}
}
}
return databaseServers;
}
}

View File

@@ -1,51 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { ServiceClientCredentials } from 'ms-rest';
import { SqlManagementClient } from 'azure-arm-sql';
import { IAzureResourceDatabaseService } from '../interfaces';
import { AzureResourceSubscription, AzureResourceDatabase } from '../models';
export class AzureResourceDatabaseService implements IAzureResourceDatabaseService {
public async getDatabases(subscription: AzureResourceSubscription, credentials: ServiceClientCredentials[]): Promise<AzureResourceDatabase[]> {
let databases: AzureResourceDatabase[] = [];
for (let cred of credentials) {
let sqlManagementClient = new SqlManagementClient(cred, subscription.id);
try {
let svrs = await sqlManagementClient.servers.list();
for (let svr of svrs) {
// Extract resource group name from svr.id
let svrIdRegExp = new RegExp(`\/subscriptions\/${subscription.id}\/resourceGroups\/(.+)\/providers\/Microsoft\.Sql\/servers\/${svr.name}`);
if (!svrIdRegExp.test(svr.id)) {
continue;
}
let founds = svrIdRegExp.exec(svr.id);
let resouceGroup = founds[1];
let 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
}));
}
} catch (error) {
if (error.code === 'InvalidAuthenticationTokenTenant' && error.statusCode === 401) {
/**
* There may be multiple tenants for an account and it may throw exceptions like following. Just swallow the exception here.
* The access token is from the wrong issuer. It must match one of the tenants associated with this subscription.
*/
}
}
}
return databases;
}
}

View File

@@ -1,77 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { WorkspaceConfiguration, ConfigurationTarget } from 'vscode';
import { Account } from 'sqlops';
import { IAzureResourceSubscriptionFilterService, IAzureResourceCacheService } from '../interfaces';
import { AzureResourceSubscription } from '../models';
interface AzureResourceSelectedSubscriptionsCache {
selectedSubscriptions: { [accountId: string]: AzureResourceSubscription[]};
}
export class AzureResourceSubscriptionFilterService implements IAzureResourceSubscriptionFilterService {
public constructor(
cacheService: IAzureResourceCacheService
) {
this._cacheService = cacheService;
}
public async getSelectedSubscriptions(account: Account): Promise<AzureResourceSubscription[]> {
let selectedSubscriptions: AzureResourceSubscription[] = [];
const cache = this._cacheService.get<AzureResourceSelectedSubscriptionsCache>(AzureResourceSubscriptionFilterService.CacheKey);
if (cache) {
selectedSubscriptions = cache.selectedSubscriptions[account.key.accountId];
}
return selectedSubscriptions;
}
public async saveSelectedSubscriptions(account: Account, selectedSubscriptions: AzureResourceSubscription[]): Promise<void> {
let selectedSubscriptionsCache: { [accountId: string]: AzureResourceSubscription[]} = {};
const cache = this._cacheService.get<AzureResourceSelectedSubscriptionsCache>(AzureResourceSubscriptionFilterService.CacheKey);
if (cache) {
selectedSubscriptionsCache = cache.selectedSubscriptions;
}
if (!selectedSubscriptionsCache) {
selectedSubscriptionsCache = {};
}
selectedSubscriptionsCache[account.key.accountId] = selectedSubscriptions;
this._cacheService.update<AzureResourceSelectedSubscriptionsCache>(AzureResourceSubscriptionFilterService.CacheKey, { selectedSubscriptions: selectedSubscriptionsCache });
const filters: string[] = [];
for (const accountId in selectedSubscriptionsCache) {
filters.push(...selectedSubscriptionsCache[accountId].map((subcription) => `${accountId}/${subcription.id}/${subcription.name}`));
}
const resourceFilterConfig = this._config.inspect<string[]>(AzureResourceSubscriptionFilterService.FilterConfigName);
let configTarget = ConfigurationTarget.Global;
if (resourceFilterConfig) {
if (resourceFilterConfig.workspaceFolderValue) {
configTarget = ConfigurationTarget.WorkspaceFolder;
} else if (resourceFilterConfig.workspaceValue) {
configTarget = ConfigurationTarget.Workspace;
} else if (resourceFilterConfig.globalValue) {
configTarget = ConfigurationTarget.Global;
}
}
await this._config.update(AzureResourceSubscriptionFilterService.FilterConfigName, filters, configTarget);
}
private _config: WorkspaceConfiguration = undefined;
private _cacheService: IAzureResourceCacheService = undefined;
private static readonly FilterConfigName = 'resourceFilter';
private static readonly CacheKey = 'azureResource.cache.selectedSubscriptions';
}

View File

@@ -1,33 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { Account } from 'sqlops';
import { ServiceClientCredentials } from 'ms-rest';
import { SubscriptionClient } from 'azure-arm-resource';
import { IAzureResourceSubscriptionService } from '../interfaces';
import { AzureResourceSubscription } from '../models';
export class AzureResourceSubscriptionService implements IAzureResourceSubscriptionService {
public async getSubscriptions(account: Account, credentials: ServiceClientCredentials[]): Promise<AzureResourceSubscription[]> {
let subscriptions: AzureResourceSubscription[] = [];
for (let cred of credentials) {
let subClient = new SubscriptionClient.SubscriptionClient(cred);
try {
let subs = await subClient.subscriptions.list();
subs.forEach((sub) => subscriptions.push({
id: sub.subscriptionId,
name: sub.displayName
}));
} catch (error) {
// Swallow the exception here.
}
}
return subscriptions;
}
}

View File

@@ -1,51 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TreeItem, TreeItemCollapsibleState } from 'vscode';
import { NodeInfo } from 'sqlops';
import { TreeNode } from '../../treeNodes';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import { AzureResourceItemType } from '../constants';
export class AzureResourceAccountNotSignedInTreeNode extends TreeNode {
public getChildren(): TreeNode[] | Promise<TreeNode[]> {
return [];
}
public getTreeItem(): TreeItem | Promise<TreeItem> {
let item = new TreeItem(AzureResourceAccountNotSignedInTreeNode.SignInLabel, TreeItemCollapsibleState.None);
item.contextValue = AzureResourceItemType.message;
item.command = {
title: AzureResourceAccountNotSignedInTreeNode.SignInLabel,
command: 'azureresource.signin',
arguments: [this]
};
return item;
}
public getNodeInfo(): NodeInfo {
return {
label: AzureResourceAccountNotSignedInTreeNode.SignInLabel,
isLeaf: true,
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath(),
nodeStatus: undefined,
nodeType: AzureResourceItemType.message,
nodeSubType: undefined,
iconType: AzureResourceItemType.message
};
}
public get nodePathValue(): string {
return 'message_accountNotSignedIn';
}
private static readonly SignInLabel = localize('azureResource.tree.accountNotSignedInTreeNode.signIn', 'Sign in to Azure ...');
}

View File

@@ -1,155 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* 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 'sqlops';
import { TreeNode } from '../../treeNodes';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import { AzureResourceContainerTreeNodeBase } from './baseTreeNodes';
import { AzureResourceItemType } from '../constants';
import { AzureResourceSubscriptionTreeNode } from './subscriptionTreeNode';
import { AzureResourceMessageTreeNode } from './messageTreeNode';
import { AzureResourceErrorMessageUtil } from '../utils';
import { AzureResourceSubscription } from '../models';
import { IAzureResourceTreeChangeHandler } from './treeProvider';
export class AzureResourceAccountTreeNode extends AzureResourceContainerTreeNodeBase {
public constructor(
account: Account,
treeChangeHandler: IAzureResourceTreeChangeHandler
) {
super(account, treeChangeHandler, undefined);
this._id = `account_${this.account.key.accountId}`;
this._label = this.generateLabel();
}
public async getChildren(): Promise<TreeNode[]> {
try {
let subscriptions: AzureResourceSubscription[] = [];
if (this._isClearingCache) {
const credentials = await this.getCredentials();
subscriptions = (await this.servicePool.subscriptionService.getSubscriptions(this.account, credentials)) || <AzureResourceSubscription[]>[];
let cache = this.getCache<AzureResourceSubscriptionsCache>();
if (!cache) {
cache = { subscriptions: { } };
}
cache.subscriptions[this.account.key.accountId] = subscriptions;
this.updateCache<AzureResourceSubscriptionsCache>(cache);
this._isClearingCache = false;
} else {
subscriptions = await this.getCachedSubscriptions();
}
this._totalSubscriptionCount = subscriptions.length;
let selectedSubscriptions = await this.servicePool.subscriptionFilterService.getSelectedSubscriptions(this.account);
let selectedSubscriptionIds = (selectedSubscriptions || <AzureResourceSubscription[]>[]).map((subscription) => subscription.id);
if (selectedSubscriptionIds.length > 0) {
subscriptions = subscriptions.filter((subscription) => selectedSubscriptionIds.indexOf(subscription.id) !== -1);
this._selectedSubscriptionCount = selectedSubscriptionIds.length;
} else {
// ALL subscriptions are listed by default
this._selectedSubscriptionCount = this._totalSubscriptionCount;
}
this.refreshLabel();
if (subscriptions.length === 0) {
return [AzureResourceMessageTreeNode.create(AzureResourceAccountTreeNode.NoSubscriptions, this)];
} else {
return subscriptions.map((subscription) => new AzureResourceSubscriptionTreeNode(subscription, this.account, this.treeChangeHandler, this));
}
} catch (error) {
return [AzureResourceMessageTreeNode.create(AzureResourceErrorMessageUtil.getErrorMessage(error), this)];
}
}
public async getCachedSubscriptions(): Promise<AzureResourceSubscription[]> {
const subscriptions: AzureResourceSubscription[] = [];
const cache = this.getCache<AzureResourceSubscriptionsCache>();
if (cache) {
subscriptions.push(...cache.subscriptions[this.account.key.accountId]);
}
return subscriptions;
}
public getTreeItem(): TreeItem | Promise<TreeItem> {
let item = new TreeItem(this._label, TreeItemCollapsibleState.Collapsed);
item.id = this._id;
item.contextValue = AzureResourceItemType.account;
item.iconPath = {
dark: this.servicePool.contextService.getAbsolutePath('resources/dark/account_inverse.svg'),
light: this.servicePool.contextService.getAbsolutePath('resources/light/account.svg')
};
return item;
}
public getNodeInfo(): NodeInfo {
return {
label: this._label,
isLeaf: false,
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath(),
nodeStatus: undefined,
nodeType: AzureResourceItemType.account,
nodeSubType: undefined,
iconType: AzureResourceItemType.account
};
}
public get nodePathValue(): string {
return this._id;
}
public get totalSubscriptionCount(): number {
return this._totalSubscriptionCount;
}
public get selectedSubscriptionCount(): number {
return this._selectedSubscriptionCount;
}
protected refreshLabel(): void {
const newLabel = this.generateLabel();
if (this._label !== newLabel) {
this._label = newLabel;
this.treeChangeHandler.notifyNodeChanged(this);
}
}
protected get cacheKey(): string {
return 'azureResource.cache.subscriptions';
}
private generateLabel(): string {
let label = `${this.account.displayInfo.displayName} (${this.account.key.accountId})`;
if (this._totalSubscriptionCount !== 0) {
label += ` (${this._selectedSubscriptionCount} / ${this._totalSubscriptionCount} subscriptions)`;
}
return label;
}
private _id: string = undefined;
private _label: string = undefined;
private _totalSubscriptionCount = 0;
private _selectedSubscriptionCount = 0;
private static readonly NoSubscriptions = localize('azureResource.tree.accountTreeNode.noSubscriptions', 'No Subscriptions found.');
}
interface AzureResourceSubscriptionsCache {
subscriptions: { [accountId: string]: AzureResourceSubscription[] };
}

View File

@@ -1,71 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { Account } from 'sqlops';
import { ServiceClientCredentials } from 'ms-rest';
import { TreeNode } from '../../treeNodes';
import { AzureResourceServicePool } from '../servicePool';
import { AzureResourceCredentialError } from '../errors';
import { IAzureResourceTreeChangeHandler } from './treeChangeHandler';
export abstract class AzureResourceTreeNodeBase extends TreeNode {
public constructor(
public readonly treeChangeHandler: IAzureResourceTreeChangeHandler,
parent: TreeNode
) {
super();
this.parent = parent;
}
public readonly servicePool = AzureResourceServicePool.getInstance();
}
export abstract class AzureResourceContainerTreeNodeBase extends AzureResourceTreeNodeBase {
public constructor(
public readonly account: Account,
treeChangeHandler: IAzureResourceTreeChangeHandler,
parent: TreeNode
) {
super(treeChangeHandler, parent);
}
public clearCache(): void {
this._isClearingCache = true;
}
public get isClearingCache(): boolean {
return this._isClearingCache;
}
protected async getCredentials(): Promise<ServiceClientCredentials[]> {
try {
return await this.servicePool.credentialService.getCredentials(this.account);
} catch (error) {
if (error instanceof AzureResourceCredentialError) {
this.servicePool.contextService.showErrorMessage(error.message);
this.servicePool.contextService.executeCommand('azureresource.signin');
} else {
throw error;
}
}
}
protected updateCache<T>(cache: T): void {
this.servicePool.cacheService.update<T>(this.cacheKey, cache);
}
protected getCache<T>(): T {
return this.servicePool.cacheService.get<T>(this.cacheKey);
}
protected abstract get cacheKey(): string;
protected _isClearingCache = true;
}

View File

@@ -1,103 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* 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 'sqlops';
import { TreeNode } from '../../treeNodes';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import { AzureResourceContainerTreeNodeBase } from './baseTreeNodes';
import { AzureResourceItemType } from '../constants';
import { AzureResourceErrorMessageUtil } from '../utils';
import { AzureResourceDatabaseTreeNode } from './databaseTreeNode';
import { AzureResourceMessageTreeNode } from './messageTreeNode';
import { AzureResourceSubscription, AzureResourceDatabase } from '../models';
import { IAzureResourceTreeChangeHandler } from './treeProvider';
export class AzureResourceDatabaseContainerTreeNode extends AzureResourceContainerTreeNodeBase {
public constructor(
public readonly subscription: AzureResourceSubscription,
account: Account,
treeChangeHandler: IAzureResourceTreeChangeHandler,
parent: TreeNode
) {
super(account, treeChangeHandler, parent);
}
public async getChildren(): Promise<TreeNode[]> {
try {
let databases: AzureResourceDatabase[] = [];
if (this._isClearingCache) {
let credentials = await this.getCredentials();
databases = (await this.servicePool.databaseService.getDatabases(this.subscription, credentials)) || <AzureResourceDatabase[]>[];
let cache = this.getCache<AzureResourceDatabasesCache>();
if (!cache) {
cache = { databases: { } };
}
cache.databases[this.subscription.id] = databases;
this.updateCache(cache);
this._isClearingCache = false;
} else {
const cache = this.getCache<AzureResourceDatabasesCache>();
if (cache) {
databases = cache.databases[this.subscription.id] || <AzureResourceDatabase[]>[];
}
}
if (databases.length === 0) {
return [AzureResourceMessageTreeNode.create(AzureResourceDatabaseContainerTreeNode.NoDatabases, this)];
} else {
return databases.map((database) => new AzureResourceDatabaseTreeNode(database, this.treeChangeHandler, this));
}
} catch (error) {
return [AzureResourceMessageTreeNode.create(AzureResourceErrorMessageUtil.getErrorMessage(error), this)];
}
}
public getTreeItem(): TreeItem | Promise<TreeItem> {
let item = new TreeItem(AzureResourceDatabaseContainerTreeNode.Label, TreeItemCollapsibleState.Collapsed);
item.contextValue = AzureResourceItemType.databaseContainer;
item.iconPath = {
dark: this.servicePool.contextService.getAbsolutePath('resources/dark/folder_inverse.svg'),
light: this.servicePool.contextService.getAbsolutePath('resources/light/folder.svg')
};
return item;
}
public getNodeInfo(): NodeInfo {
return {
label: AzureResourceDatabaseContainerTreeNode.Label,
isLeaf: false,
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath(),
nodeStatus: undefined,
nodeType: AzureResourceItemType.databaseContainer,
nodeSubType: undefined,
iconType: AzureResourceItemType.databaseContainer
};
}
public get nodePathValue(): string {
return 'databaseContainer';
}
protected get cacheKey(): string {
return 'azureResource.cache.databases';
}
private static readonly Label = localize('azureResource.tree.databaseContainerTreeNode.label', 'SQL Databases');
private static readonly NoDatabases = localize('azureResource.tree.databaseContainerTreeNode.noDatabases', 'No SQL Databases found.');
}
interface AzureResourceDatabasesCache {
databases: { [subscriptionId: string]: AzureResourceDatabase[] };
}

View File

@@ -1,103 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* 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 'sqlops';
import { TreeNode } from '../../treeNodes';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import { AzureResourceContainerTreeNodeBase } from './baseTreeNodes';
import { AzureResourceItemType } from '../constants';
import { AzureResourceMessageTreeNode } from './messageTreeNode';
import { AzureResourceErrorMessageUtil } from '../utils';
import { AzureResourceSubscription, AzureResourceDatabaseServer } from '../models';
import { AzureResourceDatabaseServerTreeNode } from './databaseServerTreeNode';
import { IAzureResourceTreeChangeHandler } from './treeProvider';
export class AzureResourceDatabaseServerContainerTreeNode extends AzureResourceContainerTreeNodeBase {
public constructor(
public readonly subscription: AzureResourceSubscription,
account: Account,
treeChangeHandler: IAzureResourceTreeChangeHandler,
parent: TreeNode
) {
super(account, treeChangeHandler, parent);
}
public async getChildren(): Promise<TreeNode[]> {
try {
let databaseServers: AzureResourceDatabaseServer[] = [];
if (this._isClearingCache) {
let credentials = await this.getCredentials();
databaseServers = (await this.servicePool.databaseServerService.getDatabaseServers(this.subscription, credentials)) || <AzureResourceDatabaseServer[]>[];
let cache = this.getCache<AzureResourceDatabaseServersCache>();
if (!cache) {
cache = { databaseServers: { } };
}
cache.databaseServers[this.subscription.id] = databaseServers;
this.updateCache<AzureResourceDatabaseServersCache>(cache);
this._isClearingCache = false;
} else {
const cache = this.getCache<AzureResourceDatabaseServersCache>();
if (cache) {
databaseServers = cache.databaseServers[this.subscription.id] || <AzureResourceDatabaseServer[]>[];
}
}
if (databaseServers.length === 0) {
return [AzureResourceMessageTreeNode.create(AzureResourceDatabaseServerContainerTreeNode.NoDatabaseServers, this)];
} else {
return databaseServers.map((server) => new AzureResourceDatabaseServerTreeNode(server, this.treeChangeHandler, this));
}
} catch (error) {
return [AzureResourceMessageTreeNode.create(AzureResourceErrorMessageUtil.getErrorMessage(error), this)];
}
}
public getTreeItem(): TreeItem | Promise<TreeItem> {
let item = new TreeItem(AzureResourceDatabaseServerContainerTreeNode.Label, TreeItemCollapsibleState.Collapsed);
item.contextValue = AzureResourceItemType.databaseServerContainer;
item.iconPath = {
dark: this.servicePool.contextService.getAbsolutePath('resources/dark/folder_inverse.svg'),
light: this.servicePool.contextService.getAbsolutePath('resources/light/folder.svg')
};
return item;
}
public getNodeInfo(): NodeInfo {
return {
label: AzureResourceDatabaseServerContainerTreeNode.Label,
isLeaf: false,
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath(),
nodeStatus: undefined,
nodeType: AzureResourceItemType.databaseServerContainer,
nodeSubType: undefined,
iconType: AzureResourceItemType.databaseServerContainer
};
}
public get nodePathValue(): string {
return 'databaseServerContainer';
}
protected get cacheKey(): string {
return 'azureResource.cache.databaseServers';
}
private static readonly Label = localize('azureResource.tree.databaseServerContainerTreeNode.label', 'SQL Servers');
private static readonly NoDatabaseServers = localize('azureResource.tree.databaseContainerTreeNode.noDatabaseServers', 'No SQL Servers found.');
}
interface AzureResourceDatabaseServersCache {
databaseServers: { [subscriptionId: string]: AzureResourceDatabaseServer[] };
}

View File

@@ -1,57 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TreeItem, TreeItemCollapsibleState } from 'vscode';
import { NodeInfo } from 'sqlops';
import { TreeNode } from '../../treeNodes';
import { AzureResourceTreeNodeBase } from './baseTreeNodes';
import { AzureResourceItemType } from '../constants';
import { AzureResourceDatabaseServer } from '../models';
import { IAzureResourceTreeChangeHandler } from './treeProvider';
export class AzureResourceDatabaseServerTreeNode extends AzureResourceTreeNodeBase {
public constructor(
public readonly databaseServer: AzureResourceDatabaseServer,
treeChangeHandler: IAzureResourceTreeChangeHandler,
parent: TreeNode
) {
super(treeChangeHandler, parent);
}
public async getChildren(): Promise<TreeNode[]> {
return [];
}
public getTreeItem(): TreeItem | Promise<TreeItem> {
let item = new TreeItem(this.databaseServer.name, TreeItemCollapsibleState.None);
item.contextValue = AzureResourceItemType.databaseServer;
item.iconPath = {
dark: this.servicePool.contextService.getAbsolutePath('resources/dark/sql_server_inverse.svg'),
light: this.servicePool.contextService.getAbsolutePath('resources/light/sql_server.svg')
};
return item;
}
public getNodeInfo(): NodeInfo {
return {
label: this.databaseServer.name,
isLeaf: true,
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath(),
nodeStatus: undefined,
nodeType: AzureResourceItemType.databaseServer,
nodeSubType: undefined,
iconType: AzureResourceItemType.databaseServer
};
}
public get nodePathValue(): string {
return `databaseServer_${this.databaseServer.name}`;
}
}

View File

@@ -1,61 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TreeItem, TreeItemCollapsibleState } from 'vscode';
import { NodeInfo } from 'sqlops';
import { TreeNode } from '../../treeNodes';
import { AzureResourceTreeNodeBase } from './baseTreeNodes';
import { AzureResourceItemType } from '../constants';
import { AzureResourceDatabase } from '../models';
import { IAzureResourceTreeChangeHandler } from './treeProvider';
export class AzureResourceDatabaseTreeNode extends AzureResourceTreeNodeBase {
public constructor(
public readonly database: AzureResourceDatabase,
treeChangeHandler: IAzureResourceTreeChangeHandler,
parent: TreeNode
) {
super(treeChangeHandler, parent);
this._label = `${this.database.name} (${this.database.serverName})`;
}
public async getChildren(): Promise<TreeNode[]> {
return [];
}
public getTreeItem(): TreeItem | Promise<TreeItem> {
let item = new TreeItem(this._label, TreeItemCollapsibleState.None);
item.contextValue = AzureResourceItemType.database;
item.iconPath = {
dark: this.servicePool.contextService.getAbsolutePath('resources/dark/sql_database_inverse.svg'),
light: this.servicePool.contextService.getAbsolutePath('resources/light/sql_database.svg')
};
return item;
}
public getNodeInfo(): NodeInfo {
return {
label: this._label,
isLeaf: true,
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath(),
nodeStatus: undefined,
nodeType: AzureResourceItemType.database,
nodeSubType: undefined,
iconType: AzureResourceItemType.database
};
}
public get nodePathValue(): string {
return `database_${this.database.name}`;
}
private _label: string = undefined;
}

View File

@@ -1,60 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TreeItem, TreeItemCollapsibleState } from 'vscode';
import { NodeInfo } from 'sqlops';
import { TreeNode } from '../../treeNodes';
import { AzureResourceItemType } from '../constants';
export class AzureResourceMessageTreeNode extends TreeNode {
public constructor(
public readonly message: string,
parent: TreeNode
) {
super();
this.parent = parent;
this._id = `message_${AzureResourceMessageTreeNode._messageNum++}`;
}
public static create(message: string, parent: TreeNode): AzureResourceMessageTreeNode {
return new AzureResourceMessageTreeNode(message, parent);
}
public getChildren(): TreeNode[] | Promise<TreeNode[]> {
return [];
}
public getTreeItem(): TreeItem | Promise<TreeItem> {
let item = new TreeItem(this.message, TreeItemCollapsibleState.None);
item.contextValue = AzureResourceItemType.message;
return item;
}
public getNodeInfo(): NodeInfo {
return {
label: this.message,
isLeaf: true,
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath(),
nodeStatus: undefined,
nodeType: AzureResourceItemType.message,
nodeSubType: undefined,
iconType: AzureResourceItemType.message
};
}
public get nodePathValue(): string {
return this._id;
}
private _id: string;
private static _messageNum: number = 0;
}

View File

@@ -1,65 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* 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 'sqlops';
import { TreeNode } from '../../treeNodes';
import { AzureResourceTreeNodeBase, AzureResourceContainerTreeNodeBase } from './baseTreeNodes';
import { AzureResourceItemType } from '../constants';
import { AzureResourceDatabaseContainerTreeNode } from './databaseContainerTreeNode';
import { AzureResourceDatabaseServerContainerTreeNode } from './databaseServerContainerTreeNode';
import { AzureResourceSubscription } from '../models';
import { IAzureResourceTreeChangeHandler } from './treeChangeHandler';
export class AzureResourceSubscriptionTreeNode extends AzureResourceTreeNodeBase {
public constructor(
public readonly subscription: AzureResourceSubscription,
account: Account,
treeChangeHandler: IAzureResourceTreeChangeHandler,
parent: TreeNode
) {
super(treeChangeHandler, parent);
this._children.push(new AzureResourceDatabaseContainerTreeNode(subscription, account, treeChangeHandler, this));
this._children.push(new AzureResourceDatabaseServerContainerTreeNode(subscription, account, treeChangeHandler, this));
}
public async getChildren(): Promise<TreeNode[]> {
return this._children;
}
public getTreeItem(): TreeItem | Promise<TreeItem> {
let item = new TreeItem(this.subscription.name, TreeItemCollapsibleState.Collapsed);
item.contextValue = AzureResourceItemType.subscription;
item.iconPath = {
dark: this.servicePool.contextService.getAbsolutePath('resources/dark/subscription_inverse.svg'),
light: this.servicePool.contextService.getAbsolutePath('resources/light/subscription.svg')
};
return item;
}
public getNodeInfo(): NodeInfo {
return {
label: this.subscription.name,
isLeaf: false,
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath(),
nodeStatus: undefined,
nodeType: AzureResourceItemType.subscription,
nodeSubType: undefined,
iconType: AzureResourceItemType.subscription
};
}
public get nodePathValue(): string {
return `subscription_${this.subscription.id}`;
}
private _children: AzureResourceContainerTreeNodeBase[] = [];
}

View File

@@ -1,12 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TreeNode } from '../../treeNodes';
export interface IAzureResourceTreeChangeHandler {
notifyNodeChanged(node: TreeNode): void;
}

View File

@@ -1,101 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TreeDataProvider, EventEmitter, Event, TreeItem } from 'vscode';
import { DidChangeAccountsParams } from 'sqlops';
import { TreeNode } from '../../treeNodes';
import { setInterval, clearInterval } from 'timers';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import { AzureResourceServicePool } from '../servicePool';
import { AzureResourceAccountTreeNode } from './accountTreeNode';
import { AzureResourceAccountNotSignedInTreeNode } from './accountNotSignedInTreeNode';
import { AzureResourceMessageTreeNode } from './messageTreeNode';
import { AzureResourceContainerTreeNodeBase, AzureResourceTreeNodeBase } from './baseTreeNodes';
import { AzureResourceErrorMessageUtil } from '../utils';
export interface IAzureResourceTreeChangeHandler {
notifyNodeChanged(node: TreeNode): void;
}
export class AzureResourceTreeProvider implements TreeDataProvider<TreeNode>, IAzureResourceTreeChangeHandler {
public constructor() {
AzureResourceServicePool.getInstance().accountService.onDidChangeAccounts((e: DidChangeAccountsParams) => { this._onDidChangeTreeData.fire(undefined); });
}
public async getChildren(element?: TreeNode): Promise<TreeNode[]> {
if (element) {
return element.getChildren(true);
}
if (!this.isSystemInitialized) {
this._loadingTimer = setInterval(async () => {
try {
// Call sqlops.accounts.getAllAccounts() to determine whether the system has been initialized.
await AzureResourceServicePool.getInstance().accountService.getAccounts();
// System has been initialized
this.isSystemInitialized = true;
if (this._loadingTimer) {
clearInterval(this._loadingTimer);
}
this._onDidChangeTreeData.fire(undefined);
} catch (error) {
// System not initialized yet
this.isSystemInitialized = false;
}
}, AzureResourceTreeProvider.LoadingTimerInterval);
return [AzureResourceMessageTreeNode.create(AzureResourceTreeProvider.Loading, undefined)];
}
try {
const accounts = await AzureResourceServicePool.getInstance().accountService.getAccounts();
if (accounts && accounts.length > 0) {
return accounts.map((account) => new AzureResourceAccountTreeNode(account, this));
} else {
return [new AzureResourceAccountNotSignedInTreeNode()];
}
} catch (error) {
return [AzureResourceMessageTreeNode.create(AzureResourceErrorMessageUtil.getErrorMessage(error), undefined)];
}
}
public get onDidChangeTreeData(): Event<TreeNode> {
return this._onDidChangeTreeData.event;
}
public notifyNodeChanged(node: TreeNode): void {
this._onDidChangeTreeData.fire(node);
}
public async refresh(node: TreeNode, isClearingCache: boolean): Promise<void> {
if (isClearingCache) {
if ((node instanceof AzureResourceContainerTreeNodeBase)) {
node.clearCache();
}
}
this._onDidChangeTreeData.fire(node);
}
public getTreeItem(element: TreeNode): TreeItem | Thenable<TreeItem> {
return element.getTreeItem();
}
public isSystemInitialized: boolean = false;
private _loadingTimer: NodeJS.Timer = undefined;
private _onDidChangeTreeData = new EventEmitter<TreeNode>();
private static readonly Loading = localize('azureResource.tree.treeProvider.loading', 'Loading ...');
private static readonly LoadingTimerInterval = 5000;
}

View File

@@ -1,44 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
export function getErrorMessage(error: Error | string): string {
return (error instanceof Error) ? error.message : error;
}
export class AzureResourceErrorMessageUtil {
public static getErrorMessage(error: Error | string): string {
return localize('azureResource.error', 'Error: {0}', getErrorMessage(error));
}
}
export function generateGuid(): string {
let hexValues: string[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
// c.f. rfc4122 (UUID version 4 = xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx)
let oct: string = '';
let tmp: number;
/* tslint:disable:no-bitwise */
for (let a: number = 0; a < 4; a++) {
tmp = (4294967296 * Math.random()) | 0;
oct += hexValues[tmp & 0xF] +
hexValues[tmp >> 4 & 0xF] +
hexValues[tmp >> 8 & 0xF] +
hexValues[tmp >> 12 & 0xF] +
hexValues[tmp >> 16 & 0xF] +
hexValues[tmp >> 20 & 0xF] +
hexValues[tmp >> 24 & 0xF] +
hexValues[tmp >> 28 & 0xF];
}
// 'Set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to zero and one, respectively'
let clockSequenceHi: string = hexValues[8 + (Math.random() * 4) | 0];
return oct.substr(0, 8) + '-' + oct.substr(9, 4) + '-4' + oct.substr(13, 3) + '-' + clockSequenceHi + oct.substr(16, 3) + '-' + oct.substr(19, 12);
/* tslint:enable:no-bitwise */
}