enable running dot-net function on Windows to allow attaching remote debugger (#2344)

* enable running dot-net function on Windows to allow attaching remote debugger

* rename from 'use_windows' to 'host_dotnet_on_windows'

* instructions

* reformat deploy.py

Co-authored-by: stas <statis@microsoft.com>
This commit is contained in:
Stas
2022-09-06 09:34:22 -07:00
committed by GitHub
parent dd3aa1ce0a
commit c175b4676a
7 changed files with 118 additions and 30 deletions

3
.gitignore vendored
View File

@ -10,3 +10,6 @@
*.swp *.swp
/.ionide/symbolCache.db /.ionide/symbolCache.db
/src/ApiService/ApiService/Properties/PublishProfiles/*
/src/ApiService/ApiService/Properties/ServiceDependencies/*

View File

@ -0,0 +1,5 @@
## How to setup remote debugging of dotnet Azure Functions on new deployments
1) when running `deploy.py` use `--host_dotnet_on_windows` flag as part of the command line. This will deploy `dotnet` Azure Function on Windows Server Farm, which supports functinoality for remote debugging of `dotnet` code.
2) Follow instructions on how to connect Visual Studio 2022 to newly deployed Azure Function: [https://docs.microsoft.com/en-us/azure/azure-functions/functions-develop-vs?tabs=in-process#remote-debugging](https://docs.microsoft.com/en-us/azure/azure-functions/functions-develop-vs?tabs=in-process#remote-debugging)

View File

@ -9,6 +9,7 @@ param signedExpiry string
param app_func_issuer string param app_func_issuer string
param app_func_audiences array param app_func_audiences array
param multi_tenant_domain string param multi_tenant_domain string
param enable_remote_debugging bool = false
param location string = resourceGroup().location param location string = resourceGroup().location
@ -78,14 +79,29 @@ module operationalInsights 'bicep-templates/operational-insights.bicep' = {
} }
} }
module serverFarms 'bicep-templates/server-farms.bicep' = { module linuxServerFarm 'bicep-templates/server-farms.bicep' = {
name: 'server-farms' name: 'linux-server-farm'
params: { params: {
server_farm_name: name server_farm_name: name
owner: owner owner: owner
location: location location: location
use_windows: false
create: true
} }
} }
module dotNetServerFarm 'bicep-templates/server-farms.bicep' = {
name: (enable_remote_debugging) ? 'windows-server-farm' : 'same-linux-server-farm'
params: {
server_farm_name: (enable_remote_debugging) ? '${name}-net' : name
owner: owner
location: location
use_windows: enable_remote_debugging
create: enable_remote_debugging
}
}
var keyVaultName = 'of-kv-${uniqueString(resourceGroup().id)}' var keyVaultName = 'of-kv-${uniqueString(resourceGroup().id)}'
resource keyVault 'Microsoft.KeyVault/vaults@2021-10-01' = { resource keyVault 'Microsoft.KeyVault/vaults@2021-10-01' = {
name: keyVaultName name: keyVaultName
@ -152,13 +168,33 @@ module autoscaleSettings 'bicep-templates/autoscale-settings.bicep' = {
name: 'autoscaleSettings' name: 'autoscaleSettings'
params: { params: {
location: location location: location
server_farm_id: serverFarms.outputs.id server_farm_id: linuxServerFarm.outputs.id
owner: owner owner: owner
workspaceId: operationalInsights.outputs.workspaceId workspaceId: operationalInsights.outputs.workspaceId
logRetention: log_retention logRetention: log_retention
autoscale_name: 'onefuzz-autoscale-${uniqueString(resourceGroup().id)}'
create_new: true
function_diagnostics_settings_name: 'functionDiagnosticSettings'
} }
} }
module autoscaleSettingsNet 'bicep-templates/autoscale-settings.bicep' = {
name: 'autoscaleSettingsNet'
params: {
location: location
server_farm_id: dotNetServerFarm.outputs.id
owner: owner
workspaceId: operationalInsights.outputs.workspaceId
logRetention: log_retention
autoscale_name: (enable_remote_debugging) ? 'onefuzz-autoscale-${uniqueString(resourceGroup().id)}-net' : 'onefuzz-autoscale-${uniqueString(resourceGroup().id)}'
create_new: enable_remote_debugging
function_diagnostics_settings_name: (enable_remote_debugging) ? 'functionDiagnosticSettings' : 'functionDiagnosticsSettingsNet'
}
dependsOn: [
autoscaleSettings
]
}
module eventGrid 'bicep-templates/event-grid.bicep' = { module eventGrid 'bicep-templates/event-grid.bicep' = {
name: 'event-grid' name: 'event-grid'
params:{ params:{
@ -182,7 +218,7 @@ resource roleAssigmentsPy 'Microsoft.Authorization/roleAssignments@2020-10-01-pr
dependsOn: [ dependsOn: [
eventGrid eventGrid
keyVault keyVault
serverFarms linuxServerFarm
] ]
}] }]
@ -196,7 +232,7 @@ resource roleAssigmentsNet 'Microsoft.Authorization/roleAssignments@2020-10-01-p
dependsOn: [ dependsOn: [
eventGrid eventGrid
keyVault keyVault
serverFarms dotNetServerFarm
] ]
}] }]
@ -211,7 +247,8 @@ resource readBlobUserAssignment 'Microsoft.Authorization/roleAssignments@2020-10
dependsOn: [ dependsOn: [
eventGrid eventGrid
keyVault keyVault
serverFarms linuxServerFarm
dotNetServerFarm
] ]
} }
@ -230,8 +267,10 @@ module pythonFunction 'bicep-templates/function.bicep' = {
location: location location: location
log_retention: log_retention log_retention: log_retention
owner: owner owner: owner
server_farm_id: serverFarms.outputs.id server_farm_id: linuxServerFarm.outputs.id
client_id: clientId client_id: clientId
use_windows: false
enable_remote_debugging: false
} }
} }
@ -249,7 +288,10 @@ module netFunction 'bicep-templates/function.bicep' = {
location: location location: location
log_retention: log_retention log_retention: log_retention
owner: owner owner: owner
server_farm_id: serverFarms.outputs.id server_farm_id: dotNetServerFarm.outputs.id
use_windows: enable_remote_debugging
enable_remote_debugging: enable_remote_debugging
} }
} }
@ -392,3 +434,5 @@ output func_key string = storage.outputs.FuncKey
output scaleset_identity string = scaleset_identity output scaleset_identity string = scaleset_identity
output tenant_id string = tenantId output tenant_id string = tenantId
output enable_remote_debugging bool = enable_remote_debugging

View File

@ -3,10 +3,12 @@ param server_farm_id string
param owner string param owner string
param workspaceId string param workspaceId string
param logRetention int param logRetention int
param autoscale_name string
param function_diagnostics_settings_name string
param create_new bool
var autoscale_name = 'onefuzz-autoscale-${uniqueString(resourceGroup().id)}'
resource autoscaleSettings 'Microsoft.Insights/autoscalesettings@2015-04-01' = { resource autoscaleSettings 'Microsoft.Insights/autoscalesettings@2015-04-01' = if (create_new) {
name: autoscale_name name: autoscale_name
location: location location: location
properties: { properties: {
@ -70,8 +72,8 @@ resource autoscaleSettings 'Microsoft.Insights/autoscalesettings@2015-04-01' = {
} }
} }
resource functionDiagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { resource functionDiagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (create_new) {
name: 'functionDiagnosticSettings' name: function_diagnostics_settings_name
scope: autoscaleSettings scope: autoscaleSettings
properties: { properties: {
logs: [ logs: [

View File

@ -6,6 +6,8 @@ param server_farm_id string
param client_id string param client_id string
param app_func_issuer string param app_func_issuer string
param app_func_audiences array param app_func_audiences array
param use_windows bool
param enable_remote_debugging bool
@secure() @secure()
param app_logs_sas_url string param app_logs_sas_url string
@ -22,19 +24,12 @@ param log_retention int
param linux_fx_version string param linux_fx_version string
resource function 'Microsoft.Web/sites@2021-03-01' = { var siteconfig = (use_windows) ? {
name: name } : {
location: location
kind: 'functionapp,linux'
tags: {
'OWNER': owner
}
identity: {
type: 'SystemAssigned'
}
properties: {
siteConfig: {
linuxFxVersion: linux_fx_version linuxFxVersion: linux_fx_version
}
var commonSiteConfig = {
alwaysOn: true alwaysOn: true
defaultDocuments: [] defaultDocuments: []
httpLoggingEnabled: true httpLoggingEnabled: true
@ -43,10 +38,29 @@ resource function 'Microsoft.Web/sites@2021-03-01' = {
http20Enabled: true http20Enabled: true
ftpsState: 'Disabled' ftpsState: 'Disabled'
} }
var extraProperties = (use_windows && enable_remote_debugging) ? {
netFrameworkVersion: 'v6.0'
remoteDebuggingEnabled: true
remoteDebuggingVersion: 'VS2022'
} : {}
resource function 'Microsoft.Web/sites@2021-03-01' = {
name: name
location: location
kind: (use_windows) ? 'functionapp' : 'functionapp,linux'
tags: {
OWNER: owner
}
identity: {
type: 'SystemAssigned'
}
properties: union({
siteConfig: union(siteconfig, commonSiteConfig)
httpsOnly: true httpsOnly: true
serverFarmId: server_farm_id serverFarmId: server_farm_id
clientAffinityEnabled: true clientAffinityEnabled: true
} }, extraProperties)
} }
resource funcAuthSettings 'Microsoft.Web/sites/config@2021-03-01' = { resource funcAuthSettings 'Microsoft.Web/sites/config@2021-03-01' = {

View File

@ -1,13 +1,18 @@
param server_farm_name string param server_farm_name string
param owner string param owner string
param location string param location string
param use_windows bool
param create bool
resource serverFarms 'Microsoft.Web/serverfarms@2021-03-01' = { var kind = (use_windows) ? 'app' : 'linux'
resource serverFarms 'Microsoft.Web/serverfarms@2022-03-01' = if (create) {
name: server_farm_name name: server_farm_name
location: location location: location
kind: 'linux' kind: kind
properties: { properties: {
reserved: true // reserved must be set to true for Linux server farm, otherwise it is false
reserved: !use_windows
} }
sku: { sku: {
name: 'P2v2' name: 'P2v2'
@ -21,3 +26,4 @@ resource serverFarms 'Microsoft.Web/serverfarms@2021-03-01' = {
} }
output id string = serverFarms.id output id string = serverFarms.id
output kind string = kind

View File

@ -163,6 +163,7 @@ class Client:
use_dotnet_agent_functions: bool, use_dotnet_agent_functions: bool,
cli_app_id: str, cli_app_id: str,
auto_create_cli_app: bool, auto_create_cli_app: bool,
host_dotnet_on_windows: bool,
): ):
self.subscription_id = subscription_id self.subscription_id = subscription_id
self.resource_group = resource_group self.resource_group = resource_group
@ -197,6 +198,7 @@ class Client:
self.use_dotnet_agent_functions = use_dotnet_agent_functions self.use_dotnet_agent_functions = use_dotnet_agent_functions
self.cli_app_id = cli_app_id self.cli_app_id = cli_app_id
self.auto_create_cli_app = auto_create_cli_app self.auto_create_cli_app = auto_create_cli_app
self.host_dotnet_on_windows = host_dotnet_on_windows
self.cli_config: Dict[str, Union[str, UUID]] = { self.cli_config: Dict[str, Union[str, UUID]] = {
"client_id": self.cli_app_id, "client_id": self.cli_app_id,
@ -630,6 +632,11 @@ class Client:
app_func_issuer = "https://sts.windows.net/%s/" % tenant_oid app_func_issuer = "https://sts.windows.net/%s/" % tenant_oid
multi_tenant_domain = {"value": ""} multi_tenant_domain = {"value": ""}
logger.info(
"template parameter enable_remote_debugging is set to: %s",
self.host_dotnet_on_windows,
)
params = { params = {
"app_func_audiences": {"value": app_func_audiences}, "app_func_audiences": {"value": app_func_audiences},
"name": {"value": self.application_name}, "name": {"value": self.application_name},
@ -641,6 +648,7 @@ class Client:
"multi_tenant_domain": multi_tenant_domain, "multi_tenant_domain": multi_tenant_domain,
"workbookData": {"value": self.workbook_data}, "workbookData": {"value": self.workbook_data},
"use_dotnet_agent_functions": {"value": self.use_dotnet_agent_functions}, "use_dotnet_agent_functions": {"value": self.use_dotnet_agent_functions},
"enable_remote_debugging": {"value": self.host_dotnet_on_windows},
} }
deployment = Deployment( deployment = Deployment(
properties=DeploymentProperties( properties=DeploymentProperties(
@ -1409,6 +1417,11 @@ def main() -> None:
help="Create a new CLI App Registration if the default app or custom " help="Create a new CLI App Registration if the default app or custom "
"app is not found. ", "app is not found. ",
) )
parser.add_argument(
"--host_dotnet_on_windows",
action="store_true",
help="Use windows runtime for hosting dotnet Azure Function",
)
args = parser.parse_args() args = parser.parse_args()
if shutil.which("func") is None: if shutil.which("func") is None:
@ -1442,6 +1455,7 @@ def main() -> None:
use_dotnet_agent_functions=args.use_dotnet_agent_functions, use_dotnet_agent_functions=args.use_dotnet_agent_functions,
cli_app_id=args.cli_app_id, cli_app_id=args.cli_app_id,
auto_create_cli_app=args.auto_create_cli_app, auto_create_cli_app=args.auto_create_cli_app,
host_dotnet_on_windows=args.host_dotnet_on_windows,
) )
if args.verbose: if args.verbose:
level = logging.DEBUG level = logging.DEBUG