Skip to content

Commit

Permalink
Add policy/OAS diff and fix debugging header (#131)
Browse files Browse the repository at this point in the history
  • Loading branch information
RupengLiu authored Oct 21, 2020
1 parent 77df31b commit 563e464
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 41 deletions.
13 changes: 12 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,11 @@
"command": "azureApiManagement.generateFunctions",
"title": "%azureApiManagement.generateFunctions%",
"category": "Azure API Management"
},
{
"command": "azureApiManagement.openDiffEditor",
"title": "Start file diffing",
"icon": "./resources/diff.svg"
}
],
"viewsContainers": {
Expand All @@ -361,7 +366,13 @@
]
},
"menus": {
"editor/title": [],
"editor/title": [
{
"when": "isEditorEnabled",
"command": "azureApiManagement.openDiffEditor",
"group": "navigation"
}
],
"commandPalette": [
{
"command": "azureApiManagement.Refresh",
Expand Down
1 change: 1 addition & 0 deletions resources/diff.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions src/commands/openDiffEditor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import { ext } from "../extensionVariables";

export async function openDiffEditor(uri: vscode.Uri): Promise<void> {
const localPath = uri.fsPath.replace("-tempFile", '');
ext.outputChannel.show();
vscode.commands.executeCommand("vscode.diff", vscode.Uri.file(localPath), vscode.Uri.file(uri.fsPath), 'Original -> Current');
}
6 changes: 6 additions & 0 deletions src/explorer/editors/Editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ export abstract class Editor<ContextT> implements vscode.Disposable {
public abstract getData(context: ContextT): Promise<string>;
public abstract updateData(context: ContextT, data: string): Promise<string>;
public abstract getFilename(context: ContextT): Promise<string>;
public abstract getDiffFilename(context: ContextT): Promise<string>;
public abstract getSaveConfirmationText(context: ContextT): Promise<string>;
public abstract getSize(context: ContextT): Promise<number>;
public async showEditor(context: ContextT, sizeLimit?: number /* in Megabytes */): Promise<void> {
const fileName: string = await this.getFilename(context);
const originFileName: string = await this.getDiffFilename(context);
this.appendLineToOutput(localize('opening', 'Opening "{0}"...', fileName));
if (sizeLimit !== undefined) {
const size: number = await this.getSize(context);
Expand All @@ -37,6 +39,7 @@ export abstract class Editor<ContextT> implements vscode.Disposable {
}

const localFilePath: string = await createTemporaryFile(fileName);
const localOriginPath: string = await createTemporaryFile(originFileName);
const document: vscode.TextDocument = await vscode.workspace.openTextDocument(localFilePath);
if (document.isDirty) {
const overwriteFlag = await vscode.window.showWarningMessage(`You are about to overwrite "${fileName}", which has unsaved changes. Do you want to continue?`, { modal: true }, DialogResponses.yes, DialogResponses.cancel);
Expand All @@ -47,6 +50,9 @@ export abstract class Editor<ContextT> implements vscode.Disposable {

this.fileMap[localFilePath] = [document, context];
const data: string = await this.getData(context);
// store an original copy of the data
await fse.writeFile(localOriginPath, data);

const textEditor: vscode.TextEditor = await vscode.window.showTextDocument(document);
await this.updateEditor(data, textEditor);
}
Expand Down
6 changes: 5 additions & 1 deletion src/explorer/editors/arm/BaseArmResourceEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,14 @@ export abstract class BaseArmResourceEditor<TRoot extends IServiceTreeRoot> exte
}
}

public async getFilename(context: AzureTreeItem<TRoot>): Promise<string> {
public async getDiffFilename(context: AzureTreeItem<TRoot>): Promise<string> {
return `${nameUtil(context.root)}-${this.entityType.toLowerCase()}-arm.json`;
}

public async getFilename(context: AzureTreeItem<TRoot>): Promise<string> {
return `${nameUtil(context.root)}-${this.entityType.toLowerCase()}-arm-tempFile.json`;
}

public async getSize(): Promise<number> {
throw new Error("Method not implemented.");
}
Expand Down
6 changes: 5 additions & 1 deletion src/explorer/editors/openApi/OpenApiEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,14 @@ export class OpenApiEditor extends Editor<ApiTreeItem> {
}
}

public async getFilename(context: ApiTreeItem): Promise<string> {
public async getDiffFilename(context: ApiTreeItem): Promise<string> {
return `${context.root.serviceName}-${context.root.apiName}-openapi.json`;
}

public async getFilename(context: ApiTreeItem): Promise<string> {
return `${context.root.serviceName}-${context.root.apiName}-openapi-tempFile.json`;
}

public async getSize(): Promise<number> {
throw new Error("Method not implemented.");
}
Expand Down
6 changes: 5 additions & 1 deletion src/explorer/editors/policy/BasePolicyEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,14 @@ export abstract class BasePolicyEditor<TRoot extends IServiceTreeRoot> extends E
}
}

public async getFilename(context: AzureTreeItem<TRoot>): Promise<string> {
public async getDiffFilename(context: AzureTreeItem<TRoot>): Promise<string> {
return `${nameUtil(context.root)}.policy.cshtml`;
}

public async getFilename(context: AzureTreeItem<TRoot>): Promise<string> {
return `${nameUtil(context.root)}-tempFile.policy.cshtml`;
}

public async updateData(context: AzureTreeItem<TRoot>, data: string): Promise<string> {
try {
await this.updatePolicy(context, <ApiManagementModels.PolicyContract>{ format: policyFormat, value: data});
Expand Down
20 changes: 12 additions & 8 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { importFunctionAppToApi } from './commands/importFunctionApp/importFunct
import { importOpenApi } from './commands/importOpenApi';
import { importWebApp, importWebAppToApi } from './commands/importWebApp/importWebApp';
import { createNamedValue, updateNamedValue } from './commands/manageNamedValue';
import { openDiffEditor } from './commands/openDiffEditor';
import { openInPortal } from './commands/openInPortal';
import { openWorkingFolder } from './commands/openWorkingFolder';
import { setupWorkingFolder } from './commands/setupWorkingFolder';
Expand Down Expand Up @@ -66,6 +67,7 @@ export function activateInternal(context: vscode.ExtensionContext) {
ext.outputChannel = vscode.window.createOutputChannel('Azure API Management');
context.subscriptions.push(ext.outputChannel);
ext.ui = new AzureUserInput(context.globalState);
vscode.commands.executeCommand('setContext', 'isEditorEnabled', false);

registerUIExtensionVariables(ext);

Expand Down Expand Up @@ -106,6 +108,7 @@ export function activateInternal(context: vscode.ExtensionContext) {

registerCommand('azureApiManagement.openExtensionWorkspaceFolder', openWorkingFolder);
registerCommand('azureApiManagement.initializeExtensionWorkspaceFolder', setupWorkingFolder);
registerCommand('azureApiManagement.openDiffEditor', async (uri: vscode.Uri) => await openDiffEditor(uri));

registerCommand('azureApiManagement.generateFunctions', async (node: ApiTreeItem) => await generateFunctions(node));

Expand All @@ -114,97 +117,98 @@ export function activateInternal(context: vscode.ExtensionContext) {
activate(context); // activeta debug context
}

// tslint:disable-next-line: max-func-body-length
function registerEditors(context: vscode.ExtensionContext) : void {
const apiResourceEditor: ApiResourceEditor = new ApiResourceEditor();
context.subscriptions.push(apiResourceEditor);
registerEvent('azureApiManagement.ApiResourceEditor.onDidSaveTextDocument', vscode.workspace.onDidSaveTextDocument, async function (this: IActionContext, doc: vscode.TextDocument): Promise<void> { await apiResourceEditor.onDidSaveTextDocument(this, context.globalState, doc); });

registerCommand('azureApiManagement.showArmApi', async (node?: ApiTreeItem) => {
if (!node) {
node = <ApiTreeItem>await ext.tree.showTreeItemPicker(ApiTreeItem.contextValue);
}
await apiResourceEditor.showEditor(node);
vscode.commands.executeCommand('setContext', 'isEditorEnabled', true);
}, doubleClickDebounceDelay);

const operationResourceEditor: OperationResourceEditor = new OperationResourceEditor();
context.subscriptions.push(operationResourceEditor);
registerEvent('azureApiManagement.OperationResourceEditor.onDidSaveTextDocument', vscode.workspace.onDidSaveTextDocument, async function (this: IActionContext, doc: vscode.TextDocument): Promise<void> { await operationResourceEditor.onDidSaveTextDocument(this, context.globalState, doc); });

registerCommand('azureApiManagement.showArmApiOperation', async (node?: ApiOperationTreeItem) => {
if (!node) {
node = <ApiOperationTreeItem>await ext.tree.showTreeItemPicker(ApiOperationTreeItem.contextValue);
}
await operationResourceEditor.showEditor(node);
vscode.commands.executeCommand('setContext', 'isEditorEnabled', true);
}, doubleClickDebounceDelay);

const productResourceEditor: ProductResourceEditor = new ProductResourceEditor();
context.subscriptions.push(productResourceEditor);
registerEvent('azureApiManagement.ProductResourceEditor.onDidSaveTextDocument', vscode.workspace.onDidSaveTextDocument, async function (this: IActionContext, doc: vscode.TextDocument): Promise<void> { await productResourceEditor.onDidSaveTextDocument(this, context.globalState, doc); });

registerCommand('azureApiManagement.showArmProduct', async (node?: ProductTreeItem) => {
if (!node) {
node = <ProductTreeItem>await ext.tree.showTreeItemPicker(ProductTreeItem.contextValue);
}
await productResourceEditor.showEditor(node);
vscode.commands.executeCommand('setContext', 'isEditorEnabled', true);
}, doubleClickDebounceDelay);

const apiEditor: OpenApiEditor = new OpenApiEditor();
context.subscriptions.push(apiEditor);
registerEvent('azureApiManagement.apiEditor.onDidSaveTextDocument', vscode.workspace.onDidSaveTextDocument, async function (this: IActionContext, doc: vscode.TextDocument): Promise<void> { await apiEditor.onDidSaveTextDocument(this, context.globalState, doc); });

registerCommand('azureApiManagement.showApi', async (node?: ApiTreeItem) => {
if (!node) {
node = <ApiTreeItem>await ext.tree.showTreeItemPicker(ApiTreeItem.contextValue);
}
await apiEditor.showEditor(node);
vscode.commands.executeCommand('setContext', 'isEditorEnabled', true);
}, doubleClickDebounceDelay);

const servicePolicyEditor: ServicePolicyEditor = new ServicePolicyEditor();
context.subscriptions.push(servicePolicyEditor);
registerEvent('azureApiManagement.servicePolicyEditor.onDidSaveTextDocument', vscode.workspace.onDidSaveTextDocument, async function (this: IActionContext, doc: vscode.TextDocument): Promise<void> { await servicePolicyEditor.onDidSaveTextDocument(this, context.globalState, doc); });

registerCommand('azureApiManagement.showServicePolicy', async (node?: ServicePolicyTreeItem) => {
if (!node) {
const serviceNode = <ServiceTreeItem>await ext.tree.showTreeItemPicker(ServiceTreeItem.contextValue);
node = serviceNode.servicePolicyTreeItem;
}
await servicePolicyEditor.showEditor(node);
vscode.commands.executeCommand('setContext', 'isEditorEnabled', true);
}, doubleClickDebounceDelay);

const apiPolicyEditor: ApiPolicyEditor = new ApiPolicyEditor();
context.subscriptions.push(apiPolicyEditor);
registerEvent('azureApiManagement.apiPolicyEditor.onDidSaveTextDocument', vscode.workspace.onDidSaveTextDocument, async function (this: IActionContext, doc: vscode.TextDocument): Promise<void> { await apiPolicyEditor.onDidSaveTextDocument(this, context.globalState, doc); });

registerCommand('azureApiManagement.showApiPolicy', async (node?: ApiPolicyTreeItem) => {
if (!node) {
const apiNode = <ApiTreeItem>await ext.tree.showTreeItemPicker(ApiTreeItem.contextValue);
node = apiNode.policyTreeItem;
}
await apiPolicyEditor.showEditor(node);
vscode.commands.executeCommand('setContext', 'isEditorEnabled', true);
}, doubleClickDebounceDelay);

const operationPolicyEditor: OperationPolicyEditor = new OperationPolicyEditor();
context.subscriptions.push(operationPolicyEditor);
registerEvent('azureApiManagement.operationPolicyEditor.onDidSaveTextDocument', vscode.workspace.onDidSaveTextDocument, async function (this: IActionContext, doc: vscode.TextDocument): Promise<void> { await operationPolicyEditor.onDidSaveTextDocument(this, context.globalState, doc); });

registerCommand('azureApiManagement.showOperationPolicy', async (node?: OperationPolicyTreeItem) => {
if (!node) {
const operationNode = <ApiOperationTreeItem>await ext.tree.showTreeItemPicker(ApiOperationTreeItem.contextValue);
node = operationNode.policyTreeItem;
}
await operationPolicyEditor.showEditor(node);
vscode.commands.executeCommand('setContext', 'isEditorEnabled', true);
}, doubleClickDebounceDelay);

const productPolicyEditor: ProductPolicyEditor = new ProductPolicyEditor();
context.subscriptions.push(productPolicyEditor);
registerEvent('azureApiManagement.productPolicyEditor.onDidSaveTextDocument', vscode.workspace.onDidSaveTextDocument, async function (this: IActionContext, doc: vscode.TextDocument): Promise<void> { await productPolicyEditor.onDidSaveTextDocument(this, context.globalState, doc); });

registerCommand('azureApiManagement.showProductPolicy', async (node?: ProductPolicyTreeItem) => {
if (!node) {
const productNode = <ProductTreeItem>await ext.tree.showTreeItemPicker(ProductTreeItem.contextValue);
node = productNode.policyTreeItem;
}
await productPolicyEditor.showEditor(node);
vscode.commands.executeCommand('setContext', 'isEditorEnabled', true);
}, doubleClickDebounceDelay);
}

Expand Down
36 changes: 7 additions & 29 deletions src/operationConsole/OperationConsole.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ export class OperationConsole {

let requestSummary = `${method} ${url} HTTP/1.1\n`;

const headers = this.getDebugHeaders();
const subscriptionHeader = api.subscriptionKeyParameterNames?.header;
const headers = this.getDebugHeaders(subscriptionHeader);
const apimService = new ApimService(root.credentials, root.environment.resourceManagerEndpointUrl, root.subscriptionId, root.resourceGroupName, root.serviceName);
const masterSubscriptionObj = await apimService.getSubscriptionMasterkey();
const masterSubscription = <IMasterSubscription>JSON.parse(masterSubscriptionObj);
Expand All @@ -87,34 +88,11 @@ export class OperationConsole {
return requestSummary;
}

// public async buildDebugRequestInfo(root: IOperationTreeRoot): Promise<string> {
// const operation = await root.client.apiOperation.get(root.resourceGroupName, root.serviceName, root.apiName, root.opName);
// const url = getAPIHostUrl(root.serviceName);
// const method = operation.method;
// let body: string | undefined;
// if (operation.request && operation.request.representations && operation.request.representations.length > 0) {
// if (operation.request.representations[0].sample) {
// body = operation.request.representations[0].sample;
// }
// }
// let requestSummary = `${method} ${url} HTTP/1.1\n`;

// const headers = this.getDebugHeaders();
// const apimService = new ApimService(root.credentials, root.environment.resourceManagerEndpointUrl, root.subscriptionId, root.resourceGroupName, root.serviceName);
// const masterSubscriptionObj = await apimService.getSubscriptionMasterkey();
// const masterSubscription = <IMasterSubscription>JSON.parse(masterSubscriptionObj);
// headers.forEach(header => {
// requestSummary += `${header}: ${masterSubscription.properties.primaryKey}\n`;
// });

// if (body) {
// requestSummary += `\n\n${body}`;
// }

// return requestSummary;
// }

private getDebugHeaders(): string[] {
private getDebugHeaders(subscriptionHeader?: string): string[] {
if (subscriptionHeader) {
return [subscriptionHeader, "Ocp-Apim-Debug"];

}
return ["Ocp-Apim-Subscription-Key", "Ocp-Apim-Debug"];
}

Expand Down

0 comments on commit 563e464

Please sign in to comment.