Search code examples
azureazure-functionsazure-resource-manager

(400) Bad Request when deploying a Function App via ARM


Hopefully, someone can tell me what I'm doing wrong with this ARM template deployment.

Using the template at the bottom of the question, I can deploy a Function App - with app service plan and storage account - but I get the following error.

STATUS              BadRequest
PROVISIONING STATE  Failed
TIMESTAMP           4/19/2017, 1:33:00 PM
DURATION            1 second
TYPE                Microsoft.Web/sites/config
RESOURCE ID         /subscriptions/blah-blah-blah/resourceGroups/blah/providers/Microsoft.Web/sites/functionname/config/appsettings
STATUSMESSAGE       {
                        "Code": "BadRequest",
                        "Message": "There was a conflict. The remote server returned an error: (400) Bad Request.",
                        "Target": null,
                        "Details": [
                        {
                            "Message": "There was a conflict. The remote server returned an error: (400) Bad Request."
                        },
                        {
                            "Code": "BadRequest"
                        },
                        {
                            "ErrorEntity": {
                                "ExtendedCode": "01020",
                                "MessageTemplate": "There was a conflict. {0}",
                                "Parameters": [
                                    "The remote server returned an error: (400) Bad Request."
                                ],
                                "Code": "BadRequest",
                                "Message": "There was a conflict. The remote server returned an error: (400) Bad Request."
                            }
                        }],
                        "Innererror": null
                    }
RESOURCE            functionname/appsettings

If I remove this AppSetting property from the function app part of the template then the deployment works fine.

"WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('Storage_Account_Name'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('Storage_Account_Name')),'2015-05-01-preview').key1)]",

But then when I go to the deployed function app I get this error popup.

Error:

'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING' application setting is missing from your app. This setting contains a connection string for an Azure Storage account that is used to host your functions content. Your app will be completely broken without this setting. You may need to delete and recreate this function app if you no longer have access to the value of that application setting.

I also note that if I try and add that appsetting in the portal manually after this successful deployment, I get the same error as the initial deployment.

So, I don't know if I'm putting it in the template incorrectly, or if something in the Azure Deployment for functions apps is broken.

Where am I going wrong?

Template

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "App_Service_Plan_Name": {
            "defaultValue": "aspname",
            "type": "String"
        },
        "Functions_App_Name": {
            "defaultValue": "funcname",
            "type": "String"
        },
        "Storage_Account_Name": {
            "defaultValue": "storagename",
            "type": "String"
        }
    },
    "variables": {},
    "resources": [
        {
            "comments": "Deployed from template",
            "type": "Microsoft.Storage/storageAccounts",
            "name": "[parameters('Storage_Account_Name')]",
            "apiVersion": "2016-01-01",
            "sku": {
                "name": "Standard_LRS"
            },
            "location": "[resourceGroup().location]",
            "kind": "Storage"
        },
        {
            "comments": "Deployed from template",
            "type": "Microsoft.Web/serverfarms",
            "sku": {
                "name": "Y1",
                "tier": "Dynamic",
                "size": "Y1",
                "family": "Y",
                "capacity": 0
            },
            "kind": "functionapp",
            "name": "[parameters('App_Service_Plan_Name')]",
            "apiVersion": "2015-08-01",
            "location": "[resourceGroup().location]",
            "properties": {
                "name": "[parameters('App_Service_Plan_Name')]",
                "numberOfWorkers": 0
            },
            "dependsOn": []
        },
        {
            "comments": "Deployed from template",
            "type": "Microsoft.Web/sites",
            "kind": "functionapp",
            "name": "[parameters('Functions_App_Name')]",
            "apiVersion": "2015-08-01",
            "location": "[resourceGroup().location]",
            "properties": {
                "name": "[parameters('Functions_App_Name')]",
                "hostNames": [
                    "[concat(parameters('Functions_App_Name'),'.azurewebsites.net')]"
                ],
                "enabledHostNames": [
                    "[concat(parameters('Functions_App_Name'),'.azurewebsites.net')]",
                    "[concat(parameters('Functions_App_Name'),'.scm.azurewebsites.net')]"
                ],
                "hostNameSslStates": [
                    {
                        "name": "[concat(parameters('Functions_App_Name'),'.azurewebsites.net')]",
                        "sslState": 0,
                        "thumbprint": null,
                        "ipBasedSslState": 0
                    },
                    {
                        "name": "[concat(parameters('Functions_App_Name'),'.scm.azurewebsites.net')]",
                        "sslState": 0,
                        "thumbprint": null,
                        "ipBasedSslState": 0
                    }
                ],
                "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('App_Service_Plan_Name'))]"
            },
            "dependsOn": [
                "[resourceId('Microsoft.Web/serverfarms', parameters('App_Service_Plan_Name'))]",
                "[resourceId('Microsoft.Storage/storageAccounts', parameters('Storage_Account_Name'))]"
            ],
            "resources": [
                {
                    "apiVersion": "2015-08-01",
                    "name": "appsettings",
                    "type": "config",
                    "dependsOn": [
                        "[resourceId('Microsoft.Web/Sites', parameters('Functions_App_Name'))]",
                        "[resourceId('Microsoft.Storage/storageAccounts', parameters('Storage_Account_Name'))]"
                    ],
                    "properties": {
                        "FUNCTIONS_EXTENSION_VERSION": "~1",
                        "AzureWebJobsDashboard": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('Storage_Account_Name'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('Storage_Account_Name')),'2015-05-01-preview').key1)]",
                        "AzureWebJobsStorage": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('Storage_Account_Name'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('Storage_Account_Name')),'2015-05-01-preview').key1)]",
                        "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('Storage_Account_Name'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('Storage_Account_Name')),'2015-05-01-preview').key1)]",
                        "WEBSITE_CONTENTSHARE": "[concat(parameters('Functions_App_Name'),'_files')]",
                        "WEBSITE_NODE_DEFAULT_VERSION": "6.5.0"
                    }
                },
                {
                    "apiVersion": "2015-08-01",
                    "name": "web",
                    "type": "config",
                    "dependsOn": [
                        "[resourceId('Microsoft.Web/Sites', parameters('Functions_App_Name'))]",
                        "[resourceId('Microsoft.Storage/storageAccounts', parameters('Storage_Account_Name'))]"
                    ],
                    "properties": {
                        "cors": {
                            "allowedOrigins": [
                                "[concat('https://',parameters('Storage_Account_Name'),'.blob.core.windows.net')]"
                            ]
                        }
                    }
                }
            ]
        }
    ]
}

Solution

  • So typically, after spending a day or so trying to find out what's wrong before breaking down and resorting to asking SO, as soon as I do I find out what's wrong.

    The issue is not the WEBSITE_CONTENTAZUREFILECONNECTIONSTRING but the WEBSITE_CONTENTSHARE. This has an underscore in it and underscores are not allowed in the naming convention of Storage Account File shares.

    So, mental note, when I see an error like There was a conflict..., think ...with a naming convention, not ...with an existing resource.

    I did also have to add the 3 Azure URLs to the CORS AllowedOrigins section

    "https://functions.azure.com",
    "https://functions-staging.azure.com",
    "https://functions-next.azure.com"