Skip to content

Commit

Permalink
Chrisdias/optionalazure (#149)
Browse files Browse the repository at this point in the history
* make azure account optional
  • Loading branch information
chrisdias committed Oct 19, 2017
1 parent e3ac6ca commit dfc3ac3
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 86 deletions.
35 changes: 27 additions & 8 deletions dockerExtension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import { DockerHubImageNode, DockerHubRepositoryNode, DockerHubOrgNode } from '.
import { AzureAccountWrapper } from './explorer/deploy/azureAccountWrapper';
import * as util from "./explorer/deploy/util";
import { dockerHubLogout, browseDockerHub } from './explorer/models/dockerHubUtils';
import { AzureAccount } from './typings/azure-account.api';
import * as opn from 'opn';

export const FROM_DIRECTIVE_PATTERN = /^\s*FROM\s*([\w-\/:]*)(\s*AS\s*[a-z][a-z0-9-_\\.]*)?$/i;
export const COMPOSE_FILE_GLOB_PATTERN = '**/[dD]ocker-[cC]ompose*.{yaml,yml}';
Expand All @@ -48,15 +50,23 @@ export interface ComposeVersionKeys {
v2: KeyInfo
};

export function activate(ctx: vscode.ExtensionContext): void {
export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
const DOCKERFILE_MODE_ID: vscode.DocumentFilter = { language: 'dockerfile', scheme: 'file' };

ctx.subscriptions.push(new Reporter(ctx));

const installedExtensions: any[] = vscode.extensions.all;
const outputChannel = util.getOutputChannel();
const azureAccount = new AzureAccountWrapper(ctx);
let azureAccount: AzureAccount;

dockerExplorerProvider = new DockerExplorerProvider();
for (var i = 0; i < installedExtensions.length; i++) {
const ext = installedExtensions[i];
if (ext.id === 'ms-vscode.azure-account') {
azureAccount = await ext.activate();
break;
}
}

ctx.subscriptions.push(new Reporter(ctx));

dockerExplorerProvider = new DockerExplorerProvider(azureAccount);
vscode.window.registerTreeDataProvider('dockerExplorer', dockerExplorerProvider);
vscode.commands.registerCommand('dockerExplorer.refreshExplorer', () => dockerExplorerProvider.refresh());
vscode.commands.registerCommand('dockerExplorer.systemPrune', () => systemPrune());
Expand Down Expand Up @@ -90,8 +100,17 @@ export function activate(ctx: vscode.ExtensionContext): void {

ctx.subscriptions.push(vscode.commands.registerCommand('vscode-docker.createWebApp', async (context?: AzureImageNode | DockerHubImageNode) => {
if (context) {
const wizard = new WebAppCreator(outputChannel, azureAccount, context);
const result = await wizard.run();
if (azureAccount) {
const azureAccountWrapper = new AzureAccountWrapper(ctx, azureAccount);
const wizard = new WebAppCreator(outputChannel, azureAccountWrapper, context);
const result = await wizard.run();
} 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) {
opn('https://marketplace.visualstudio.com/items?itemName=ms-vscode.azure-account');
}
}
}
}));

Expand Down
5 changes: 3 additions & 2 deletions explorer/deploy/azureAccountWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ServiceClientCredentials } from 'ms-rest';
import { AzureEnvironment } from 'ms-rest-azure';
import { SubscriptionClient, SubscriptionModels } from 'azure-arm-resource';
import { AzureAccount, AzureSession, AzureLoginStatus } from '../../typings/azure-account.api';

import * as util from './util';

