Reputation: 13795
I have an Azure Functions (2.0) instance deployed by an ARM Template using Azure DevOps pipelines. I have another pipeline that deploys a functions application to the instance through zip deploy. This almost works perfectly, however, if I deploy the functions Infrastructure as Code, then deploy the app and then redeploy the Infrastructure as Code, my functions app is removed and all the functions disappear. I am using the incremental deployment so I cont see why it does this. Any thoughts on why it is behaving like this or how to troubleshoot?
I have copied my resource group deployment script and ARM template below.
New-AzureRmResourceGroupDeployment -Name ((Get-ChildItem $TemplateFile).BaseName + '-' + ((Get-Date).ToUniversalTime()).ToString('MMdd-HHmm')) `
-ResourceGroupName $ResourceGroupName `
-TemplateFile $TemplateFile `
-TemplateParameterFile $TemplateParametersFile `
-Mode Incremental `
@OptionalParameters `
-Force -Verbose `
-AdminsGroup $AdminsGroup `
-AdminsGroupObjectId $AdminsGroupObjectId `
-ErrorVariable ErrorMessages
ARM template
{
"type": "Microsoft.Web/serverfarms",
"sku": {
"name": "Y1",
"tier": "Dynamic",
"size": "Y1",
"family": "Y",
"capacity": 0
},
"kind": "app",
"apiVersion": "2016-09-01",
"name": "[variables('FunctionPlanNameMyStuff')]",
"location": "[resourceGroup().location]",
"properties": {
"name": "[variables('FunctionPlanNameMyStuff')]",
"perSiteScaling": false,
"reserved": false,
"targetWorkerCount": 0,
"targetWorkerSizeId": 0
}
},
{
"comments": "MyStuff Functions Site",
"type": "Microsoft.Web/sites",
"kind": "functionapp",
"name": "[variables('FunctionSiteNameMyStuff')]",
"apiVersion": "2016-08-01",
"location": "[resourceGroup().location]",
"identity": {
"type": "SystemAssigned"
},
"scale": null,
"properties": {
"enabled": true,
"hostNameSslStates": [
{
"name": "[concat(variables('FunctionSiteNameMyStuff'),'.azurewebsites.net')]",
"sslState": "Disabled",
"virtualIP": null,
"thumbprint": null,
"toUpdate": null,
"hostType": "Standard"
},
{
"name": "[concat(variables('FunctionSiteNameMyStuff'),'.scm.azurewebsites.net')]",
"sslState": "Disabled",
"virtualIP": null,
"thumbprint": null,
"toUpdate": null,
"hostType": "Repository"
}
],
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('FunctionPlanNameMyStuff'))]",
"reserved": false,
"siteConfig": null,
"scmSiteAlsoStopped": false,
"hostingEnvironmentProfile": null,
"clientAffinityEnabled": false,
"clientCertEnabled": false,
"hostNamesDisabled": false,
"containerSize": 1536,
"dailyMemoryTimeQuota": 0,
"cloningInfo": null
},
"resources": [
{
"apiVersion": "2015-08-01",
"name": "appsettings",
"type": "config",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', variables('FunctionSiteNameMyStuff'))]",
"[resourceId('Microsoft.Storage/storageAccounts', variables('FunctionStorageAccountMyStuff'))]"
],
"properties": {
"AzureWebJobsStorage": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('FunctionStorageAccountMyStuff'), ';AccountKey=', listKeys(variables('FunctionStorageResourceIdMyStuff'), '2017-10-01').keys[0].value)]",
"AzureWebJobsDashboard": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('FunctionStorageAccountMyStuff'), ';AccountKey=', listKeys(variables('FunctionStorageResourceIdMyStuff'), '2017-10-01').keys[0].value)]",
"WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('FunctionStorageAccountMyStuff'), ';AccountKey=', listKeys(variables('FunctionStorageResourceIdMyStuff'),'2015-05-01-preview').key1)]",
"WEBSITE_CONTENTSHARE": "[toLower(variables('FunctionSiteNameMyStuff'))]",
"FUNCTIONS_EXTENSION_VERSION": "~2",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"FUNCTION_APP_EDIT_MODE": "readwrite",
"KeyVaultUrl": "[concat('https://', variables('KeyVaultName'), '.vault.azure.net/')]",
"DeveloperMode": false
}
}
],
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('FunctionPlanNameMyStuff'))]",
"[resourceId('Microsoft.Storage/storageAccounts', variables('FunctionStorageAccountMyStuff'))]"
]
},
{
"comments": "Functions web site config",
"type": "Microsoft.Web/sites/config",
"name": "[concat(variables('FunctionSiteNameMyStuff'), '/', 'web')]",
"apiVersion": "2016-08-01",
"location": "[resourceGroup().location]",
"tags": {
},
"scale": null,
"properties": {
"numberOfWorkers": 1,
"defaultDocuments": [
"Default.htm",
"Default.html",
"Default.asp",
"index.htm",
"index.html",
"iisstart.htm",
"default.aspx",
"index.php",
"hostingstart.html"
],
"netFrameworkVersion": "v4.0",
"phpVersion": "5.6",
"pythonVersion": "",
"nodeVersion": "",
"linuxFxVersion": "",
"requestTracingEnabled": false,
"remoteDebuggingEnabled": false,
"remoteDebuggingVersion": null,
"httpLoggingEnabled": false,
"logsDirectorySizeLimit": 35,
"detailedErrorLoggingEnabled": false,
"publishingUsername": "[concat('$', variables('FunctionSiteNameMyStuff'), 'pubuser')]",
"publishingPassword": "[concat(variables('FnAppPublishingPasswordMyStuff'), uniqueString(resourceGroup().id))]",
"appSettings": null,
"metadata": null,
"connectionStrings": null,
"machineKey": null,
"handlerMappings": null,
"documentRoot": null,
"scmType": "None",
"use32BitWorkerProcess": true,
"webSocketsEnabled": false,
"alwaysOn": false,
"javaVersion": null,
"javaContainer": null,
"javaContainerVersion": null,
"appCommandLine": "",
"managedPipelineMode": "Integrated",
"virtualApplications": [
{
"virtualPath": "/",
"physicalPath": "site\\wwwroot",
"preloadEnabled": false,
"virtualDirectories": null
}
],
"winAuthAdminState": 0,
"winAuthTenantState": 0,
"customAppPoolIdentityAdminState": false,
"customAppPoolIdentityTenantState": false,
"runtimeADUser": null,
"runtimeADUserPassword": null,
"loadBalancing": "LeastRequests",
"routingRules": [],
"experiments": {
"rampUpRules": []
},
"limits": null,
"autoHealEnabled": false,
"autoHealRules": null,
"tracingOptions": null,
"vnetName": "",
"siteAuthEnabled": false,
"siteAuthSettings": {
"enabled": null,
"unauthenticatedClientAction": null,
"tokenStoreEnabled": null,
"allowedExternalRedirectUrls": null,
"defaultProvider": null,
"clientId": null,
"clientSecret": null,
"issuer": null,
"allowedAudiences": null,
"additionalLoginParams": null,
"isAadAutoProvisioned": false,
"googleClientId": null,
"googleClientSecret": null,
"googleOAuthScopes": null,
"facebookAppId": null,
"facebookAppSecret": null,
"facebookOAuthScopes": null,
"twitterConsumerKey": null,
"twitterConsumerSecret": null,
"microsoftAccountClientId": null,
"microsoftAccountClientSecret": null,
"microsoftAccountOAuthScopes": null
},
"cors": null,
"push": null,
"apiDefinition": {
"url": "[concat('https://', variables('FunctionPlanNameMyStuff'), '.azurewebsites.net/swagger/docs/v1')]"
},
"autoSwapSlotName": null,
"localMySqlEnabled": false,
"managedServiceIdentityId": null,
"ipSecurityRestrictions": null,
"http20Enabled": false,
"minTlsVersion": "1.0"
},
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('FunctionSiteNameMyStuff'))]"
]
},
Upvotes: 8
Views: 2895
Reputation: 13399
So @curiouscoder's answer does work but it requires more than a one liner really so I'm expanding on it here.
I hit this issue after adding some CORS origins to my ARM template, when I ran the template it removed the functions, to fix it you need to do the following (this assumes a Windows based function app which yours is and so is mine and that you're deploying from Azure DevOps):
The function app will now be running from the zip file rather from a deployment direct to the wwwroot folder, this means the wwwroot folder is made readonly. You'll get errors if you try to edit anything there:
The benefit of this approach is that you can't half deploy your app and having it read only means you can't accidentally mess with it once deployed.
The above does not work as smoothly as a slot change and will require the app to be restarted so it needs to be used in conjunction with a staging app or slots although as of writing the latter are still in preview for function apps.
The original github announcement is worth a read here as they're more detailed than the docs.
Upvotes: 6
Reputation: 841
Add this app setting to your template:
{ "name": "WEBSITE_RUN_FROM_PACKAGE", "value": "1" }
Functions can only be run from zip file if this setting is present, and redeploying a template without it will remove existing value for this setting (if there was any).
Upvotes: 12
Reputation: 43203
Your ARM template is problematic because it sets the App Settings as a separate action from the app creation, which is not supported when using Azure Files.
See this sample for guidance.
Upvotes: 0