Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delay loading of Azure Account extension #552

Merged
merged 2 commits into from
Oct 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion commands/azureCommands/create-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { quickPickLocation, quickPickResourceGroup, quickPickSKU, quickPickSubsc
export async function createRegistry(): Promise<Registry> {
const subscription: SubscriptionModels.Subscription = await quickPickSubscription();
const resourceGroup: ResourceGroup = await quickPickResourceGroup(true, subscription);
const client = AzureUtilityManager.getInstance().getContainerRegistryManagementClient(subscription);
const client = await AzureUtilityManager.getInstance().getContainerRegistryManagementClient(subscription);
const registryName: string = await acquireRegistryName(client);
const sku: string = await quickPickSKU();
const location = await quickPickLocation(subscription);
Expand Down
4 changes: 2 additions & 2 deletions commands/azureCommands/delete-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ export async function deleteAzureRegistry(context?: AzureRegistryNode): Promise<
}
const shouldDelete = await confirmUserIntent(`Are you sure you want to delete ${registry.name} and its associated images?`);
if (shouldDelete) {
let subscription: SubscriptionModels.Subscription = acrTools.getSubscriptionFromRegistry(registry);
let subscription: SubscriptionModels.Subscription = await acrTools.getSubscriptionFromRegistry(registry);
let resourceGroup: string = acrTools.getResourceGroupName(registry);
const client = AzureUtilityManager.getInstance().getContainerRegistryManagementClient(subscription);
const client = await AzureUtilityManager.getInstance().getContainerRegistryManagementClient(subscription);
await client.registries.beginDeleteMethod(resourceGroup, nonNullProp(registry, 'name'));
vscode.window.showInformationMessage(`Successfully deleted registry ${registry.name}`);
dockerExplorerProvider.refreshRegistries();
Expand Down
4 changes: 2 additions & 2 deletions commands/utils/quick-pick-azure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export async function quickPickSKU(): Promise<string> {
}

export async function quickPickSubscription(): Promise<Subscription> {
const subscriptions = AzureUtilityManager.getInstance().getFilteredSubscriptionList();
const subscriptions = await AzureUtilityManager.getInstance().getFilteredSubscriptionList();
if (subscriptions.length === 0) {
vscode.window.showErrorMessage("You do not have any subscriptions. You can create one in your Azure portal", "Open Portal").then(val => {
if (val === "Open Portal") {
Expand Down Expand Up @@ -144,7 +144,7 @@ export async function confirmUserIntent(yesOrNoPrompt: string): Promise<boolean>

/*Creates a new resource group within the current subscription */
async function createNewResourceGroup(loc: string, subscription?: Subscription): Promise<ResourceGroup> {
const resourceGroupClient = AzureUtilityManager.getInstance().getResourceManagementClient(subscription);
const resourceGroupClient = await AzureUtilityManager.getInstance().getResourceManagementClient(subscription);

let opt: vscode.InputBoxOptions = {
validateInput: async (value: string) => { return await checkForValidResourcegroupName(value, resourceGroupClient) },
Expand Down
90 changes: 33 additions & 57 deletions dockerExtension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

let loadStartTime = Date.now();

import * as assert from 'assert';
import * as opn from 'opn';
import * as path from 'path';
import * as request from 'request-promise-native';
Expand All @@ -29,7 +30,7 @@ import { showLogsContainer } from './commands/showlogs-container';
import { startAzureCLI, startContainer, startContainerInteractive } from './commands/start-container';
import { stopContainer } from './commands/stop-container';
import { systemPrune } from './commands/system-prune';
import { IHasImageDescriptorAndLabel, tagImage } from './commands/tag-image';
import { tagImage } from './commands/tag-image';
import { docker } from './commands/utils/docker-endpoint';
import { DefaultTerminalProvider } from './commands/utils/TerminalProvider';
import { DockerDebugConfigProvider } from './configureWorkspace/configDebugProvider';
Expand Down Expand Up @@ -57,7 +58,6 @@ import { ext } from "./extensionVariables";
import { initializeTelemetryReporter, reporter } from './telemetry/telemetry';
import { AzureAccount } from './typings/azure-account.api';
import { addUserAgent } from './utils/addUserAgent';
import { registerAzureCommand } from './utils/Azure/common';
import { AzureUtilityManager } from './utils/azureUtilityManager';
import { Keytar } from './utils/keytar';

Expand Down Expand Up @@ -108,33 +108,13 @@ function initializeExtensionVariables(ctx: vscode.ExtensionContext): void {
export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
let activateStartTime = Date.now();

const installedExtensions = vscode.extensions.all;
let azureAccount: AzureAccount | undefined;

initializeExtensionVariables(ctx);

await callWithTelemetryAndErrorHandling('docker.activate', async function (this: IActionContext): Promise<void> {
this.properties.isActivationEvent = 'true';
this.measurements.mainFileLoad = (loadEndTime - loadStartTime) / 1000;
this.measurements.mainFileLoadedToActivate = (activateStartTime - loadEndTime) / 1000;

// tslint:disable-next-line:prefer-for-of // Grandfathered in
for (let i = 0; i < installedExtensions.length; i++) {
const extension = installedExtensions[i];
if (extension.id === 'ms-vscode.azure-account') {
try {
let activateAccountExtStart = Date.now();
// tslint:disable-next-line:no-unsafe-any
azureAccount = <AzureAccount>await extension.activate();
let activateAccountExtEnd = Date.now();

this.measurements.activateAccountExt = (activateAccountExtEnd - activateAccountExtStart) / 1000;
} catch (error) {
console.log('Failed to activate the Azure Account Extension: ' + parseError(error).message);
}
break;
}
}
ctx.subscriptions.push(vscode.languages.registerCompletionItemProvider(DOCUMENT_SELECTOR, new DockerfileCompletionItemProvider(), '.'));

const YAML_MODE_ID: vscode.DocumentFilter = { language: 'yaml', scheme: 'file', pattern: COMPOSE_FILE_GLOB_PATTERN };
Expand All @@ -143,37 +123,32 @@ export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
ctx.subscriptions.push(vscode.languages.registerCompletionItemProvider(YAML_MODE_ID, new DockerComposeCompletionItemProvider(), '.'));
ctx.subscriptions.push(vscode.workspace.registerTextDocumentContentProvider(DOCKER_INSPECT_SCHEME, new DockerInspectDocumentContentProvider()));

if (azureAccount) {
AzureUtilityManager.getInstance().setAccount(azureAccount);
}

registerDockerCommands(azureAccount);
registerDockerCommands();

ctx.subscriptions.push(vscode.debug.registerDebugConfigurationProvider('docker', new DockerDebugConfigProvider()));
await consolidateDefaultRegistrySettings();
activateLanguageClient(ctx);

// Start loading the Azure account after we're completely done activating.
setTimeout(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's with the use of setTimeout? It feels like you just need to call this without an await:

AzureUtilityManager.getInstance().tryGetAzureAccount()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm just being overly certainly that it doesn't start until we're completely out of our code.

// Do not wait
// tslint:disable-next-line:promise-function-async
() => AzureUtilityManager.getInstance().tryGetAzureAccount(),
1);
});
}

async function createWebApp(context?: AzureImageTagNode | DockerHubImageTagNode, azureAccount?: AzureAccount): Promise<void> {
if (context) {
if (azureAccount) {
const azureAccountWrapper = new AzureAccountWrapper(ext.context, azureAccount);
const wizard = new WebAppCreator(ext.outputChannel, azureAccountWrapper, context);
const result = await wizard.run();
if (result.status === 'Faulted') {
throw result.error;
} else if (result.status === 'Cancelled') {
throw new UserCancelledError();
}
} else {
const open: vscode.MessageItem = { title: "View in Marketplace" };
const response = await vscode.window.showErrorMessage('Please install the Azure Account extension to deploy to Azure.', open);
if (response === open) {
// tslint:disable-next-line:no-unsafe-any
opn('https://marketplace.visualstudio.com/items?itemName=ms-vscode.azure-account');
}
}
async function createWebApp(context?: AzureImageTagNode | DockerHubImageTagNode): Promise<void> {
assert(!!context, "Should not be available through command palette");

let azureAccount = await AzureUtilityManager.getInstance().requireAzureAccount();
const azureAccountWrapper = new AzureAccountWrapper(ext.context, azureAccount);
const wizard = new WebAppCreator(ext.outputChannel, azureAccountWrapper, context);
const result = await wizard.run();
if (result.status === 'Faulted') {
throw result.error;
} else if (result.status === 'Cancelled') {
throw new UserCancelledError();
}
}

Expand Down Expand Up @@ -201,8 +176,8 @@ function registerCommand(commandId: string, callback: (this: IActionContext, ...
});
}

function registerDockerCommands(azureAccount: AzureAccount | undefined): void {
dockerExplorerProvider = new DockerExplorerProvider(azureAccount);
function registerDockerCommands(): void {
dockerExplorerProvider = new DockerExplorerProvider();
vscode.window.registerTreeDataProvider('dockerExplorer', dockerExplorerProvider);
registerCommand('vscode-docker.explorer.refresh', () => dockerExplorerProvider.refresh());

Expand All @@ -228,22 +203,23 @@ function registerDockerCommands(azureAccount: AzureAccount | undefined): void {
registerCommand('vscode-docker.compose.down', composeDown);
registerCommand('vscode-docker.compose.restart', composeRestart);
registerCommand('vscode-docker.system.prune', systemPrune);
registerCommand('vscode-docker.createWebApp', async (context?: AzureImageTagNode | DockerHubImageTagNode) => await createWebApp(context, azureAccount));
registerCommand('vscode-docker.dockerHubLogout', dockerHubLogout);
registerCommand('vscode-docker.browseDockerHub', (context?: DockerHubImageTagNode | DockerHubRepositoryNode | DockerHubOrgNode) => {
browseDockerHub(context);
});
registerCommand('vscode-docker.browseAzurePortal', (context?: AzureRegistryNode | AzureRepositoryNode | AzureImageTagNode) => {
browseAzurePortal(context);
});
registerCommand('vscode-docker.connectCustomRegistry', connectCustomRegistry);
registerCommand('vscode-docker.disconnectCustomRegistry', disconnectCustomRegistry);
registerCommand('vscode-docker.setRegistryAsDefault', setRegistryAsDefault);
registerAzureCommand('vscode-docker.delete-ACR-Registry', deleteAzureRegistry);
registerAzureCommand('vscode-docker.delete-ACR-Image', deleteAzureImage);
registerAzureCommand('vscode-docker.delete-ACR-Repository', deleteRepository);
registerAzureCommand('vscode-docker.create-ACR-Registry', createRegistry);
registerAzureCommand('vscode-docker.pull-ACR-Image', pullFromAzure);

registerCommand('vscode-docker.browseAzurePortal', (context?: AzureRegistryNode | AzureRepositoryNode | AzureImageTagNode) => {
browseAzurePortal(context);
});
registerCommand('vscode-docker.createWebApp', async (context?: AzureImageTagNode | DockerHubImageTagNode) => await createWebApp(context));
registerCommand('vscode-docker.delete-ACR-Registry', deleteAzureRegistry);
registerCommand('vscode-docker.delete-ACR-Image', deleteAzureImage);
registerCommand('vscode-docker.delete-ACR-Repository', deleteRepository);
registerCommand('vscode-docker.create-ACR-Registry', createRegistry);
registerCommand('vscode-docker.pull-ACR-Image', pullFromAzure);
}

export async function deactivate(): Promise<void> {
Expand Down
9 changes: 1 addition & 8 deletions explorer/dockerExplorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import { docker } from '../commands/utils/docker-endpoint';
import { AzureAccount } from '../typings/azure-account.api';
import { NodeBase } from './models/nodeBase';
import { RootNode } from './models/rootNode';

Expand All @@ -16,11 +14,6 @@ export class DockerExplorerProvider implements vscode.TreeDataProvider<NodeBase>
private _imagesNode: RootNode | undefined;
private _containersNode: RootNode | undefined;
private _registriesNode: RootNode | undefined;
private _azureAccount: AzureAccount | undefined;

constructor(azureAccount: AzureAccount | undefined) {
this._azureAccount = azureAccount;
}

public refresh(): void {
this.refreshImages();
Expand Down Expand Up @@ -67,7 +60,7 @@ export class DockerExplorerProvider implements vscode.TreeDataProvider<NodeBase>
this._containersNode = node;
rootNodes.push(node);

node = new RootNode('Registries', 'registriesRootNode', this._onDidChangeTreeData, this._azureAccount);
node = new RootNode('Registries', 'registriesRootNode', this._onDidChangeTreeData);
this._registriesNode = node;
rootNodes.push(node);

Expand Down
4 changes: 2 additions & 2 deletions explorer/models/azureRegistryNodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { IconPath, NodeBase } from './nodeBase';
export class AzureRegistryNode extends NodeBase {
constructor(
public readonly label: string,
public readonly azureAccount: AzureAccount | undefined,
public readonly azureAccount: AzureAccount,
public readonly registry: ContainerModels.Registry,
public readonly subscription: SubscriptionModels.Subscription
) {
Expand Down Expand Up @@ -94,7 +94,7 @@ export class AzureRepositoryNode extends NodeBase {
public async getChildren(element: AzureRepositoryNode): Promise<AzureImageTagNode[]> {
const imageNodes: AzureImageTagNode[] = [];
let node: AzureImageTagNode;
let repo = new Repository(element.registry, element.label);
let repo = await Repository.Create(element.registry, element.label);
let images: AzureImage[] = await getImagesByRepository(repo);
for (let img of images) {
node = new AzureImageTagNode(
Expand Down
8 changes: 4 additions & 4 deletions explorer/models/registryRootNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ export class RegistryRootNode extends NodeBase {
constructor(
public readonly label: string,
public readonly contextValue: 'dockerHubRootNode' | 'azureRegistryRootNode' | 'customRootNode',
public readonly eventEmitter?: vscode.EventEmitter<NodeBase>,
public readonly azureAccount?: AzureAccount
public readonly eventEmitter: vscode.EventEmitter<NodeBase> | undefined, // Needed only for Azure
public readonly azureAccount: AzureAccount | undefined // Needed only for Azure
) {
super(label);

Expand Down Expand Up @@ -133,14 +133,14 @@ export class RegistryRootNode extends NodeBase {
}

if (loggedIntoAzure) {
const subscriptions: SubscriptionModels.Subscription[] = AzureUtilityManager.getInstance().getFilteredSubscriptionList();
const subscriptions: SubscriptionModels.Subscription[] = await AzureUtilityManager.getInstance().getFilteredSubscriptionList();

const subPool = new AsyncPool(MAX_CONCURRENT_SUBSCRIPTON_REQUESTS);
let subsAndRegistries: { 'subscription': SubscriptionModels.Subscription, 'registries': ContainerModels.RegistryListResult }[] = [];
//Acquire each subscription's data simultaneously
for (let sub of subscriptions) {
subPool.addTask(async () => {
const client = AzureUtilityManager.getInstance().getContainerRegistryManagementClient(sub);
const client = await AzureUtilityManager.getInstance().getContainerRegistryManagementClient(sub);
try {
let regs: ContainerModels.Registry[] = await client.registries.list();
subsAndRegistries.push({
Expand Down
15 changes: 7 additions & 8 deletions explorer/models/rootNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as path from 'path';
import * as vscode from 'vscode';
import { docker } from '../../commands/utils/docker-endpoint';
import { AzureAccount } from '../../typings/azure-account.api';
import { AzureUtilityManager } from '../../utils/azureUtilityManager';
import { ContainerNode, ContainerNodeContextValue } from './containerNode';
import { ImageNode } from './imageNode';
import { IconPath, NodeBase } from './nodeBase';
Expand All @@ -31,21 +32,18 @@ export class RootNode extends NodeBase {
private _containerCache: Docker.ContainerDesc[] | undefined;
private _containerDebounceTimer: NodeJS.Timer | undefined;
private _containersNode: RootNode | undefined;
private _azureAccount: AzureAccount | undefined;

constructor(
public readonly label: string,
public readonly contextValue: 'imagesRootNode' | 'containersRootNode' | 'registriesRootNode',
public eventEmitter: vscode.EventEmitter<NodeBase>,
public azureAccount?: AzureAccount
public eventEmitter: vscode.EventEmitter<NodeBase>
) {
super(label);
if (this.contextValue === 'imagesRootNode') {
this._imagesNode = this;
} else if (this.contextValue === 'containersRootNode') {
this._containersNode = this;
}
this._azureAccount = azureAccount;
}

public autoRefreshImages(): void {
Expand Down Expand Up @@ -260,13 +258,14 @@ export class RootNode extends NodeBase {
private async getRegistries(): Promise<RegistryRootNode[]> {
const registryRootNodes: RegistryRootNode[] = [];

registryRootNodes.push(new RegistryRootNode('Docker Hub', "dockerHubRootNode"));
registryRootNodes.push(new RegistryRootNode('Docker Hub', "dockerHubRootNode", undefined, undefined));

if (this._azureAccount) {
registryRootNodes.push(new RegistryRootNode('Azure', "azureRegistryRootNode", this.eventEmitter, this._azureAccount));
let azureAccount: AzureAccount = await AzureUtilityManager.getInstance().tryGetAzureAccount();
if (azureAccount) {
registryRootNodes.push(new RegistryRootNode('Azure', "azureRegistryRootNode", this.eventEmitter, azureAccount));
}

registryRootNodes.push(new RegistryRootNode('Private Registries', 'customRootNode'));
registryRootNodes.push(new RegistryRootNode('Private Registries', 'customRootNode', undefined, undefined));

return registryRootNodes;
}
Expand Down
2 changes: 0 additions & 2 deletions explorer/utils/browseAzurePortal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { getTenantId, nonNullValue } from '../../utils/nonNull';
import { AzureImageTagNode, AzureRegistryNode, AzureRepositoryNode } from '../models/azureRegistryNodes';

export function browseAzurePortal(node?: AzureRegistryNode | AzureRepositoryNode | AzureImageTagNode): void {

if (node && node.azureAccount) {
const tenantId: string = getTenantId(node.subscription);
const session: AzureSession = nonNullValue(
Expand All @@ -22,5 +21,4 @@ export function browseAzurePortal(node?: AzureRegistryNode | AzureRepositoryNode
// tslint:disable-next-line:no-unsafe-any
opn(url);
}

}
Loading