3
votes

I am working on ARM templates for some web application deployments. These templates set up a web application along with a staging slot for this application. The way I wish to handle this is to only deploy the app settings to the staging slot. By doing this I can handle rollbacks nicely as the app settings will swap with the slot and have any old values tied to the app they were deployed with. However upon deploying these ARM templates successfully I can see there are no app settings deployed to my staging slots other than website_node_default_version.

Below is a snippet of the ARM templates showing one pair of web app + staging slot:

{
        "type": "Microsoft.Web/sites",
        "apiVersion": "2016-08-01",
        "name": "[variables('egressAppName')]",
        "location": "[parameters('location')]",
        "kind": "app",
        "properties": {
            "enabled": true,
            "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]",
            "clientAffinityEnabled": true
        }
    },
    {
        "type": "Microsoft.Web/sites/slots",
        "apiVersion": "2016-08-01",
        "name": "[concat(variables('egressAppName'),'/','staging')]",
        "location": "[parameters('location')]",
        "dependsOn": [
            "[resourceId('Microsoft.Web/sites', variables('egressAppName'))]"
        ],
        "kind": "app",
        "properties": {
            "enabled": true,
            "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]",
            "clientAffinityEnabled": true,
            "appSettings": [
                {
                    "name": "APP_INSIGHTS_INSTRUMENTATION_KEY",
                    "value": "[reference(resourceId(variables('rsg') ,'microsoft.insights/components/', variables('ainName')), '2015-05-01').InstrumentationKey]"
                },
                {
                    "name": "ASPNETCORE_ENVIRONMENT",
                    "value": "[parameters('netCoreEnvironment')]"
                },
                {
                    "name": "MONITOR_API_ACCOUNT_RATE_LIMIT",
                    "value": "[parameters('accountRateLimit')]"
                },
                {
                    "name": "MONITOR_API_ACCOUNT_RATE_LIMIT_WINDOW_SECONDS",
                    "value": "[parameters('accountLimitWindow')]"
                },
                {
                    "name": "MONITOR_API_IP_RATE_LIMIT",
                    "value": "[parameters('ipLimit')]"
                },
                {
                    "name": "MONITOR_API_IP_RATE_LIMIT_WINDOW_SECONDS",
                    "value": "[parameters('ipLimitWindow')]"
                },
                {
                    "name": "MONITOR_DATA_EXPLORER_INSTANCE_NAME",
                    "value": "[variables('dataExplorerName')]"
                },
                {
                    "name": "MONITOR_DATA_EXPLORER_REGION",
                    "value": "[parameters('location')]"
                },
                {
                    "name": "MONITOR_DIAG_ACCOUNT_APP_ID",
                    "value": "[parameters('diagAccountAppID')]"
                },
                {
                    "name": "MONITOR_DIAG_ACCOUNT_APP_SECRET_LOCATION",
                    "value": "[parameters('diagAccountAppSecret')]"
                },
                {
                    "name": "MONITOR_EGRESS_APP_TENANT",
                    "value": "[parameters('egressTenantID')]"
                },
                {
                    "name": "MONITOR_KEY_VAULT_APP_ID",
                    "value": "[parameters('keyVaultAppID')]"
                },
                {
                    "name": "MONITOR_KEY_VAULT_APP_SECRET",
                    "value": "[parameters('keyVaultAppSecret')]"
                },
                {
                    "name": "MONITOR_KEY_VAULT_NAME",
                    "value": "[variables('keyVaultName')]"
                },
                {
                    "name": "MONITOR_PGSQL_CONNECTION_STRING",
                    "value": "[parameters('postgresConnectionString')]"
                },
                {
                    "name": "MONITOR_TOKEN_VALIDATION_CLOCK_SKEW_SECONDS",
                    "value": "[parameters('validationClockSkew')]"
                },
                {
                    "name": "WEBSITE_RUN_FROM_PACKAGE",
                    "value": "1"
                }
            ]
        }
    }

I have tried deleting just the staging slots and redeploying as well as deleting all the web apps and redeploying with no luck. At this point I'm just hoping to get more eyes over this to see if I've missed anything obvious. I'm deploying these ARM templates through Azure DevOps release pipelines using the Azure Resource Group Deployment task.

1
By not applying the appsettings in the production slot a redeploy of the ARM will not delete the appsettings, right? I am currently investigating this pattern anf maybe want to apply it but I need to be sure that a redeploy will never delete the appsettings in the production slot.mslot
@mslot Yes this is correct. My knowledge of ARM templates is that they are non destructive and will not touch something not defined in the template. Because App settings are technically a separate config resource if they are created outside of the ARM template or as in this flow swapped into production, redeploying the ARM template will not overwrite them. I have been experimenting with leaving app settings out of ARM templates completely and deploying them with the "Azure App Service Settings" task in Azure DevOps and would recommend this with the same flow as above (deploying them to a slot)David Parsonson
Thanks. I have also experimented a lot with this. I need to handle rollback and I need to not restart production slot when a new setting is added. I think the "non destructive" is a bit hard to understand because technically the appsettings object resides under the siteconfig which can contain other properties. So if it doesn't contain appsettings, but another property, I would think it would delete the appsettings. It looks like the destruction is applied down to property level of the ARM json object. I didn't know of the DevOps task. Thanks for that.mslot

1 Answers

2
votes

The appSettings should be defined in the SiteConfig object instead of Microsoft.Web/sites/slots properties as your template. To create a Microsoft.Web/sites/slots/config resource for app settings, you could add the JSON to the resources section of your template.

Also, you can see the Monitoring and diagnostic settings could be swapped here. enter image description here