Add remote debugging support for Node.js on Linux App Service plans (#1458)

This commit is contained in:
Michael Crane 2019-09-04 14:30:41 -07:00 коммит произвёл Eric Jizba
Родитель 5d9891c914
Коммит 58bef37800
8 изменённых файлов: 91 добавлений и 17 удалений

Просмотреть файл

@ -37,8 +37,10 @@ Install the prerequisites for your desired language:
* Stream logs from your Azure Function Apps
* View and manage deployment slots
> **NOTE**: To enable, set `azureFunctions.enableSlots` to true.
* Debug Java function project in Azure (experimental)
* Debug Node.js function project in Azure (experimental)
> **NOTE**: To enable, set `azureFunctions.enableRemoteDebugging` to true.
* Debug Java function project in Azure (experimental)
> **NOTE**: To enable, set `azureFunctions.enableJavaRemoteDebugging` to true.
### Create New Project

Просмотреть файл

@ -48,7 +48,8 @@
"onCommand:azureFunctions.deleteFunction",
"onCommand:azureFunctions.deploy",
"onCommand:azureFunctions.configureDeploymentSource",
"onCommand:azureFunctions.debugFunctionAppOnAzure",
"onCommand:azureFunctions.startRemoteDebug",
"onCommand:azureFunctions.startJavaRemoteDebug",
"onCommand:azureFunctions.appSettings.add",
"onCommand:azureFunctions.appSettings.download",
"onCommand:azureFunctions.appSettings.upload",
@ -176,8 +177,13 @@
"category": "Azure Functions"
},
{
"command": "azureFunctions.debugFunctionAppOnAzure",
"title": "%azFunc.debugFunctionAppOnAzure%",
"command": "azureFunctions.startRemoteDebug",
"title": "%azFunc.startRemoteDebug%",
"category": "Azure Functions"
},
{
"command": "azureFunctions.startJavaRemoteDebug",
"title": "%azFunc.startJavaRemoteDebug%",
"category": "Azure Functions"
},
{
@ -452,10 +458,15 @@
"group": "4@2"
},
{
"command": "azureFunctions.debugFunctionAppOnAzure",
"command": "azureFunctions.startRemoteDebug",
"when": "view == azFuncTree && viewItem =~ /^azFunc(Production|)Slot$/ && config.azureFunctions.enableRemoteDebugging == true",
"group": "5@1"
},
{
"command": "azureFunctions.startJavaRemoteDebug",
"when": "view == azFuncTree && viewItem =~ /^azFunc(Production|)Slot$/ && config.azureFunctions.enableJavaRemoteDebugging == true",
"group": "5@2"
},
{
"command": "azureFunctions.viewProperties",
"when": "view == azFuncTree && viewItem =~ /^azFunc(Production|)Slot$/",
@ -646,9 +657,13 @@
"when": "never"
},
{
"command": "azureFunctions.debugFunctionAppOnAzure",
"command": "azureFunctions.startRemoteDebug",
"when": "config.azureFunctions.enableRemoteDebugging == true"
},
{
"command": "azureFunctions.startJavaRemoteDebug",
"when": "config.azureFunctions.enableJavaRemoteDebugging == true"
},
{
"command": "azureFunctions.createSlot",
"when": "config.azureFunctions.enableSlots == true"
@ -831,6 +846,11 @@
"description": "%azFunc.enableRemoteDebugging%",
"default": false
},
"azureFunctions.enableJavaRemoteDebugging": {
"type": "boolean",
"description": "%azFunc.enableJavaRemoteDebugging%",
"default": false
},
"azureFunctions.showProjectWarning": {
"type": "boolean",
"description": "%azFunc.showProjectWarningDescription%",

Просмотреть файл

@ -22,7 +22,8 @@
"azFunc.projectLanguageDescription": "The default language to use when performing operations in the Azure Functions extension (e.g. \"Create New Function\").",
"azFunc.deploy": "Deploy to Function App...",
"azFunc.configureDeploymentSource": "Configure Deployment Source...",
"azFunc.debugFunctionAppOnAzure": "Attach Debugger",
"azFunc.startRemoteDebug": "Start Remote Debugging",
"azFunc.startJavaRemoteDebug": "Attach Debugger",
"azFunc.appSettings.add": "Add New Setting...",
"azFunc.appSettings.download": "Download Remote Settings...",
"azFunc.appSettings.upload": "Upload Local Settings...",
@ -46,7 +47,8 @@
"azFunc.showDeploySubpathWarningDescription": "Show a warning when the \"deploySubpath\" setting does not match the selected folder for deploying.",
"azFunc.startStreamingLogs": "Start Streaming Logs",
"azFunc.stopStreamingLogs": "Stop Streaming Logs",
"azFunc.enableRemoteDebugging": "Enable remote debugging, an experimental feature that only supports Java-based Functions Apps.",
"azFunc.enableRemoteDebugging": "Enable remote debugging for Node.js Function Apps running on Linux App Service plans. Consumption plans are not supported. (experimental)",
"azFunc.enableJavaRemoteDebugging": "Enable remote debugging for Java Functions Apps running on Windows. (experimental)",
"azFunc.deleteProxy": "Delete Proxy...",
"azFunc.pickProcessTimeoutDescription": "The timeout (in seconds) to be used when searching for the Azure Functions host process. Since a build is required every time you F5, you may need to adjust this based on how long your build takes.",
"azFunc.templateVersion": "A runtime release version (any runtime) that species which templates will be used rather than the latest templates. This version will be used for ALL runtimes. (Requires a restart of VS Code to take effect)",

Просмотреть файл

@ -0,0 +1,19 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { WebSiteManagementModels } from 'azure-arm-website';
export function checkForRemoteDebugSupport(siteConfig: WebSiteManagementModels.SiteConfig): void {
// Read siteConfig.linuxFxVersion to determine debugging support
// If the Function App is running on Windows, it will be empty
// If the Function App is running on Linux consumption, it will be empty
// If the Function App is running on a Linux App Service plan, it will contain Docker registry information, e.g. "DOCKER|repo.azurecr.io/image:tag"
// The blessed Node.js Docker image will be something like "DOCKER|mcr.microsoft.com/azure-functions/node:2.0-node8-appservice"
if (siteConfig.linuxFxVersion && siteConfig.linuxFxVersion.startsWith('DOCKER|mcr.microsoft.com/azure-functions/node')) {
return;
}
throw new Error('Azure Remote Debugging is currently only supported for Node.js Function Apps running on Linux App Service plans. Consumption plans are not supported.');
}

Просмотреть файл

@ -0,0 +1,29 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { WebSiteManagementModels } from 'azure-arm-website';
import * as vscode from 'vscode';
import * as appservice from 'vscode-azureappservice';
import { IActionContext } from 'vscode-azureextensionui';
import { ext } from '../../extensionVariables';
import { ProductionSlotTreeItem } from '../../tree/ProductionSlotTreeItem';
import { SlotTreeItemBase } from '../../tree/SlotTreeItemBase';
import { checkForRemoteDebugSupport } from './checkForRemoteDebugSupport';
export async function startRemoteDebug(context: IActionContext, node?: SlotTreeItemBase): Promise<void> {
if (!node) {
node = await ext.tree.showTreeItemPicker<SlotTreeItemBase>(ProductionSlotTreeItem.contextValue, context);
}
const siteClient: appservice.SiteClient = node.root.client;
const siteConfig: WebSiteManagementModels.SiteConfig = await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification }, async progress => {
appservice.reportMessage('Fetching site configuration...', progress);
return await siteClient.getSiteConfig();
});
checkForRemoteDebugSupport(siteConfig);
await appservice.startRemoteDebug(siteClient, siteConfig);
}

