-
-
Save palmerandy/22909c79de6d1f483a727116e5a1bfd4 to your computer and use it in GitHub Desktop.
| { | |
| "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", | |
| "contentVersion": "1.0.0.0", | |
| "parameters": { | |
| "azureSubscriptionId": { | |
| "type": "string", | |
| "metadata": { | |
| "description": "The azure subscription Id. Something like 12345678-abcd-abcd-abcd-1234567890ab." | |
| } | |
| }, | |
| "appName": { | |
| "type": "string", | |
| "metadata": { | |
| "description": "The name of the Function app to be created / modified" | |
| } | |
| }, | |
| "appServicePlanName": { | |
| "type": "string", | |
| "metadata": { | |
| "description": "The name of the App Service plan that will host the Function app - this must exist already." | |
| } | |
| }, | |
| "functionsStorageAccountName": { | |
| "type": "string", | |
| "metadata": { | |
| "description": "The name of the storage account to be created / modified that will be used to power the new Function app. More details in the comment of the resource." | |
| } | |
| }, | |
| "websiteStorageAccountName": { | |
| "type": "string", | |
| "metadata": { | |
| "description": "The name of the existing storage account that the website uses as it's primary storage account (e.g. for queues and table storage)." | |
| } | |
| }, | |
| "applicationInsightsName": { | |
| "type": "string", | |
| "metadata": { | |
| "description": "The name of the existing application insight to log information." | |
| } | |
| }, | |
| "applicationInsightsLocation": { | |
| "type": "string", | |
| "metadata": { | |
| "description": "The name of the existing application insight to log information." | |
| } | |
| } | |
| }, | |
| "variables": { | |
| "functionsStorageAccountid": "[concat('/subscriptions/', parameters('subscriptionId'), '/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Storage/storageAccounts/', parameters('functionsStorageAccountName'))]", | |
| "websiteStorageAccountid": "[concat('/subscriptions/', parameters('subscriptionId'), '/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Storage/storageAccounts/', parameters('websiteStorageAccountName'))]", | |
| "slotName": "[concat(parameters('appName'), '/staging')]" | |
| }, | |
| "resources": [ | |
| { | |
| "type": "Microsoft.Storage/storageAccounts", | |
| "name": "[parameters('functionsStorageAccountName')]", | |
| "apiVersion": "2016-12-01", | |
| "location": "[resourceGroup().location]", | |
| "kind": "Storage", | |
| "sku": { | |
| "name": "Standard_LRS" | |
| }, | |
| "properties": { | |
| "supportsHttpsTrafficOnly": false, | |
| "encryption": { | |
| "keySource": "Microsoft.Storage", | |
| "services": { | |
| "blob": { | |
| "enabled": true | |
| }, | |
| "file": { | |
| "enabled": true | |
| } | |
| } | |
| }, | |
| "dependsOn": [], | |
| "comments": "This storage account is used to log to Azure Table storage and power the Monitor tab in the portal. We explicity use a seperate account, in case we want to change the SKU of websiteStorageAcccount parameter." | |
| } | |
| }, | |
| { | |
| "name": "[parameters('applicationInsightsName')]", | |
| "apiVersion": "2014-04-01", | |
| "type": "Microsoft.Insights/components", | |
| "kind": "other", | |
| "location": "[parameters('applicationInsightsLocation')]", | |
| "properties": { "applicationId": "[parameters('applicationInsightsName')]" } | |
| }, | |
| { | |
| "name": "[parameters('appName')]", | |
| "apiVersion": "2015-08-01", | |
| "type": "Microsoft.Web/sites", | |
| "kind": "functionapp", | |
| "location": "[resourceGroup().location]", | |
| "identity": { | |
| "type": "SystemAssigned" | |
| }, | |
| "properties": { | |
| "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('appServicePlanName'))]", | |
| "siteConfig": { | |
| "phpVersion": "off", | |
| "use32BitWorkerProcess": "false", | |
| "alwaysOn": "true", | |
| "remoteDebuggingEnabled": "false", | |
| "remoteDebuggingVersion": "", | |
| "webSocketsEnabled": true, | |
| "http20Enabled": true, | |
| "ftpsState": "Disabled", | |
| "appSettings": [ | |
| { | |
| "name": "FUNCTIONS_EXTENSION_VERSION", | |
| "value": "~1" | |
| }, | |
| { | |
| "name": "Project", | |
| "value": "src" | |
| } | |
| ] | |
| }, | |
| "dependsOn": [ | |
| "[resourceId('Microsoft.Web/Sites', parameters('appName'))]", | |
| "[resourceId('Microsoft.Storage/storageAccounts', parameters('functionsStorageAccountName'))]", | |
| "[resourceId('Microsoft.Insights/components', parameters('applicationInsightsName'))]" | |
| ], | |
| "comments": "This Function App will host all Azure functions." | |
| }, | |
| "resources": [ | |
| { | |
| "name": "slotConfigNames", | |
| "type": "config", | |
| "apiVersion": "2015-08-01", | |
| "dependsOn": [ | |
| "[resourceId('Microsoft.Web/Sites', parameters('appName'))]" | |
| ], | |
| "tags": { | |
| "displayName": "slotConfigNames" | |
| }, | |
| "properties": { | |
| "appSettingNames": [ | |
| "DisableAllFunctions" | |
| ] | |
| } | |
| }, | |
| { | |
| "apiVersion": "2015-08-01", | |
| "name": "appsettings", | |
| "type": "config", | |
| "dependsOn": [ | |
| "[resourceId('Microsoft.Web/Sites', parameters('appName'))]", | |
| "[resourceId('Microsoft.Storage/storageAccounts', parameters('functionsStorageAccountName'))]" | |
| ], | |
| "properties": { | |
| //Important: when adding new App Setting, you need to add them to the staging slot | |
| "DisableAllFunctions": "false", //note this setting is slot specific | |
| "AzureWebJobsStorage": "[concat('DefaultEndpointsProtocol=https;AccountName=', parameters('websiteStorageAccountName'), ';AccountKey=', listKeys(variables('websiteStorageAccountid'),'2015-05-01-preview').key1)]", | |
| "AzureWebJobsDashboard": "[concat('DefaultEndpointsProtocol=https;AccountName=', parameters('functionsStorageAccountName'), ';AccountKey=', listKeys(variables('functionsStorageAccountid'),'2015-05-01-preview').key1)]", | |
| "FUNCTIONS_EXTENSION_VERSION": "~1", | |
| "APPINSIGHTS_INSTRUMENTATIONKEY": "[reference(resourceId('Microsoft.Insights/components', parameters('applicationInsightsName')), '2014-04-01').InstrumentationKey]" | |
| } | |
| } | |
| ] | |
| }, | |
| { | |
| "apiVersion": "2016-08-01", | |
| "dependsOn": [ | |
| "[resourceId('Microsoft.Web/sites', parameters('appName'))]" | |
| ], | |
| "kind": "functionapp", | |
| "location": "[resourceGroup().location]", | |
| "name": "[variables('slotName')]", | |
| "properties": { | |
| "enabled": true, | |
| "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('appServicePlanName'))]" | |
| }, | |
| "type": "Microsoft.Web/sites/slots", | |
| "resources": [ | |
| { | |
| "name": "appsettings", | |
| "type": "config", | |
| "apiVersion": "2015-08-01", | |
| "dependsOn": [ | |
| "[resourceId('Microsoft.Web/sites/slots', variables('slotName'))]" | |
| ], | |
| "tags": { | |
| "displayName": "AppSettings" | |
| }, | |
| "properties": { | |
| //Important: when adding new App Setting, you need to add them to the production slot | |
| "DisableAllFunctions": "true", //note this setting is slot specifc | |
| "AzureWebJobsStorage": "[concat('DefaultEndpointsProtocol=https;AccountName=', parameters('websiteStorageAccountName'), ';AccountKey=', listKeys(variables('websiteStorageAccountid'),'2015-05-01-preview').key1)]", | |
| "AzureWebJobsDashboard": "[concat('DefaultEndpointsProtocol=https;AccountName=', parameters('functionsStorageAccountName'), ';AccountKey=', listKeys(variables('functionsStorageAccountid'),'2015-05-01-preview').key1)]", | |
| "FUNCTIONS_EXTENSION_VERSION": "~1", | |
| "APPINSIGHTS_INSTRUMENTATIONKEY": "[reference(resourceId('Microsoft.Insights/components', parameters('applicationInsightsName')), '2014-04-01').InstrumentationKey]" | |
| } | |
| } | |
| ] | |
| } | |
| ] | |
| } |
Thanks @delta25 - I appreciate it. I have fixed this up.
I would like to ask you a few things, so I'm going to reference a lines as groups here.
From line 89-161 it appears that you're deploying a function app with two resources. One of those resource has the type "config" and name "slotConfigNames", on lines 127-142. Lines 143-159 appear to already configure the properties. What is the purpose of this resource being defined?
Lines 162-196 deploy the staging slot for the function app. This resource deployment doesn't have the same resource defined like in the production slot on lines 127-142.
Another question...couldn't you just embed the resource defined on lines 162-196 under the existing "resources" array in the production app? According to the schema documentation for the Sites template, you can provide a "slot" resource in the Microsoft.Web/sites object.
From line 89-161 it appears that you're deploying a function app with two resources. One of those resource has the type "config" and name "slotConfigNames", on lines 127-142. Lines 143-159 appear to already configure the properties. What is the purpose of this resource being defined?
I'm not sure if I fully understand your question, but here is what each each groups of line objective:
Line 89-96 is the Function App (a type of App Service).
Line 97-118 are the Function App's properties
Lines 128-142 is the Function Apps slot configuration
Lines 143-159 is the Function App's app settings
Lines 162-196 deploy the staging slot for the function app. This resource deployment doesn't have the same resource defined like in the production slot on lines 127-142.
Yes - the point is to keep the production slot online.. This is explained in my related blog post https://andypalmer.dev/posts/automated-deployment-of-azure-functions-arm-templates/
Another question...couldn't you just embed the resource defined on lines 162-196 under the existing "resources" array in the production app? According to the schema documentation for the Sites template, you can provide a "slot" resource in the Microsoft.Web/sites object.
This sounds like it could work.
Thanks for this. Just want to point out that you have a tiny error in line 181. You're hardcoding the name 'staging' but throughout the rest of the template you're making use of a variable.