4

Is there a way, using Azure Resource Manager (ARM) templates, to deploy a storage account only if that storage account does not exist?

The below template will create:

  1. App Insights resource (shared)
  2. Storage Account (shared)
  3. App Plan
  4. App instance with configuration containing the App Insights Instrumentation Key and the Storage Account Connection String.

I would like the first two steps to be optional meaning if they already exist, just use them.

Only thing I have found so far is the pattern of newOrExisting, but that just does not make any sense. The script should be able to tell if those resource already exist and simply skip creation.

The same App Insights and Storage Account will be used by other deployment scripts so it would be nice if the template could just figure it out.

Thanks for any help!

{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
    "environmentName": {
        "type": "string",
        "defaultValue": "Dev",
        "allowedValues": [
            "Dev",
            "Test",
            "Prod"
        ]
    }
},
"variables": {
    "rgLocation": "[resourceGroup().location]",
    "insightsName": "[concat('Insights-', parameters('environmentName'))]",
    "appName": "[concat('MyAppName-', parameters('environmentName'))]",
    "genStorageName": "[concat('blgenstorage', parameters('environmentName'))]"
},
{
        "comments": "Creates a general storage account that is used to save various data, including configurations.",
        "name": "[variables('genStorageName')]",
        "type": "Microsoft.Storage/storageAccounts",
        "apiVersion": "2017-06-01",
        "sku": {
            "name": "Standard_LRS"
        },
        "kind": "Storage",
        "location": "[variables('rgLocation')]",
        "tags": {},
        "properties": {}            
    },
    {
        "comments": "Creates the service plan under which the web app will live.",
        "name": "[concat('ServicePlan-MyApp-', parameters('environment'))]",
        "type": "Microsoft.Web/serverfarms",
        "apiVersion": "2016-09-01",
        "kind": "app",
        "location": "[variables('rgLocation')]",
        "tags": {},
        "properties": {
            "name": "[concat('ServicePlan-MyApp-', parameters('environmentName'))]",
            "perSiteScaling": "false",
            "reserved": "false"
        },
        "sku": {
            "name": "S1",
            "tier": "Standard",
            "size": "S1",
            "family": "S",
            "capacity": 1
        }
    },
    {
        "comments": "Primary web app deployment.",
        "name": "[variables('appName')]",
        "type": "Microsoft.Web/sites",
        "apiVersion": "2016-08-01",
        "kind": "app",
        "location": "[variables('rgLocation')]",
        "tags": {},
        "dependsOn": [
            "[resourceId('Microsoft.Web/serverfarms', concat('ServicePlan-MyApp-', variables('envShortName')))]",
            "[resourceId('Microsoft.Storage/storageAccounts', variables('genStorageName'))]",
            "[resourceId('microsoft.insights/components', variables('insightsName'))]"
        ],
        "properties": {
            "enabled": true,
            "hostNameSslStates": [
                {
                    "name": "[concat(variables('appName'), '.azurewebsites.net')]",
                    "sslState": "Disabled"
                },
                {
                    "name": "[concat(variables('appName'), '.scm.azurewebsites.net')]",
                    "sslState": "Disabled"
                }
            ],
            "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', concat('ServicePlan-MyApp-', parameters('environmentName')))]",
            "siteConfig": {
                "numberOfWorkers": 1,
                "defaultDocuments": [
                    "Default.htm",
                    "Default.html",
                    "Default.asp",
                    "index.htm",
                    "index.html",
                    "iisstart.htm",
                    "default.aspx",
                    "index.php",
                    "hostingstart.html"
                ],
                "netFrameworkVersion": "v4.6",
                "appSettings": [
                    {
                        "name": "AppInsightsInstrumentationKey",
                        "value": "[reference(resourceId('Microsoft.Insights/components', variables('insightsName')), '2015-05-01').InstrumentationKey]"
                    }
                ],
                "connectionStrings": [
                    {
                        "name": "AzureStorage",
                        "connectionString": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('genStorageName')), '2017-06-01').keys[0].value]",
                        "type": "Custom"
                    }
                ],
                "alwaysOn": true,
                "managedPipelineMode": "Integrated",
                "virtualApplications": [
                    {
                        "virtualPath": "/",
                        "physicalPath": "site\\wwwroot",
                        "preloadEnabled": false
                    }
                ],
                "autoHealEnabled": false,
                "vnetName": ""
            },
            "microService": "WebSites",
            "clientAffinityEnabled": false,
            "clientCertEnabled": false,
            "hostNamesDisabled": false
        }
}
Saca
  • 10,355
  • 1
  • 34
  • 47
MPavlak
  • 2,133
  • 1
  • 23
  • 38

1 Answers1

3

How would you create a storage account if it exists?

Basically if an ARM Template encounters a resource its trying to deploy it will update it if the properties do not match. In your case it won't do anything (it will skip it).

4c74356b41
  • 69,186
  • 6
  • 100
  • 141
  • 1
    Deploy only if it does not exist. Currently, the script fails, it does not update resources if it already exists. – MPavlak Jun 27 '17 at 13:54
  • OK, I was hitting a wall all day yesterday and now I just got a green check. – MPavlak Jun 27 '17 at 14:03
  • glad you sorted it out – 4c74356b41 Jun 27 '17 at 14:04
  • 3
    It is actually possible to do conditional/logic now https://azure.microsoft.com/en-ca/blog/create-flexible-arm-templates-using-conditions-and-logical-functions/ – Shane Courtrille Jun 25 '18 at 21:26
  • has nothing to do with conditional logic, you dont need a conditional logic to not update the resource if it exists, because you cant really do that without a hach and it goes against the whole idea behind infrastructure as code – 4c74356b41 Jun 16 '20 at 15:42
  • There are some scenarios where you don't want to run the ARM template if the resource exists. For example, KeyVault, the ARM template requires you to specify the access policy array, meaning that any deployment of the key vault resource will override all your access policies. That's not desirable, so the least evil is to only deploy KeyVault if the resource doesn't exist, that way I'm able to still add/update secrets, keys and other access policies. – mdarefull Nov 08 '21 at 21:58
  • you can just remove the `accessPolicies` property from the template and add them as separate resources – 4c74356b41 Nov 10 '21 at 05:13