Search code examples
azureazure-devopsazure-rm-template

How to deploy a resource in a secondary location in an Azure Resource Manager Template when it is unavailable in the primary location?


I have an ARM template that is used to create resources in the location of a given Resource Group. Here is how I can deploy a SignalR service:

    {
        "apiVersion": "2018-10-01",
        "name": "[variables('signalRName')]",
        "type": "Microsoft.SignalRService/signalR",
        "location": "[resourceGroup().location]",
        "tags": {},
        "sku": {
            "name": "Free_F1",
            "tier": "Free"
        },
        "properties": { }
   }

Being in Canada, I have access to two locations: Canada East and Canada Central. However SignalR that is not available in Canada Central yet but it is in Canada East:

ew-AzResourceGroupDeployment: 11:40:32 AM - Error: Code=LocationNotAvailableForResourceType; Message=The provided location 'canadacentral' is not available for resource type 'Microsoft.SignalRService/SignalR'. List of available regions for the resource type is 'eastus,westus,southeastasia,westeurope,westus2,eastus2,northeurope,australiaeast,canadaeast,centralus,japaneast,uksouth,southcentralus,brazilsouth,francecentral,koreacentral'.

Question

What can I do to deploy the resource unavailable in the primary location into some secondary / fallback location?


Solution

  • I have found a way to achieve it at the expense of few tweaks. First, I have to specify myself a secondary location parameter in my parameters file.

    For instance, in the following parameters file, I specified Canada Central as a primary location and Canada East as a secondary location:

        {
            "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
            "contentVersion": "1.0.0.0",
            "parameters": {
                "primaryLocation": {
                    "value": "Canada Central"
                },
                "secondaryLocation": {
                    "value": "Canada East"
                }
                ...
            }
        }
    

    This parameter is defined in my deploy template file:

        {
            "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
            "contentVersion": "1.0.0.0",
            "parameters": {
                "primaryLocation": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 32
                }
                "secondaryLocation": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 32
                }
            }
            ... }
    

    Then I found out about the providers statement. This statement returns the list of locations available of a given resource type.

    So I updated the location property to look for the resource group's location in the list of locations available for SignalR. If it is contained in the list, then I use resource group's location. Otherwise, I use the secondary location provided.

        {
            "apiVersion": "2018-10-01",
            "name": "[variables('signalRName')]",
            "type": "Microsoft.SignalRService/signalR",
            "location": "[if(contains(providers('Microsoft.SignalRService', 'signalR').locations, parameters('primaryLocation')), parameters('primaryLocation'), parameters('secondaryLocation'))]",
            "tags": {},
            "sku": {
                "name": "Free_F1",
                "tier": "Free"
            },
            "properties": { }
        }
    

    Note

    I can't use resourceGroup().location because it does not return the location in the same format as providers('Microsoft.SignalRService', 'signalR').locations. The first one will return something like canadaeast whereas the second returns Canada East.