mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Refactor to remove controller and static instance (#5735)
This commit is contained in:
@@ -16,6 +16,7 @@ export enum AzureResourceItemType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export enum AzureResourceServiceNames {
|
export enum AzureResourceServiceNames {
|
||||||
|
resourceService = 'AzureResourceService',
|
||||||
cacheService = 'AzureResourceCacheService',
|
cacheService = 'AzureResourceCacheService',
|
||||||
accountService = 'AzureResourceAccountService',
|
accountService = 'AzureResourceAccountService',
|
||||||
subscriptionService = 'AzureResourceSubscriptionService',
|
subscriptionService = 'AzureResourceSubscriptionService',
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ import { azureResource } from './azure-resource';
|
|||||||
import { IAzureResourceNodeWithProviderId } from './interfaces';
|
import { IAzureResourceNodeWithProviderId } from './interfaces';
|
||||||
|
|
||||||
export class AzureResourceService {
|
export class AzureResourceService {
|
||||||
private constructor() {
|
private _areResourceProvidersLoaded: boolean = false;
|
||||||
}
|
private _resourceProviders: { [resourceProviderId: string]: azureResource.IAzureResourceProvider } = {};
|
||||||
|
private _treeDataProviders: { [resourceProviderId: string]: azureResource.IAzureResourceTreeDataProvider } = {};
|
||||||
|
|
||||||
public static getInstance(): AzureResourceService {
|
public constructor() {
|
||||||
return AzureResourceService._instance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async listResourceProviderIds(): Promise<string[]> {
|
public async listResourceProviderIds(): Promise<string[]> {
|
||||||
@@ -121,9 +121,4 @@ export class AzureResourceService {
|
|||||||
this._treeDataProviders[resourceProvider.providerId] = resourceProvider.getTreeDataProvider();
|
this._treeDataProviders[resourceProvider.providerId] = resourceProvider.getTreeDataProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
private _areResourceProvidersLoaded: boolean = false;
|
|
||||||
private _resourceProviders: { [resourceProviderId: string]: azureResource.IAzureResourceProvider } = {};
|
|
||||||
private _treeDataProviders: { [resourceProviderId: string]: azureResource.IAzureResourceTreeDataProvider } = {};
|
|
||||||
|
|
||||||
private static readonly _instance = new AzureResourceService();
|
|
||||||
}
|
}
|
||||||
@@ -15,14 +15,19 @@ import { AzureResourceService } from './resourceService';
|
|||||||
import { IAzureResourceNodeWithProviderId } from './interfaces';
|
import { IAzureResourceNodeWithProviderId } from './interfaces';
|
||||||
import { AzureResourceMessageTreeNode } from './messageTreeNode';
|
import { AzureResourceMessageTreeNode } from './messageTreeNode';
|
||||||
import { AzureResourceErrorMessageUtil } from './utils';
|
import { AzureResourceErrorMessageUtil } from './utils';
|
||||||
|
import { AppContext } from '../appContext';
|
||||||
|
import { AzureResourceServiceNames } from './constants';
|
||||||
|
|
||||||
export class AzureResourceResourceTreeNode extends TreeNode {
|
export class AzureResourceResourceTreeNode extends TreeNode {
|
||||||
|
private _resourceService: AzureResourceService;
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
public readonly resourceNodeWithProviderId: IAzureResourceNodeWithProviderId,
|
public readonly resourceNodeWithProviderId: IAzureResourceNodeWithProviderId,
|
||||||
parent: TreeNode
|
parent: TreeNode,
|
||||||
|
private appContext: AppContext
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
this._resourceService = appContext.getService<AzureResourceService>(AzureResourceServiceNames.resourceService);
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,12 +41,12 @@ export class AzureResourceResourceTreeNode extends TreeNode {
|
|||||||
const children = await this._resourceService.getChildren(this.resourceNodeWithProviderId.resourceProviderId, this.resourceNodeWithProviderId.resourceNode);
|
const children = await this._resourceService.getChildren(this.resourceNodeWithProviderId.resourceProviderId, this.resourceNodeWithProviderId.resourceNode);
|
||||||
|
|
||||||
if (children.length === 0) {
|
if (children.length === 0) {
|
||||||
return [AzureResourceMessageTreeNode.create(AzureResourceResourceTreeNode.noResourcesLabel, this)];
|
return [AzureResourceMessageTreeNode.create(localize('azure.resource.resourceTreeNode.noResourcesLabel', 'No Resources found'), this)];
|
||||||
} else {
|
} else {
|
||||||
return children.map((child) => {
|
return children.map((child) => {
|
||||||
// To make tree node's id unique, otherwise, treeModel.js would complain 'item already registered'
|
// To make tree node's id unique, otherwise, treeModel.js would complain 'item already registered'
|
||||||
child.resourceNode.treeItem.id = `${this.resourceNodeWithProviderId.resourceNode.treeItem.id}.${child.resourceNode.treeItem.id}`;
|
child.resourceNode.treeItem.id = `${this.resourceNodeWithProviderId.resourceNode.treeItem.id}.${child.resourceNode.treeItem.id}`;
|
||||||
return new AzureResourceResourceTreeNode(child, this);
|
return new AzureResourceResourceTreeNode(child, this, this.appContext);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -73,7 +78,4 @@ export class AzureResourceResourceTreeNode extends TreeNode {
|
|||||||
return this.resourceNodeWithProviderId.resourceNode.treeItem.id;
|
return this.resourceNodeWithProviderId.resourceNode.treeItem.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _resourceService = AzureResourceService.getInstance();
|
|
||||||
|
|
||||||
private static readonly noResourcesLabel = localize('azure.resource.resourceTreeNode.noResourcesLabel', 'No Resources found.');
|
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,7 @@ import { azureResource } from '../azure-resource';
|
|||||||
import { TreeNode } from '../treeNode';
|
import { TreeNode } from '../treeNode';
|
||||||
import { IAzureResourceNodeWithProviderId } from '../interfaces';
|
import { IAzureResourceNodeWithProviderId } from '../interfaces';
|
||||||
import { AzureResourceContainerTreeNodeBase } from './baseTreeNodes';
|
import { AzureResourceContainerTreeNodeBase } from './baseTreeNodes';
|
||||||
import { AzureResourceItemType } from '../constants';
|
import { AzureResourceItemType, AzureResourceServiceNames } from '../constants';
|
||||||
import { IAzureResourceTreeChangeHandler } from './treeChangeHandler';
|
import { IAzureResourceTreeChangeHandler } from './treeChangeHandler';
|
||||||
import { AzureResourceMessageTreeNode } from '../messageTreeNode';
|
import { AzureResourceMessageTreeNode } from '../messageTreeNode';
|
||||||
import { AzureResourceErrorMessageUtil } from '../utils';
|
import { AzureResourceErrorMessageUtil } from '../utils';
|
||||||
@@ -39,7 +39,7 @@ export class AzureResourceSubscriptionTreeNode extends AzureResourceContainerTre
|
|||||||
|
|
||||||
public async getChildren(): Promise<TreeNode[]> {
|
public async getChildren(): Promise<TreeNode[]> {
|
||||||
try {
|
try {
|
||||||
const resourceService = AzureResourceService.getInstance();
|
const resourceService = this.appContext.getService<AzureResourceService>(AzureResourceServiceNames.resourceService);
|
||||||
|
|
||||||
const children: IAzureResourceNodeWithProviderId[] = [];
|
const children: IAzureResourceNodeWithProviderId[] = [];
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ export class AzureResourceSubscriptionTreeNode extends AzureResourceContainerTre
|
|||||||
return children.map((child) => {
|
return children.map((child) => {
|
||||||
// To make tree node's id unique, otherwise, treeModel.js would complain 'item already registered'
|
// To make tree node's id unique, otherwise, treeModel.js would complain 'item already registered'
|
||||||
child.resourceNode.treeItem.id = `${this._id}.${child.resourceNode.treeItem.id}`;
|
child.resourceNode.treeItem.id = `${this._id}.${child.resourceNode.treeItem.id}`;
|
||||||
return new AzureResourceResourceTreeNode(child, this);
|
return new AzureResourceResourceTreeNode(child, this, this.appContext);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -22,9 +22,7 @@ import { IAzureResourceAccountService } from '../../azureResource/interfaces';
|
|||||||
import { AzureResourceServiceNames } from '../constants';
|
import { AzureResourceServiceNames } from '../constants';
|
||||||
|
|
||||||
export class AzureResourceTreeProvider implements TreeDataProvider<TreeNode>, IAzureResourceTreeChangeHandler {
|
export class AzureResourceTreeProvider implements TreeDataProvider<TreeNode>, IAzureResourceTreeChangeHandler {
|
||||||
public constructor(
|
public constructor(public readonly appContext: AppContext) {
|
||||||
public readonly appContext: AppContext
|
|
||||||
) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getChildren(element?: TreeNode): Promise<TreeNode[]> {
|
public async getChildren(element?: TreeNode): Promise<TreeNode[]> {
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------------------------
|
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
|
||||||
*--------------------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
import ControllerBase from './controllerBase';
|
|
||||||
import { DidChangeAccountsParams, Account } from 'azdata';
|
|
||||||
|
|
||||||
import {
|
|
||||||
IAzureResourceCacheService,
|
|
||||||
IAzureResourceAccountService,
|
|
||||||
IAzureResourceSubscriptionService,
|
|
||||||
IAzureResourceSubscriptionFilterService,
|
|
||||||
IAzureResourceTenantService
|
|
||||||
} from '../azureResource/interfaces';
|
|
||||||
import { AzureResourceServiceNames } from '../azureResource/constants';
|
|
||||||
import { AzureResourceTreeProvider } from '../azureResource/tree/treeProvider';
|
|
||||||
import { registerAzureResourceCommands } from '../azureResource/commands';
|
|
||||||
import { AzureResourceAccountService } from '../azureResource/services/accountService';
|
|
||||||
import { AzureResourceSubscriptionService } from '../azureResource/services/subscriptionService';
|
|
||||||
import { AzureResourceSubscriptionFilterService } from '../azureResource/services/subscriptionFilterService';
|
|
||||||
import { AzureResourceCacheService } from '../azureResource/services/cacheService';
|
|
||||||
import { AzureResourceTenantService } from '../azureResource/services/tenantService';
|
|
||||||
|
|
||||||
import { registerAzureResourceDatabaseServerCommands } from '../azureResource/providers/databaseServer/commands';
|
|
||||||
import { registerAzureResourceDatabaseCommands } from '../azureResource/providers/database/commands';
|
|
||||||
import { equals } from '../azureResource/utils';
|
|
||||||
|
|
||||||
export default class AzureResourceController extends ControllerBase {
|
|
||||||
public activate(): Promise<boolean> {
|
|
||||||
this.appContext.registerService<IAzureResourceCacheService>(AzureResourceServiceNames.cacheService, new AzureResourceCacheService(this.extensionContext));
|
|
||||||
this.appContext.registerService<IAzureResourceAccountService>(AzureResourceServiceNames.accountService, new AzureResourceAccountService(this.apiWrapper));
|
|
||||||
this.appContext.registerService<IAzureResourceSubscriptionService>(AzureResourceServiceNames.subscriptionService, new AzureResourceSubscriptionService());
|
|
||||||
this.appContext.registerService<IAzureResourceSubscriptionFilterService>(AzureResourceServiceNames.subscriptionFilterService, new AzureResourceSubscriptionFilterService(new AzureResourceCacheService(this.extensionContext)));
|
|
||||||
this.appContext.registerService<IAzureResourceTenantService>(AzureResourceServiceNames.tenantService, new AzureResourceTenantService());
|
|
||||||
|
|
||||||
const azureResourceTree = new AzureResourceTreeProvider(this.appContext);
|
|
||||||
this.extensionContext.subscriptions.push(this.apiWrapper.registerTreeDataProvider('azureResourceExplorer', azureResourceTree));
|
|
||||||
|
|
||||||
let previousAccounts: Array<Account> = undefined;
|
|
||||||
this.appContext.getService<IAzureResourceAccountService>(AzureResourceServiceNames.accountService).onDidChangeAccounts((e: DidChangeAccountsParams) => {
|
|
||||||
// the onDidChangeAccounts event will trigger in many cases where the accounts didn't actually change
|
|
||||||
// the notifyNodeChanged event triggers a refresh which triggers a getChildren which can trigger this callback
|
|
||||||
// this below check short-circuits the infinite callback loop
|
|
||||||
if (!equals(e.accounts, previousAccounts)) {
|
|
||||||
azureResourceTree.notifyNodeChanged(undefined);
|
|
||||||
}
|
|
||||||
previousAccounts = e.accounts;
|
|
||||||
});
|
|
||||||
|
|
||||||
registerAzureResourceCommands(this.appContext, azureResourceTree);
|
|
||||||
|
|
||||||
registerAzureResourceDatabaseServerCommands(this.appContext);
|
|
||||||
|
|
||||||
registerAzureResourceDatabaseCommands(this.appContext);
|
|
||||||
|
|
||||||
return Promise.resolve(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public deactivate(): void {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,34 +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 vscode from 'vscode';
|
|
||||||
|
|
||||||
import { AppContext } from '../appContext';
|
|
||||||
import { ApiWrapper } from '../apiWrapper';
|
|
||||||
|
|
||||||
export default abstract class ControllerBase implements vscode.Disposable {
|
|
||||||
|
|
||||||
public constructor(protected appContext: AppContext) {
|
|
||||||
}
|
|
||||||
|
|
||||||
protected get apiWrapper(): ApiWrapper {
|
|
||||||
return this.appContext.apiWrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get extensionContext(): vscode.ExtensionContext {
|
|
||||||
return this.appContext && this.appContext.extensionContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract activate(): Promise<boolean>;
|
|
||||||
|
|
||||||
abstract deactivate(): void;
|
|
||||||
|
|
||||||
public dispose(): void {
|
|
||||||
this.deactivate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -8,10 +8,9 @@ import * 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 * as constants from './constants';
|
||||||
|
import * as azdata from 'azdata';
|
||||||
|
|
||||||
import AzureResourceController from './controllers/azureResourceController';
|
|
||||||
import { AppContext } from './appContext';
|
import { AppContext } from './appContext';
|
||||||
import ControllerBase from './controllers/controllerBase';
|
|
||||||
import { ApiWrapper } from './apiWrapper';
|
import { ApiWrapper } from './apiWrapper';
|
||||||
import { AzureAccountProviderService } from './account-provider/azureAccountProviderService';
|
import { AzureAccountProviderService } from './account-provider/azureAccountProviderService';
|
||||||
|
|
||||||
@@ -19,9 +18,21 @@ import { AzureResourceDatabaseServerProvider } from './azureResource/providers/d
|
|||||||
import { AzureResourceDatabaseServerService } from './azureResource/providers/databaseServer/databaseServerService';
|
import { AzureResourceDatabaseServerService } from './azureResource/providers/databaseServer/databaseServerService';
|
||||||
import { AzureResourceDatabaseProvider } from './azureResource/providers/database/databaseProvider';
|
import { AzureResourceDatabaseProvider } from './azureResource/providers/database/databaseProvider';
|
||||||
import { AzureResourceDatabaseService } from './azureResource/providers/database/databaseService';
|
import { AzureResourceDatabaseService } from './azureResource/providers/database/databaseService';
|
||||||
|
import { AzureResourceService } from './azureResource/resourceService';
|
||||||
|
import { IAzureResourceCacheService, IAzureResourceAccountService, IAzureResourceSubscriptionService, IAzureResourceSubscriptionFilterService, IAzureResourceTenantService } from './azureResource/interfaces';
|
||||||
|
import { AzureResourceServiceNames } from './azureResource/constants';
|
||||||
|
import { AzureResourceAccountService } from './azureResource/services/accountService';
|
||||||
|
import { AzureResourceSubscriptionService } from './azureResource/services/subscriptionService';
|
||||||
|
import { AzureResourceSubscriptionFilterService } from './azureResource/services/subscriptionFilterService';
|
||||||
|
import { AzureResourceCacheService } from './azureResource/services/cacheService';
|
||||||
|
import { AzureResourceTenantService } from './azureResource/services/tenantService';
|
||||||
|
import { registerAzureResourceCommands } from './azureResource/commands';
|
||||||
|
import { registerAzureResourceDatabaseServerCommands } from './azureResource/providers/databaseServer/commands';
|
||||||
|
import { registerAzureResourceDatabaseCommands } from './azureResource/providers/database/commands';
|
||||||
|
import { AzureResourceTreeProvider } from './azureResource/tree/treeProvider';
|
||||||
|
import { equals } from './azureResource/utils';
|
||||||
|
|
||||||
let controllers: ControllerBase[] = [];
|
let extensionContext: vscode.ExtensionContext;
|
||||||
|
|
||||||
|
|
||||||
// The function is a duplicate of \src\paths.js. IT would be better to import path.js but it doesn't
|
// The function is a duplicate of \src\paths.js. IT would be better to import path.js but it doesn't
|
||||||
// work for now because the extension is running in different process.
|
// work for now because the extension is running in different process.
|
||||||
@@ -39,36 +50,30 @@ export function getDefaultLogLocation() {
|
|||||||
return path.join(getAppDataPath(), 'azuredatastudio');
|
return path.join(getAppDataPath(), 'azuredatastudio');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function pushDisposable(disposable: vscode.Disposable): void {
|
||||||
|
extensionContext.subscriptions.push(disposable);
|
||||||
|
}
|
||||||
|
|
||||||
// this method is called when your extension is activated
|
// this method is called when your extension is activated
|
||||||
// your extension is activated the very first time the command is executed
|
// your extension is activated the very first time the command is executed
|
||||||
export function activate(extensionContext: vscode.ExtensionContext) {
|
export function activate(context: vscode.ExtensionContext) {
|
||||||
|
extensionContext = context;
|
||||||
const apiWrapper = new ApiWrapper();
|
const apiWrapper = new ApiWrapper();
|
||||||
let appContext = new AppContext(extensionContext, apiWrapper);
|
let appContext = new AppContext(extensionContext, apiWrapper);
|
||||||
let activations: Thenable<boolean>[] = [];
|
|
||||||
|
|
||||||
// Create the folder for storing the token caches
|
let storagePath = findOrMakeStoragePath();
|
||||||
let storagePath = path.join(getDefaultLogLocation(), constants.extensionName);
|
if (!storagePath) {
|
||||||
try {
|
|
||||||
if (!fs.existsSync(storagePath)) {
|
|
||||||
fs.mkdirSync(storagePath);
|
|
||||||
console.log('Initialized Azure account extension storage.');
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error(`Initialization of Azure account extension storage failed: ${e}`);
|
|
||||||
console.error('Azure accounts will not be available');
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the provider service and activate
|
// Create the provider service and activate
|
||||||
const accountProviderService = new AzureAccountProviderService(extensionContext, storagePath);
|
initAzureAccountProvider(extensionContext, storagePath);
|
||||||
extensionContext.subscriptions.push(accountProviderService);
|
|
||||||
accountProviderService.activate();
|
|
||||||
|
|
||||||
const azureResourceController = new AzureResourceController(appContext);
|
registerAzureServices(appContext);
|
||||||
controllers.push(azureResourceController);
|
const azureResourceTree = new AzureResourceTreeProvider(appContext);
|
||||||
extensionContext.subscriptions.push(azureResourceController);
|
pushDisposable(apiWrapper.registerTreeDataProvider('azureResourceExplorer', azureResourceTree));
|
||||||
activations.push(azureResourceController.activate());
|
registerAccountService(appContext, azureResourceTree);
|
||||||
|
registerCommands(appContext, azureResourceTree);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
provideResources() {
|
provideResources() {
|
||||||
@@ -80,9 +85,60 @@ export function activate(extensionContext: vscode.ExtensionContext) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// this method is called when your extension is deactivated
|
// Create the folder for storing the token caches
|
||||||
export function deactivate() {
|
function findOrMakeStoragePath() {
|
||||||
for (let controller of controllers) {
|
let storagePath = path.join(getDefaultLogLocation(), constants.extensionName);
|
||||||
controller.deactivate();
|
try {
|
||||||
|
if (!fs.existsSync(storagePath)) {
|
||||||
|
fs.mkdirSync(storagePath);
|
||||||
|
console.log('Initialized Azure account extension storage.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.error(`Initialization of Azure account extension storage failed: ${e}`);
|
||||||
|
console.error('Azure accounts will not be available');
|
||||||
|
}
|
||||||
|
return storagePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function initAzureAccountProvider(extensionContext: vscode.ExtensionContext, storagePath: string): Promise<void> {
|
||||||
|
try {
|
||||||
|
const accountProviderService = new AzureAccountProviderService(extensionContext, storagePath);
|
||||||
|
extensionContext.subscriptions.push(accountProviderService);
|
||||||
|
await accountProviderService.activate();
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Unexpected error starting account provider: ' + err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerAzureServices(appContext: AppContext): void {
|
||||||
|
appContext.registerService<AzureResourceService>(AzureResourceServiceNames.resourceService, new AzureResourceService());
|
||||||
|
appContext.registerService<IAzureResourceCacheService>(AzureResourceServiceNames.cacheService, new AzureResourceCacheService(extensionContext));
|
||||||
|
appContext.registerService<IAzureResourceSubscriptionService>(AzureResourceServiceNames.subscriptionService, new AzureResourceSubscriptionService());
|
||||||
|
appContext.registerService<IAzureResourceSubscriptionFilterService>(AzureResourceServiceNames.subscriptionFilterService, new AzureResourceSubscriptionFilterService(new AzureResourceCacheService(extensionContext)));
|
||||||
|
appContext.registerService<IAzureResourceTenantService>(AzureResourceServiceNames.tenantService, new AzureResourceTenantService());
|
||||||
|
}
|
||||||
|
function registerAccountService(appContext: AppContext, azureResourceTree: AzureResourceTreeProvider): void {
|
||||||
|
let accountService = new AzureResourceAccountService(appContext.apiWrapper);
|
||||||
|
appContext.registerService<IAzureResourceAccountService>(AzureResourceServiceNames.accountService, accountService);
|
||||||
|
let previousAccounts: Array<azdata.Account> = undefined;
|
||||||
|
accountService.onDidChangeAccounts((e: azdata.DidChangeAccountsParams) => {
|
||||||
|
// the onDidChangeAccounts event will trigger in many cases where the accounts didn't actually change
|
||||||
|
// the notifyNodeChanged event triggers a refresh which triggers a getChildren which can trigger this callback
|
||||||
|
// this below check short-circuits the infinite callback loop
|
||||||
|
if (!equals(e.accounts, previousAccounts)) {
|
||||||
|
azureResourceTree.notifyNodeChanged(undefined);
|
||||||
|
}
|
||||||
|
previousAccounts = e.accounts;
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerCommands(appContext: AppContext, azureResourceTree: AzureResourceTreeProvider): void {
|
||||||
|
registerAzureResourceCommands(appContext, azureResourceTree);
|
||||||
|
|
||||||
|
registerAzureResourceDatabaseServerCommands(appContext);
|
||||||
|
|
||||||
|
registerAzureResourceDatabaseCommands(appContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ let mockResourceProvider1: TypeMoq.IMock<azureResource.IAzureResourceProvider>;
|
|||||||
let mockResourceTreeDataProvider2: TypeMoq.IMock<azureResource.IAzureResourceTreeDataProvider>;
|
let mockResourceTreeDataProvider2: TypeMoq.IMock<azureResource.IAzureResourceTreeDataProvider>;
|
||||||
let mockResourceProvider2: TypeMoq.IMock<azureResource.IAzureResourceProvider>;
|
let mockResourceProvider2: TypeMoq.IMock<azureResource.IAzureResourceProvider>;
|
||||||
|
|
||||||
const resourceService: AzureResourceService = AzureResourceService.getInstance();
|
let resourceService: AzureResourceService;
|
||||||
|
|
||||||
describe('AzureResourceService.listResourceProviderIds', function(): void {
|
describe('AzureResourceService.listResourceProviderIds', function(): void {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -61,6 +61,7 @@ describe('AzureResourceService.listResourceProviderIds', function(): void {
|
|||||||
mockResourceProvider2.setup((o) => o.providerId).returns(() => 'mockResourceProvider2');
|
mockResourceProvider2.setup((o) => o.providerId).returns(() => 'mockResourceProvider2');
|
||||||
mockResourceProvider2.setup((o) => o.getTreeDataProvider()).returns(() => mockResourceTreeDataProvider2.object);
|
mockResourceProvider2.setup((o) => o.getTreeDataProvider()).returns(() => mockResourceTreeDataProvider2.object);
|
||||||
|
|
||||||
|
resourceService = new AzureResourceService();
|
||||||
resourceService.clearResourceProviders();
|
resourceService.clearResourceProviders();
|
||||||
resourceService.areResourceProvidersLoaded = true;
|
resourceService.areResourceProvidersLoaded = true;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -14,8 +14,9 @@ import 'mocha';
|
|||||||
import { azureResource } from '../../azureResource/azure-resource';
|
import { azureResource } from '../../azureResource/azure-resource';
|
||||||
import { AzureResourceService } from '../../azureResource/resourceService';
|
import { AzureResourceService } from '../../azureResource/resourceService';
|
||||||
import { AzureResourceResourceTreeNode } from '../../azureResource/resourceTreeNode';
|
import { AzureResourceResourceTreeNode } from '../../azureResource/resourceTreeNode';
|
||||||
|
import { AppContext } from '../../appContext';
|
||||||
const resourceService = AzureResourceService.getInstance();
|
import { ApiWrapper } from '../../apiWrapper';
|
||||||
|
import { AzureResourceServiceNames } from '../../azureResource/constants';
|
||||||
|
|
||||||
// Mock test data
|
// Mock test data
|
||||||
const mockAccount: azdata.Account = {
|
const mockAccount: azdata.Account = {
|
||||||
@@ -85,6 +86,8 @@ const mockResourceNodes: azureResource.IAzureResourceNode[] = [mockResourceNode1
|
|||||||
|
|
||||||
let mockResourceTreeDataProvider: TypeMoq.IMock<azureResource.IAzureResourceTreeDataProvider>;
|
let mockResourceTreeDataProvider: TypeMoq.IMock<azureResource.IAzureResourceTreeDataProvider>;
|
||||||
let mockResourceProvider: TypeMoq.IMock<azureResource.IAzureResourceProvider>;
|
let mockResourceProvider: TypeMoq.IMock<azureResource.IAzureResourceProvider>;
|
||||||
|
let resourceService: AzureResourceService;
|
||||||
|
let appContext: AppContext;
|
||||||
|
|
||||||
describe('AzureResourceResourceTreeNode.info', function(): void {
|
describe('AzureResourceResourceTreeNode.info', function(): void {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -95,18 +98,20 @@ describe('AzureResourceResourceTreeNode.info', function(): void {
|
|||||||
mockResourceProvider = TypeMoq.Mock.ofType<azureResource.IAzureResourceProvider>();
|
mockResourceProvider = TypeMoq.Mock.ofType<azureResource.IAzureResourceProvider>();
|
||||||
mockResourceProvider.setup((o) => o.providerId).returns(() => mockResourceProviderId);
|
mockResourceProvider.setup((o) => o.providerId).returns(() => mockResourceProviderId);
|
||||||
mockResourceProvider.setup((o) => o.getTreeDataProvider()).returns(() => mockResourceTreeDataProvider.object);
|
mockResourceProvider.setup((o) => o.getTreeDataProvider()).returns(() => mockResourceTreeDataProvider.object);
|
||||||
|
resourceService = new AzureResourceService();
|
||||||
resourceService.clearResourceProviders();
|
resourceService.clearResourceProviders();
|
||||||
resourceService.registerResourceProvider(mockResourceProvider.object);
|
resourceService.registerResourceProvider(mockResourceProvider.object);
|
||||||
|
|
||||||
resourceService.areResourceProvidersLoaded = true;
|
resourceService.areResourceProvidersLoaded = true;
|
||||||
|
|
||||||
|
appContext = new AppContext(undefined, new ApiWrapper());
|
||||||
|
appContext.registerService(AzureResourceServiceNames.resourceService, resourceService);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should be correct when created.', async function(): Promise<void> {
|
it('Should be correct when created.', async function(): Promise<void> {
|
||||||
const resourceTreeNode = new AzureResourceResourceTreeNode({
|
const resourceTreeNode = new AzureResourceResourceTreeNode({
|
||||||
resourceProviderId: mockResourceProviderId,
|
resourceProviderId: mockResourceProviderId,
|
||||||
resourceNode: mockResourceRootNode
|
resourceNode: mockResourceRootNode
|
||||||
}, undefined);
|
}, undefined, appContext);
|
||||||
|
|
||||||
should(resourceTreeNode.nodePathValue).equal(mockResourceRootNode.treeItem.id);
|
should(resourceTreeNode.nodePathValue).equal(mockResourceRootNode.treeItem.id);
|
||||||
|
|
||||||
@@ -133,17 +138,21 @@ describe('AzureResourceResourceTreeNode.getChildren', function(): void {
|
|||||||
mockResourceProvider.setup((o) => o.providerId).returns(() => mockResourceProviderId);
|
mockResourceProvider.setup((o) => o.providerId).returns(() => mockResourceProviderId);
|
||||||
mockResourceProvider.setup((o) => o.getTreeDataProvider()).returns(() => mockResourceTreeDataProvider.object);
|
mockResourceProvider.setup((o) => o.getTreeDataProvider()).returns(() => mockResourceTreeDataProvider.object);
|
||||||
|
|
||||||
|
resourceService = new AzureResourceService();
|
||||||
resourceService.clearResourceProviders();
|
resourceService.clearResourceProviders();
|
||||||
resourceService.registerResourceProvider(mockResourceProvider.object);
|
resourceService.registerResourceProvider(mockResourceProvider.object);
|
||||||
|
|
||||||
resourceService.areResourceProvidersLoaded = true;
|
resourceService.areResourceProvidersLoaded = true;
|
||||||
|
|
||||||
|
appContext = new AppContext(undefined, new ApiWrapper());
|
||||||
|
appContext.registerService(AzureResourceServiceNames.resourceService, resourceService);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should return resource nodes when it is container node.', async function(): Promise<void> {
|
it('Should return resource nodes when it is container node.', async function(): Promise<void> {
|
||||||
const resourceTreeNode = new AzureResourceResourceTreeNode({
|
const resourceTreeNode = new AzureResourceResourceTreeNode({
|
||||||
resourceProviderId: mockResourceProviderId,
|
resourceProviderId: mockResourceProviderId,
|
||||||
resourceNode: mockResourceRootNode
|
resourceNode: mockResourceRootNode
|
||||||
}, undefined);
|
},
|
||||||
|
undefined, appContext);
|
||||||
|
|
||||||
const children = await resourceTreeNode.getChildren();
|
const children = await resourceTreeNode.getChildren();
|
||||||
|
|
||||||
@@ -173,7 +182,7 @@ describe('AzureResourceResourceTreeNode.getChildren', function(): void {
|
|||||||
const resourceTreeNode = new AzureResourceResourceTreeNode({
|
const resourceTreeNode = new AzureResourceResourceTreeNode({
|
||||||
resourceProviderId: mockResourceProviderId,
|
resourceProviderId: mockResourceProviderId,
|
||||||
resourceNode: mockResourceNode1
|
resourceNode: mockResourceNode1
|
||||||
}, undefined);
|
}, undefined, appContext);
|
||||||
|
|
||||||
const children = await resourceTreeNode.getChildren();
|
const children = await resourceTreeNode.getChildren();
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import { IAzureResourceCacheService } from '../../../azureResource/interfaces';
|
|||||||
import { generateGuid } from '../../../azureResource/utils';
|
import { generateGuid } from '../../../azureResource/utils';
|
||||||
|
|
||||||
// Mock services
|
// Mock services
|
||||||
let mockAppContext: AppContext;
|
let appContext: AppContext;
|
||||||
|
|
||||||
let mockExtensionContext: TypeMoq.IMock<vscode.ExtensionContext>;
|
let mockExtensionContext: TypeMoq.IMock<vscode.ExtensionContext>;
|
||||||
let mockApiWrapper: TypeMoq.IMock<ApiWrapper>;
|
let mockApiWrapper: TypeMoq.IMock<ApiWrapper>;
|
||||||
@@ -60,7 +60,7 @@ let mockResourceProvider1: TypeMoq.IMock<azureResource.IAzureResourceProvider>;
|
|||||||
let mockResourceTreeDataProvider2: TypeMoq.IMock<azureResource.IAzureResourceTreeDataProvider>;
|
let mockResourceTreeDataProvider2: TypeMoq.IMock<azureResource.IAzureResourceTreeDataProvider>;
|
||||||
let mockResourceProvider2: TypeMoq.IMock<azureResource.IAzureResourceProvider>;
|
let mockResourceProvider2: TypeMoq.IMock<azureResource.IAzureResourceProvider>;
|
||||||
|
|
||||||
const resourceService: AzureResourceService = AzureResourceService.getInstance();
|
const resourceService: AzureResourceService = new AzureResourceService();
|
||||||
|
|
||||||
describe('AzureResourceSubscriptionTreeNode.info', function(): void {
|
describe('AzureResourceSubscriptionTreeNode.info', function(): void {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -68,10 +68,6 @@ describe('AzureResourceSubscriptionTreeNode.info', function(): void {
|
|||||||
mockApiWrapper = TypeMoq.Mock.ofType<ApiWrapper>();
|
mockApiWrapper = TypeMoq.Mock.ofType<ApiWrapper>();
|
||||||
mockCacheService = TypeMoq.Mock.ofType<IAzureResourceCacheService>();
|
mockCacheService = TypeMoq.Mock.ofType<IAzureResourceCacheService>();
|
||||||
|
|
||||||
mockAppContext = new AppContext(mockExtensionContext.object, mockApiWrapper.object);
|
|
||||||
|
|
||||||
mockAppContext.registerService<IAzureResourceCacheService>(AzureResourceServiceNames.cacheService, mockCacheService.object);
|
|
||||||
|
|
||||||
mockCacheService.setup((o) => o.generateKey(TypeMoq.It.isAnyString())).returns(() => generateGuid());
|
mockCacheService.setup((o) => o.generateKey(TypeMoq.It.isAnyString())).returns(() => generateGuid());
|
||||||
|
|
||||||
mockTreeChangeHandler = TypeMoq.Mock.ofType<IAzureResourceTreeChangeHandler>();
|
mockTreeChangeHandler = TypeMoq.Mock.ofType<IAzureResourceTreeChangeHandler>();
|
||||||
@@ -93,12 +89,16 @@ describe('AzureResourceSubscriptionTreeNode.info', function(): void {
|
|||||||
resourceService.clearResourceProviders();
|
resourceService.clearResourceProviders();
|
||||||
resourceService.registerResourceProvider(mockResourceProvider1.object);
|
resourceService.registerResourceProvider(mockResourceProvider1.object);
|
||||||
resourceService.registerResourceProvider(mockResourceProvider2.object);
|
resourceService.registerResourceProvider(mockResourceProvider2.object);
|
||||||
|
|
||||||
resourceService.areResourceProvidersLoaded = true;
|
resourceService.areResourceProvidersLoaded = true;
|
||||||
|
|
||||||
|
appContext = new AppContext(mockExtensionContext.object, mockApiWrapper.object);
|
||||||
|
appContext.registerService<IAzureResourceCacheService>(AzureResourceServiceNames.cacheService, mockCacheService.object);
|
||||||
|
appContext.registerService(AzureResourceServiceNames.resourceService, resourceService);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should be correct when created.', async function(): Promise<void> {
|
it('Should be correct when created.', async function(): Promise<void> {
|
||||||
const subscriptionTreeNode = new AzureResourceSubscriptionTreeNode(mockAccount, mockSubscription, mockTenantId, mockAppContext, mockTreeChangeHandler.object, undefined);
|
const subscriptionTreeNode = new AzureResourceSubscriptionTreeNode(mockAccount, mockSubscription, mockTenantId, appContext, mockTreeChangeHandler.object, undefined);
|
||||||
|
|
||||||
should(subscriptionTreeNode.nodePathValue).equal(`account_${mockAccount.key.accountId}.subscription_${mockSubscription.id}.tenant_${mockTenantId}`);
|
should(subscriptionTreeNode.nodePathValue).equal(`account_${mockAccount.key.accountId}.subscription_${mockSubscription.id}.tenant_${mockTenantId}`);
|
||||||
|
|
||||||
@@ -121,9 +121,6 @@ describe('AzureResourceSubscriptionTreeNode.getChildren', function(): void {
|
|||||||
mockApiWrapper = TypeMoq.Mock.ofType<ApiWrapper>();
|
mockApiWrapper = TypeMoq.Mock.ofType<ApiWrapper>();
|
||||||
mockCacheService = TypeMoq.Mock.ofType<IAzureResourceCacheService>();
|
mockCacheService = TypeMoq.Mock.ofType<IAzureResourceCacheService>();
|
||||||
|
|
||||||
mockAppContext = new AppContext(mockExtensionContext.object, mockApiWrapper.object);
|
|
||||||
mockAppContext.registerService<IAzureResourceCacheService>(AzureResourceServiceNames.cacheService, mockCacheService.object);
|
|
||||||
|
|
||||||
mockCacheService.setup((o) => o.generateKey(TypeMoq.It.isAnyString())).returns(() => generateGuid());
|
mockCacheService.setup((o) => o.generateKey(TypeMoq.It.isAnyString())).returns(() => generateGuid());
|
||||||
|
|
||||||
mockTreeChangeHandler = TypeMoq.Mock.ofType<IAzureResourceTreeChangeHandler>();
|
mockTreeChangeHandler = TypeMoq.Mock.ofType<IAzureResourceTreeChangeHandler>();
|
||||||
@@ -145,12 +142,16 @@ describe('AzureResourceSubscriptionTreeNode.getChildren', function(): void {
|
|||||||
resourceService.clearResourceProviders();
|
resourceService.clearResourceProviders();
|
||||||
resourceService.registerResourceProvider(mockResourceProvider1.object);
|
resourceService.registerResourceProvider(mockResourceProvider1.object);
|
||||||
resourceService.registerResourceProvider(mockResourceProvider2.object);
|
resourceService.registerResourceProvider(mockResourceProvider2.object);
|
||||||
|
|
||||||
resourceService.areResourceProvidersLoaded = true;
|
resourceService.areResourceProvidersLoaded = true;
|
||||||
|
|
||||||
|
appContext = new AppContext(mockExtensionContext.object, mockApiWrapper.object);
|
||||||
|
appContext.registerService<IAzureResourceCacheService>(AzureResourceServiceNames.cacheService, mockCacheService.object);
|
||||||
|
appContext.registerService(AzureResourceServiceNames.resourceService, resourceService);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should return resource containers.', async function(): Promise<void> {
|
it('Should return resource containers.', async function(): Promise<void> {
|
||||||
const subscriptionTreeNode = new AzureResourceSubscriptionTreeNode(mockAccount, mockSubscription, mockTenantId, mockAppContext, mockTreeChangeHandler.object, undefined);
|
const subscriptionTreeNode = new AzureResourceSubscriptionTreeNode(mockAccount, mockSubscription, mockTenantId, appContext, mockTreeChangeHandler.object, undefined);
|
||||||
const children = await subscriptionTreeNode.getChildren();
|
const children = await subscriptionTreeNode.getChildren();
|
||||||
|
|
||||||
mockResourceTreeDataProvider1.verify((o) => o.getChildren(), TypeMoq.Times.once());
|
mockResourceTreeDataProvider1.verify((o) => o.getChildren(), TypeMoq.Times.once());
|
||||||
|
|||||||
Reference in New Issue
Block a user