15

Looking to get some guidance and explanation around dependsOn.

I have seen in templates there are two methods of providing dependencies in a template.

One method is to provide resourceId and the other method is to provide a string value using concat. I'm trying to understand the difference between the two.

Example

[concat('Microsoft.Network/networkInterfaces/', variables('networkInterfaceName'))]

and also on some examples, this is referenced with resourceId:

[resourceId('Microsoft.Compute/virtualMachines', parameters('virtualMachineName'))]

I am looking to understand the difference and also in which scenarios we should use concat to reference dependencies and where we can use resourceID

Kzryzstof
  • 7,688
  • 10
  • 61
  • 108
WS2012R2
  • 159
  • 1
  • 1
  • 3

3 Answers3

14

The real difference between when you use resourceId or not (in dependsOn) is this: Is the resource you depend on in the same template? If so, you can simply just have the name. For example, here is a load balancer, which depends on a public IP and a vNet that are created in the same template:

  "apiVersion": "[variables('lbApiVersion')]",
  "type": "Microsoft.Network/loadBalancers",
  "name": "[variables('lbName1')]",
  "location": "[variables('computeLocation')]",
  "dependsOn": [
    "[variables('lbIPName1')]",
    "[variables('virtualNetworkName')]"
  ],
  "properties": {
    "frontendIPConfigurations": [
      {
        "name": "LoadBalancerIPConfig",
        "properties": {
          "publicIPAddress": {
            "id": "[resourceId('Microsoft.Network/publicIPAddresses', variables('lbIPName1'))]"
          }

If you are referencing a resource from outside the template, then you need resourceId. This is not needed with dependsOn, as you can only depend on resources that are in the same template. Where it is needed in my example, is the publicIPAddress id. This property needs a full resource Id, which is what the resourceId function provides. So the question becomes, does that property need a full resource Id?

Edward Rixon
  • 1,199
  • 1
  • 17
  • 31
  • Thank you. Using nested templates, I was getting the error "abc...doesn't depend on parent resource abc... ...Please add dependency explicitly using the 'dependsOn' syntax...". Although the VM is created in the same template, to resolve, I was trying to fully qualify the resource where I had to actually reduce the qualification. All I needed to do was replace "[resourceId('Microsoft.Compute/virtualMachines/', variables('vmName'))]" with "[variables('vmName']". – woter324 May 18 '17 at 13:14
  • 1
    this is not true, or not entirely true. if you have 2 resources with the same name in the same deployment this wont work – 4c74356b41 Dec 14 '18 at 17:34
  • Is this really the case? When trying to reference any resource from outside the template using `resourceId` I get `The resource 'XXXXX' is not defined in the template` – Cocowalla May 12 '20 at 13:25
  • without trying it out myself, I'm not sure, plus I haven't used arm templates at all in a couple years. And without seeing your template and rg etc, it could be a variety of reasons. it could be a wrong name, it could be that its in a different resource group, so you need more qualifier, etc... but I assure you at time of writing, this was definitely correct. – Edward Rixon May 13 '20 at 14:12
  • documentation of resourceId explains it well https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/template-functions-resource#resourceid – Edward Rixon May 13 '20 at 14:18
8

The other answer in this thread is misleading, to say the least.

It does not matter which route you take to actually supply the value to the dependsOn (or any other property) of the template. Hell, you can just put a string there

"dependsOn" [
    "/subscription/GUID/resourceGroups/rgName/provider/providerName/resource/resourceName"
]

obviously, this is a bad idea, but it illustrated the point. you just need to return a VALID resource identifier, you can construct it in any way (or you can pass it in as a variable when provisioning with a script).

Also, sometimes resourceId can't work when you are using nested resource, so you need to concatenate 3 variables, in that case concat can help.

And nothing prevents you from nesting one inside the other:

"[concat(resourceId('Microsoft.Compute/virtualMachines', parameters('virtualMachineName'), 'SOME TEXT'))]

TLDR you can use any way you like to return a valid resource identifier.

ps: example of a "broken" resourceId that would work normally:

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "resources": [
        {
            "type": "Microsoft.Resources/deployments",
            "apiVersion": "2017-05-10",
            "name": "nestedTemplate",
            "resourceGroup": "xxx",
            "properties": {
                "mode": "Incremental",
                "template": {
                    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
                    "contentVersion": "1.0.0.0",
                    "resources": [
                        {
                            "type": "Microsoft.Storage/storageAccounts",
                            "apiVersion": "2017-06-01",
                            "name": "egw4y35hthrh35h24tz1",
                            "location": "eastus",
                            "sku": {
                                "name": "Standard_LRS"
                            },
                            "tags": {
                                "test": "[resourceId('Microsoft.Storage/storageAccounts', 'test')]"
                            },
                            "kind": "Storage",
                            "properties": {}
                        }
                    ]
                }
            }
        }
    ]
}

this has to be a subscription level deployment

4c74356b41
  • 69,186
  • 6
  • 100
  • 141
  • Understood. Is it possible to add such an example or link to the answer where resourceId() cannot be used to get resourceId of a resource? That will clearly differentiate between use cases of both functions. – stackoverflowusrone Mar 08 '20 at 05:40
  • This answer is mistaken. There are two different types of dependency; one using a resource id (however defined), and one using the name by which the resource will be deployed _in the same arm template_. In the resource id case, all that gets checked is that the resource exists; in the resource name case, it finishes doing the creation/update of the resource before going on to the dependent resource. That makes a real difference when updating existing resources with new properties. – Vince Bowdren Oct 07 '21 at 13:55
  • you cant depend on a resource that already exists, it makes no sense, how would you use it to produce a graph of dependencies? dependsOn has nothing to do with updating a resource. nothing is wrong with the answer, the only real reason to use resourceId vs the name of the resource - you can have 2 different resource types with the same name, then the name reference won't work – 4c74356b41 Oct 08 '21 at 17:28
1

Difference:

concat: Combines multiple string values and returns the concatenated string.

resourceId: Returns the unique identifier of a resource.

Example "[concat('Microsoft.Network/networkInterfaces/', variables('networkInterfaceName'))]"

Result: Microsoft.Network/networkInterfaces/{networkInterfaceName}

Example: [resourceId('Microsoft.Compute/virtualMachines', parameters('virtualMachineName'))]",

Result: /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/{Microsoft.Compute/virtualMachines}/{networkInterfaceName}/

More Functions in the ARM template please refer to document.

Tom Sun - MSFT
  • 24,161
  • 3
  • 30
  • 47
  • 1
    Thanks for posting. But i'm trying to understand why in some instances we use Concat under dependancies (Dependson) and why we use ResourceID in some instances ? this is my confusion – WS2012R2 Mar 09 '17 at 02:31
  • I have updated the answer. If we want to deploy a resource, then we need to supply the resourceId, although we can concat multiple string, but we can easily get it by using resourceId function – Tom Sun - MSFT Mar 09 '17 at 02:34
  • Thanks. so does it mean that if I need to reference an object outside of my subscription, I MUST use Resource ID and if it's a resource in my subscription I can use either ResourceID or Concat ? From what I can see Concat doesn't have the subscription ID / Resource Group info etc, which means I think it has to be in the same resource group as well ? – WS2012R2 Mar 09 '17 at 02:41
  • Concat is not used for reference resource, just combine the multiple string values. If we want to deploy the resource we need to select which subscription to deploy. – Tom Sun - MSFT Mar 09 '17 at 02:49