export class NotSignedInError extends Error { }
Expand All @@ -17,8 +18,8 @@ export class CredentialError extends Error { }
export class AzureAccountWrapper {
readonly accountApi: AzureAccount;

constructor(readonly extensionConext: ExtensionContext) {
this.accountApi = extensions.getExtension<AzureAccount>('ms-vscode.azure-account')!.exports;
constructor(readonly extensionConext: ExtensionContext, azureAccount: AzureAccount) {
this.accountApi = azureAccount;
}

getAzureSessions(): AzureSession[] {
Expand Down
8 changes: 7 additions & 1 deletion explorer/dockerExplorer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as vscode from 'vscode';
import { NodeBase } from './models/nodeBase';
import { RootNode } from './models/rootNode';
import { AzureAccount } from '../typings/azure-account.api';

export class DockerExplorerProvider implements vscode.TreeDataProvider<NodeBase> {

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

constructor(azureAccount) {
this._azureAccount = azureAccount;
}

refresh(): void {
this._onDidChangeTreeData.fire(this._imagesNode);
Expand Down Expand Up @@ -51,7 +57,7 @@ export class DockerExplorerProvider implements vscode.TreeDataProvider<NodeBase>
this._containersNode = node;
rootNodes.push(node);

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

Expand Down
13 changes: 9 additions & 4 deletions explorer/models/azureRegistryNodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@ import { SubscriptionClient, ResourceManagementClient, SubscriptionModels } from
import { AzureAccount, AzureSession } from '../../typings/azure-account.api';
import { RegistryType } from './registryType';

const azureAccount: AzureAccount = vscode.extensions.getExtension<AzureAccount>('ms-vscode.azure-account')!.exports;

export class AzureRegistryNode extends NodeBase {
private _azureAccount: AzureAccount;

constructor(
public readonly label: string,
public readonly contextValue: string,
public readonly iconPath: any = {}
public readonly iconPath: any = {},
public readonly azureAccount?: AzureAccount
) {
super(label);
this._azureAccount = azureAccount;
}

public type: RegistryType;
Expand All @@ -39,7 +40,11 @@ export class AzureRegistryNode extends NodeBase {
let node: AzureRepositoryNode;

const tenantId: string = element.subscription.tenantId;
const session: AzureSession = azureAccount.sessions.find((s, i, array) => s.tenantId.toLowerCase() === tenantId.toLowerCase());
if (!this._azureAccount) {
return [];
}

const session: AzureSession = this._azureAccount.sessions.find((s, i, array) => s.tenantId.toLowerCase() === tenantId.toLowerCase());
const { accessToken, refreshToken } = await acquireToken(session);

if (accessToken && refreshToken) {
Expand Down
67 changes: 40 additions & 27 deletions explorer/models/registryRootNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ import { SubscriptionClient, ResourceManagementClient, SubscriptionModels } from

const ContainerRegistryManagement = require('azure-arm-containerregistry');

const azureAccount: AzureAccount = vscode.extensions.getExtension<AzureAccount>('ms-vscode.azure-account')!.exports;

export class RegistryRootNode extends NodeBase {
private _keytar: typeof keytarType;

private _azureAccount: AzureAccount;

constructor(
public readonly label: string,
public readonly contextValue: string,
public readonly eventEmitter: vscode.EventEmitter<NodeBase>
public readonly eventEmitter: vscode.EventEmitter<NodeBase>,
public readonly azureAccount?: AzureAccount
) {
super(label);
try {
Expand All @@ -32,15 +32,17 @@ export class RegistryRootNode extends NodeBase {
// unable to find keytar
}

if (this.eventEmitter && this.contextValue === 'azureRegistryRootNode') {

azureAccount.onFiltersChanged((e) => {
this._azureAccount = azureAccount;

if (this._azureAccount && this.eventEmitter && this.contextValue === 'azureRegistryRootNode') {

this._azureAccount.onFiltersChanged((e) => {
this.eventEmitter.fire(this);
});
azureAccount.onStatusChanged((e) => {
this._azureAccount.onStatusChanged((e) => {
this.eventEmitter.fire(this);
});
azureAccount.onSessionsChanged((e) => {
this._azureAccount.onSessionsChanged((e) => {
this.eventEmitter.fire(this);
});
}
Expand Down Expand Up @@ -109,14 +111,19 @@ export class RegistryRootNode extends NodeBase {
}

private async getAzureRegistries(): Promise<AzureRegistryNode[] | AzureLoadingNode[] | AzureNotSignedInNode[]> {
const loggedIntoAzure: boolean = await azureAccount.waitForLogin()

if (!this._azureAccount) {
return [];
}

const loggedIntoAzure: boolean = await this._azureAccount.waitForLogin()
const azureRegistryNodes: AzureRegistryNode[] = [];

if (azureAccount.status === 'Initializing' || azureAccount.status === 'LoggingIn') {
if (this._azureAccount.status === 'Initializing' || this._azureAccount.status === 'LoggingIn') {
return [new AzureLoadingNode()];
}

if (azureAccount.status === 'LoggedOut') {
if (this._azureAccount.status === 'LoggedOut') {
return [new AzureNotSignedInNode()];
}

Expand All @@ -139,7 +146,7 @@ export class RegistryRootNode extends NodeBase {
light: path.join(__filename, '..', '..', '..', '..', 'images', 'light', 'Registry_16x.svg'),
dark: path.join(__filename, '..', '..', '..', '..', 'images', 'dark', 'Registry_16x.svg')
};
let node = new AzureRegistryNode(registries[j].loginServer, 'registry', iconPath);
let node = new AzureRegistryNode(registries[j].loginServer, 'registry', iconPath, this._azureAccount);
node.type = RegistryType.Azure;
node.password = creds.passwords[0].value;
node.userName = creds.username;
Expand All @@ -148,13 +155,14 @@ export class RegistryRootNode extends NodeBase {
}
}
}
}
}

return azureRegistryNodes;
}

private getCredentialByTenantId(tenantId: string): ServiceClientCredentials {
const session = azureAccount.sessions.find((s, i, array) => s.tenantId.toLowerCase() === tenantId.toLowerCase());

const session = this._azureAccount.sessions.find((s, i, array) => s.tenantId.toLowerCase() === tenantId.toLowerCase());

if (session) {
return session.credentials;
Expand All @@ -164,18 +172,23 @@ export class RegistryRootNode extends NodeBase {
}

private getFilteredSubscriptions(): SubscriptionModels.Subscription[] {
return azureAccount.filters.map<SubscriptionModels.Subscription>(filter => {
return {
id: filter.subscription.id,
session: filter.session,
subscriptionId: filter.subscription.subscriptionId,
tenantId: filter.session.tenantId,
displayName: filter.subscription.displayName,
state: filter.subscription.state,
subscriptionPolicies: filter.subscription.subscriptionPolicies,
authorizationSource: filter.subscription.authorizationSource
};
});

if (this._azureAccount) {
return this._azureAccount.filters.map<SubscriptionModels.Subscription>(filter => {
return {
id: filter.subscription.id,
session: filter.session,
subscriptionId: filter.subscription.subscriptionId,
tenantId: filter.session.tenantId,
displayName: filter.subscription.displayName,
state: filter.subscription.state,
subscriptionPolicies: filter.subscription.subscriptionPolicies,
authorizationSource: filter.subscription.authorizationSource
};
});
} else {
return [];
}
}
}

Expand Down
13 changes: 11 additions & 2 deletions explorer/models/rootNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { docker } from '../../commands/utils/docker-endpoint';
import { ImageNode } from './imageNode';
import { NodeBase } from './nodeBase';
import { RegistryRootNode } from './registryRootNode';
import { AzureAccount } from '../../typings/azure-account.api';

export class RootNode extends NodeBase {
private _imageCache: Docker.ImageDesc[];
Expand All @@ -13,18 +14,21 @@ export class RootNode extends NodeBase {
private _containerCache: Docker.ContainerDesc[];
private _containerDebounceTimer: NodeJS.Timer;
private _containersNode: RootNode;
private _azureAccount: AzureAccount;

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

autoRefreshImages(): void {
Expand Down Expand Up @@ -243,8 +247,13 @@ export class RootNode extends NodeBase {

private async getRegistries(): Promise<RegistryRootNode[]> {
const registryRootNodes: RegistryRootNode[] = [];

registryRootNodes.push(new RegistryRootNode('DockerHub', "dockerHubRootNode", null));
registryRootNodes.push(new RegistryRootNode('Azure', "azureRegistryRootNode", this.eventEmitter));

if (this._azureAccount) {
registryRootNodes.push(new RegistryRootNode('Azure', "azureRegistryRootNode", this.eventEmitter, this._azureAccount));
}

return registryRootNodes;
}
}
Loading

0 comments on commit dfc3ac3

Please sign in to comment.