0
votes

I'm trying to use this Azure Resource Manager template code snippet to add a custom domain to set of webapps. The web apps are being created correctly, as is the traffic manager profile. However, the ARM template is failing when adding the custom hostnames. Note that I'm using a variable parameter that is passed into the template to create the websites.

    {
      "name": "[concat(parameters('webAppNamePrefix'), '-', uniqueString(resourceGroup().id), '-site-', copyIndex())]",
      "type": "Microsoft.Web/sites",
      "kind": "app,linux,container",
      "location": "[parameters('webAppLocations')[copyIndex()]]",
      "apiVersion": "2016-08-01",
      "copy": {
        "count": "[length(parameters('webAppLocations'))]",
        "name": "siteCopy"
      },
      "dependsOn": [
        "farmCopy"
      ],
      "resources": [
        {
          "name": "appsettings",
          "type": "config",
          "apiVersion": "2016-08-01",
          "dependsOn": [
            "[concat(parameters('webAppNamePrefix'), '-', uniqueString(resourceGroup().id), '-site-', copyIndex())]"
          ],
          "tags": {
            "displayName": "Application settings"
          },
          "properties": {
            "publishingUsername": "[variables('publishingUsername')]",
            "DOCKER_CUSTOM_IMAGE_NAME": "[parameters('dockerImageName')]"
          }
        }
      ],
      "tags": {
        "[concat('hidden-related:', resourceId('Microsoft.Web/serverfarms', concat(parameters('webAppNamePrefix'), '-', uniqueString(resourceGroup().id))), '-', copyIndex())]": "Resource",
        "displayName": "[concat(parameters('webAppNamePrefix'), '-', uniqueString(resourceGroup().id), '-site-', copyIndex())]"
      },
      "properties": {
        "name": "[concat(parameters('webAppNamePrefix'), '-', uniqueString(resourceGroup().id), '-site-', copyIndex())]",
        "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', concat(parameters('webAppNamePrefix'), '-', uniqueString(resourceGroup().id), '-', copyIndex()))]"
      }
    },
    {
      "type": "Microsoft.Web/sites/hostnameBindings",
      "name": "[concat(parameters('webAppNamePrefix'), '-', uniqueString(resourceGroup().id), '-site-', copyIndex(), '/', parameters('customHostname'))]",
      "apiVersion": "2016-08-01",
      "location": "[resourceGroup().location]",
      "properties": {
      },
      "dependsOn": [
        "[concat('Microsoft.Web/sites/',parameters('webAppNamePrefix'), '-', uniqueString(resourceGroup().id), '-site-', copyIndex(), '/', parameters('customHostname'))]"
      ]
    }

2018-03-20T23:50:20.7707394Z ##[error]Deployment template validation failed: 'The template resource '[concat(parameters('webAppNamePrefix'), '-', uniqueString(resourceGroup().id), '-site-', copyIndex(), '/', parameters('customHostname'))]' at line '1' and column '2892' is not valid: The template function 'copyIndex' is not expected at this location. The function can only be used in a resource with copy specified. Please see https://aka.ms/arm-copy for usage details.. Please see https://aka.ms/arm-template-expressions for usage details.'.
2018-03-20T23:50:20.7723109Z ##[error]Task failed while creating or updating the template deployment.

Note that the copyIndex() works fine for the website names elsewhere in the template. So why isn't it working for the "Microsoft.Web/sites/hostnameBindings" section? I'm stumped.

Here are the parameters. Note the webAppLocations parameter which is an array.

"parameters": {
    "webAppNamePrefix": {
      "type": "string",
      "minLength": 1
    },
    "dockerImageName": {
      "type": "string",
      "metadata": {
        "description": "Name of docker image to use"
      }
    },
    "farmSkuName": {
      "type": "string",
      "metadata": {
        "description": "Describes plan's pricing tier and capacity. Check details at https://azure.microsoft.com/en-us/pricing/details/app-service/"
      }
    },
    "environmentType": {
      "type": "string",
      "allowedValues": [
        "dev",
        "qa",
        "prod"
      ],
      "metadata": {
        "description": "Environment type name"
      }
    },
    "webAppLocations": {
      "type": "array"
    },
    "trafficManagerPrefix": {
      "type": "string"
    },
    "customHostname": {
      "type": "string",
      "metadata": {
          "description": "The custom hostname that you wish to add."
      }
    }    
  },
1

1 Answers

1
votes

You should never really place anything after resources property, not because it breaks the template, but because its much harder to look at it. in your case you placed Microsoft.Web/sites/hostnameBindings outside of resources.

{
    "name": "[concat(parameters('webAppNamePrefix'), '-', uniqueString(resourceGroup().id), '-site-', copyIndex())]",
    "type": "Microsoft.Web/sites",
    "kind": "app,linux,container",
    "location": "[parameters('webAppLocations')[copyIndex()]]",
    "apiVersion": "2016-08-01",
    "copy": {
        "count": "[length(parameters('webAppLocations'))]",
        "name": "siteCopy"
    },
    "dependsOn": [
        "farmCopy"
    ],
    "tags": {
        "[concat('hidden-related:', resourceId('Microsoft.Web/serverfarms', concat(parameters('webAppNamePrefix'), '-', uniqueString(resourceGroup().id))), '-', copyIndex())]": "Resource",
        "displayName": "[concat(parameters('webAppNamePrefix'), '-', uniqueString(resourceGroup().id), '-site-', copyIndex())]"
    },
    "properties": {
        "name": "[concat(parameters('webAppNamePrefix'), '-', uniqueString(resourceGroup().id), '-site-', copyIndex())]",
        "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', concat(parameters('webAppNamePrefix'), '-', uniqueString(resourceGroup().id), '-', copyIndex()))]"
    },
    "resources": [
        {
            "name": "appsettings",
            "type": "config",
            "apiVersion": "2016-08-01",
            "dependsOn": [
                "[concat(parameters('webAppNamePrefix'), '-', uniqueString(resourceGroup().id), '-site-', copyIndex())]"
            ],
            "tags": {
                "displayName": "Application settings"
            },
            "properties": {
                "publishingUsername": "[variables('publishingUsername')]",
                "DOCKER_CUSTOM_IMAGE_NAME": "[parameters('dockerImageName')]"
            }
        },
        {
            "type": "hostnameBindings",
            "name": "[parameters('customHostname')]",
            "apiVersion": "2016-08-01",
            "location": "[resourceGroup().location]",
            "properties": {},
            "dependsOn": [
                "[concat('Microsoft.Web/sites/',parameters('webAppNamePrefix'), '-', uniqueString(resourceGroup().id), '-site-', copyIndex(), '/', parameters('customHostname'))]"
            ]
        }
    ]
}