-
Notifications
You must be signed in to change notification settings - Fork 67
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor remote debugging commands into common library so we can supp…
…ort functions
- Loading branch information
Showing
6 changed files
with
243 additions
and
11 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the MIT License. See License.txt in the project root for license information. | ||
*--------------------------------------------------------------------------------------------*/ | ||
|
||
import { SiteConfigResource } from 'azure-arm-website/lib/models'; | ||
import * as vscode from 'vscode'; | ||
import { callWithTelemetryAndErrorHandling, DialogResponses, IActionContext } from 'vscode-azureextensionui'; | ||
import { ext } from '../extensionVariables'; | ||
import { SiteClient } from '../SiteClient'; | ||
|
||
export const remoteDebugLink: string = 'https://aka.ms/appsvc-remotedebug'; | ||
|
||
export function reportMessage(message: string, progress: vscode.Progress<{}>): void { | ||
ext.outputChannel.appendLine(message); | ||
progress.report({ message: message }); | ||
} | ||
|
||
export async function setRemoteDebug(isRemoteDebuggingToBeEnabled: boolean, confirmMessage: string, noopMessage: string | undefined, siteClient: SiteClient, siteConfig: SiteConfigResource, progress?: vscode.Progress<{}>, learnMoreLink?: string): Promise<void> { | ||
if (isRemoteDebuggingToBeEnabled !== siteConfig.remoteDebuggingEnabled) { | ||
const confirmButton: vscode.MessageItem = isRemoteDebuggingToBeEnabled ? { title: 'Enable' } : { title: 'Disable' }; | ||
|
||
// don't have to check input as this handles cancels and learnMore responses | ||
await ext.ui.showWarningMessage(confirmMessage, { modal: true, learnMoreLink }, confirmButton, DialogResponses.cancel); | ||
siteConfig.remoteDebuggingEnabled = isRemoteDebuggingToBeEnabled; | ||
if (progress) { | ||
reportMessage('Updating site configuration to set remote debugging...', progress); | ||
} | ||
|
||
await callWithTelemetryAndErrorHandling('appService.remoteDebugUpdateConfiguration', async (context: IActionContext) => { | ||
context.errorHandling.suppressDisplay = true; | ||
context.errorHandling.rethrow = true; | ||
await siteClient.updateConfiguration(siteConfig); | ||
}); | ||
|
||
if (progress) { | ||
reportMessage('Updating site configuration done.', progress); | ||
} | ||
} else { | ||
// Update not needed | ||
if (noopMessage) { | ||
vscode.window.showWarningMessage(noopMessage); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the MIT License. See License.txt in the project root for license information. | ||
*--------------------------------------------------------------------------------------------*/ | ||
|
||
import { SiteConfigResource, User } from 'azure-arm-website/lib/models'; | ||
import * as portfinder from 'portfinder'; | ||
import * as vscode from 'vscode'; | ||
import { callWithTelemetryAndErrorHandling, IActionContext } from 'vscode-azureextensionui'; | ||
import { ext } from '../extensionVariables'; | ||
import { SiteClient } from '../SiteClient'; | ||
import { TunnelProxy } from '../TunnelProxy'; | ||
import { remoteDebugLink, reportMessage, setRemoteDebug } from './remoteDebugCommon'; | ||
|
||
let isRemoteDebugging: boolean = false; | ||
|
||
export async function startRemoteDebug(siteClient: SiteClient, siteConfig: SiteConfigResource): Promise<void> { | ||
if (isRemoteDebugging) { | ||
throw new Error('Azure Remote Debugging is currently starting or already started.'); | ||
} | ||
|
||
isRemoteDebugging = true; | ||
try { | ||
await startRemoteDebugInternal(siteClient, siteConfig); | ||
} catch (error) { | ||
isRemoteDebugging = false; | ||
throw error; | ||
} | ||
} | ||
|
||
async function startRemoteDebugInternal(siteClient: SiteClient, siteConfig: SiteConfigResource): Promise<void> { | ||
await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification }, async (progress: vscode.Progress<{}>): Promise<void> => { | ||
const debugConfig: vscode.DebugConfiguration = await getDebugConfiguration(); | ||
// tslint:disable-next-line:no-unsafe-any | ||
const localHostPortNumber: number = debugConfig.port; | ||
|
||
reportMessage('Checking app settings...', progress); | ||
|
||
const confirmEnableMessage: string = 'The app configuration will be updated to enable remote debugging and restarted. Would you like to continue?'; | ||
await setRemoteDebug(true, confirmEnableMessage, undefined, siteClient, siteConfig, progress, remoteDebugLink); | ||
|
||
reportMessage('Starting tunnel proxy...', progress); | ||
|
||
const publishCredential: User = await siteClient.getWebAppPublishCredential(); | ||
const tunnelProxy: TunnelProxy = new TunnelProxy(localHostPortNumber, siteClient, publishCredential); | ||
await callWithTelemetryAndErrorHandling('appService.remoteDebugStartProxy', async (startContext: IActionContext) => { | ||
startContext.errorHandling.suppressDisplay = true; | ||
startContext.errorHandling.rethrow = true; | ||
await tunnelProxy.startProxy(); | ||
}); | ||
|
||
reportMessage('Attaching debugger...', progress); | ||
|
||
await callWithTelemetryAndErrorHandling('appService.remoteDebugAttach', async (attachContext: IActionContext) => { | ||
attachContext.errorHandling.suppressDisplay = true; | ||
attachContext.errorHandling.rethrow = true; | ||
await vscode.debug.startDebugging(undefined, debugConfig); | ||
}); | ||
|
||
reportMessage('Attached!', progress); | ||
|
||
const terminateDebugListener: vscode.Disposable = vscode.debug.onDidTerminateDebugSession(async (event: vscode.DebugSession) => { | ||
if (event.name === debugConfig.name) { | ||
isRemoteDebugging = false; | ||
|
||
if (tunnelProxy !== undefined) { | ||
tunnelProxy.dispose(); | ||
} | ||
terminateDebugListener.dispose(); | ||
|
||
const confirmDisableMessage: string = 'Leaving the app in debugging mode may cause performance issues. Would you like to disable debugging for this app? The app will be restarted.'; | ||
await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification }, async (innerProgress: vscode.Progress<{}>): Promise<void> => { | ||
await setRemoteDebug(false, confirmDisableMessage, undefined, siteClient, siteConfig, innerProgress, remoteDebugLink); | ||
}); | ||
} | ||
}); | ||
}); | ||
} | ||
|
||
async function getDebugConfiguration(): Promise<vscode.DebugConfiguration> { | ||
const sessionId: string = Date.now().toString(); | ||
const portNumber: number = await portfinder.getPortPromise(); | ||
|
||
// So far only node is supported | ||
const config: vscode.DebugConfiguration = { | ||
// return { | ||
name: sessionId, | ||
type: 'node', | ||
protocol: 'inspector', | ||
request: 'attach', | ||
address: 'localhost', | ||
port: portNumber | ||
}; | ||
|
||
// Try to map workspace folder source files to the remote instance | ||
if (vscode.workspace.workspaceFolders) { | ||
if (vscode.workspace.workspaceFolders.length === 1) { | ||
config.localRoot = vscode.workspace.workspaceFolders[0].uri.fsPath; | ||
config.remoteRoot = '/home/site/wwwroot'; | ||
} else { | ||
// In this case we don't know which folder to use. Show a warning and proceed. | ||
// In the future we should allow users to choose a workspace folder to map sources from. | ||
// tslint:disable-next-line:no-floating-promises | ||
ext.ui.showWarningMessage('Unable to bind breakpoints from workspace when multiple folders are open. Use "loaded scripts" instead.'); | ||
} | ||
} else { | ||
// vscode will throw an error if you try to start debugging without any workspace folder open | ||
throw new Error('Please open a workspace folder before attaching a debugger.'); | ||
} | ||
|
||
return config; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the MIT License. See License.txt in the project root for license information. | ||
*--------------------------------------------------------------------------------------------*/ | ||
|
||
import { SiteConfigResource } from 'azure-arm-website/lib/models'; | ||
import * as vscode from 'vscode'; | ||
import { SiteClient } from '../SiteClient'; | ||
import { remoteDebugLink, setRemoteDebug } from './remoteDebugCommon'; | ||
|
||
export async function stopRemoteDebug(siteClient: SiteClient, siteConfig: SiteConfigResource): Promise<void> { | ||
const confirmMessage: string = 'The app configuration will be updated to disable remote debugging and restarted. Would you like to continue?'; | ||
const noopMessage: string = 'The app is not configured for debugging.'; | ||
|
||
await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification }, async (progress: vscode.Progress<{}>): Promise<void> => { | ||
await setRemoteDebug(false, confirmMessage, noopMessage, siteClient, siteConfig, progress, remoteDebugLink); | ||
}); | ||
} |