2
votes

I'm trying to create a conditional resource template. The devel environment is not as beefy as the production environment and I've been successful in doing this for the most part. However, I can't seem to get nested resources right.

Here's a snippet from my ARM template:

"webApp-resources": "[variables(concat('webApp-', parameters('env'), '-resources'))]",
"webApp-dev-resources": [],
"webApp-prod-resources": [
  {
    "name": "staging",
    "type": "Microsoft.Web/sites/slots",
    "location": "[resourceGroup().location]",
    "apiVersion": "2015-08-01",
    "dependsOn": [
      "[resourceId('Microsoft.Web/sites', variables('webApp-name'))]"
    ]
  }
],

The idea is simple, the resources variable is composed using the env parameter. The env parameter can be either dev or prod and while this works, I get the following error when I try to deploy this template.

{
  "name": "[variables('webApp-name')]",
  "type": "Microsoft.Web/sites",
  ...
  "resources": "[variables('webApp-resources')]" // <- culprit!
},

The request content was invalid and could not be deserialized: 'Error converting value "[variables('webApp-resources')]" to type 'Microsoft.WindowsAzure.ResourceStack.Frontdoor.Templates.Schema.TemplateResource[]'. Path 'properties.template.resources[1].resources', line 195, position 64.'

I've also tried moving the resource into a variable and referencing the variable in a similar conditional manner, very similar to how we would do nested template linking but without the template linking.

resources: [
  "[variables('webApp-resource')]" // <- this doesn't work!
]

This resulted in a similar error but different error if I recalled correctly.

From this I've concluded that ARM template syntax is not simply find and replace which I think is bad because it does make it harder to reason about what works and what doesn't. Because if it was, this would have resulted in a valid template that would work. Which I've verified by pasting the correct value into the resources section.

Has anyone had similar problems, how did you work around the issue?

1
actually, I'm not even sure if I'm answering the right question, I don't exactly understand your problem, can you elaborate a bit? - 4c74356b41
Deployment slots are only supported by the standard and up App Service Plans, the devel environment doesn't need deployment slots so I opted to not use them. However, I now have a deployment template that needs to vary depending on which environment it is deployed into. This I've managed to do OK but I haven't been able to add the deployment slot "staging" so that this slot only exists in the prod environment. dev environment is using basic tier but prod is using standard tier. The errors in my question portrays to various (IMAO) straightforward attempts at making this happen. - John Leidegren
are you attempting to use variable instead of a resource? I'm pretty sure you can't do that, but you can create slots conditionally - 4c74356b41
@4c74356b41 I did try to use a variable as a resource, under the assumption that ARM templates simply do JSON substitutions but that didn't work. I dunno why. - John Leidegren
I had a similar issue and ended up with atomic ARM templates (eg. serviceplan, appservice, deploymentslot etc.) and couple of PowerShell modules and scripts that do the magic. - Michal Cumpl

1 Answers

4
votes

You should be able to do this without multiple template files, but not without using nested deployments. So depending on what you're trying to avoid, try this:

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "env": {
      "type": "string",
      "allowedValues": [ "dev", "prod" ]
    }
  },
  "variables": {
    "resourceArray": "[variables(concat('resources', parameters('env')))]",
    "resourcesprod": [
        {
          "name": "as",
          "type": "Microsoft.Compute/availabilitySets",
          "location": "[resourceGroup().location]",
          "apiVersion": "2015-06-15",
          "dependsOn": [],
          "properties": {
          }
        }
      ],
    "resourcesdev": []
  },
    "resources": [
      {
        "name": "nest",
        "type": "Microsoft.Resources/deployments",
        "apiVersion": "2016-09-01",
        "dependsOn": [],
        "properties": {
          "mode": "Incremental",
          "template": {
            "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
            "contentVersion": "1.0.0.0",
            "resources": "[variables('resourceArray')]"
          },
          "parameters": {
          }
        }
      }
    ],
  "outputs": {}
}