Просмотреть файл

Просмотреть файл

@ -8,17 +8,17 @@ import * as portfinder from 'portfinder';
import * as vscode from 'vscode';
import { SiteClient } from 'vscode-azureappservice';
import { DialogResponses, IActionContext } from 'vscode-azureextensionui';
import { DebugProxy } from '../DebugProxy';
import { ext } from '../extensionVariables';
import { localize } from '../localize';
import { ProductionSlotTreeItem } from '../tree/ProductionSlotTreeItem';
import { SlotTreeItemBase } from '../tree/SlotTreeItemBase';
import { openUrl } from '../utils/openUrl';
import { ext } from '../../extensionVariables';
import { localize } from '../../localize';
import { ProductionSlotTreeItem } from '../../tree/ProductionSlotTreeItem';
import { SlotTreeItemBase } from '../../tree/SlotTreeItemBase';
import { openUrl } from '../../utils/openUrl';
import { DebugProxy } from './DebugProxy';
const HTTP_PLATFORM_DEBUG_PORT: string = '8898';
const JAVA_OPTS: string = `-Djava.net.preferIPv4Stack=true -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=127.0.0.1:${HTTP_PLATFORM_DEBUG_PORT}`;
export async function remoteDebugFunctionApp(context: IActionContext, node?: SlotTreeItemBase): Promise<void> {
export async function remoteDebugJavaFunctionApp(context: IActionContext, node?: SlotTreeItemBase): Promise<void> {
if (!node) {
node = await ext.tree.showTreeItemPicker<SlotTreeItemBase>(ProductionSlotTreeItem.contextValue, context);
}

Просмотреть файл

@ -39,7 +39,8 @@ import { startStreamingLogs } from './commands/logstream/startStreamingLogs';
import { stopStreamingLogs } from './commands/logstream/stopStreamingLogs';
import { openInPortal } from './commands/openInPortal';
import { pickFuncProcess } from './commands/pickFuncProcess';
import { remoteDebugFunctionApp } from './commands/remoteDebugFunctionApp';
import { startRemoteDebug } from './commands/remoteDebug/startRemoteDebug';
import { remoteDebugJavaFunctionApp } from './commands/remoteDebugJava/remoteDebugJavaFunctionApp';
import { renameAppSetting } from './commands/renameAppSetting';
import { restartFunctionApp } from './commands/restartFunctionApp';
import { startFunctionApp } from './commands/startFunctionApp';
@ -128,7 +129,8 @@ export async function activateInternal(context: vscode.ExtensionContext, perfSta
registerCommand('azureFunctions.appSettings.encrypt', encryptLocalSettings);
registerCommand('azureFunctions.appSettings.delete', async (actionContext: IActionContext, node?: AzExtTreeItem) => await deleteNode(actionContext, AppSettingTreeItem.contextValue, node));
registerCommand('azureFunctions.appSettings.toggleSlotSetting', toggleSlotSetting);
registerCommand('azureFunctions.debugFunctionAppOnAzure', remoteDebugFunctionApp);
registerCommand('azureFunctions.startRemoteDebug', startRemoteDebug);
registerCommand('azureFunctions.startJavaRemoteDebug', remoteDebugJavaFunctionApp);
registerCommand('azureFunctions.deleteProxy', async (actionContext: IActionContext, node?: AzExtTreeItem) => await deleteNode(actionContext, ProxyTreeItem.contextValue, node));
registerCommand('azureFunctions.installOrUpdateFuncCoreTools', installOrUpdateFuncCoreTools);
registerCommand('azureFunctions.uninstallFuncCoreTools', uninstallFuncCoreTools);