1

I'm trying to conditionally provide resource property values through translation of runtime resource properties within a copyIndex loop..

Upon deploying the following ARM template, I receive the error:

Unable to process template language expressions for resource '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Compute/virtualMachines/{vm-name}/extensions/Microsoft.EnterpriseCloud.Monitoring' at line '30' and column '10'. 'The template resource '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Compute/virtualMachines/{vm-name}' is not found.' (Code: InvalidTemplate)

"type": "[variables('extensionType')[reference(concat('Microsoft.Compute/virtualMachines/', parameters('virtualMachines')[copyIndex()].name)).storageProfile.osDisk.osType]]",

However, the VM exists with the ID it provides, so it doesn't make sense that the engine cannot find it. If I hard-code the Extension Type, there are no errors and the Extension is installed on the VM with the same ID.

Unfortunately, I don't know if this is a bug within ARM or if I'm just doing something wrong..

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "workspaceResourceId": { "type": "string" },
        "virtualMachines": { "type": "array" }
    },
    "variables": {
        "extensionType": {
        "Windows": "MicrosoftMonitoringAgent",
        "Linux": "OmsAgentForLinux"
        }
    },
    "resources": [
        {
        "copy": {
            "name": "VMMonitoringExtensionsCopy",
            "count": "[length(parameters('virtualMachines'))]"
        },
        "type": "Microsoft.Compute/virtualMachines/extensions",
        "apiVersion": "2015-05-01-preview",
        "location": "[parameters('virtualMachines')[copyIndex()].location]",
        "name": "[concat(parameters('virtualMachines')[copyIndex()].name, '/Microsoft.EnterpriseCloud.Monitoring')]",
        "properties": {
            "publisher": "Microsoft.EnterpriseCloud.Monitoring",
            "type": "[variables('extensionType')[reference(concat('Microsoft.Compute/virtualMachines/', parameters('virtualMachines')[copyIndex()].name)).storageProfile.osDisk.osType]]",
            "typeHandlerVersion": "1.0",
            "autoUpgradeMinorVersion": true,
            "settings": {
            "workspaceId": "[reference(parameters('workspaceResourceId'), '2015-11-01-preview').customerId]"
            },
            "protectedSettings": {
            "workspaceKey": "[listKeys(parameters('workspaceResourceId'), '2015-11-01-preview').primarySharedKey]"
            }
        }
        }
    ]
}

The object array being passed in for virtualMachines looks like this:

[
    { "name": "vm-name", "location": "azure-region" }
]
JoeBrockhaus
  • 2,745
  • 2
  • 40
  • 64

1 Answers1

0

A couple things you can try:

1) Assuming the VM is not defined in the same template try using the "full" resourceId in the reference function. See the last example in this doc: https://azure.microsoft.com/en-us/documentation/articles/resource-group-template-functions/#reference - it seems like the error already knows the full resourceId, but it's worth trying

2) the other thought is that the reference function is evaluated at runtime and the resource provider doesn't like the expression but that's a swag.

I will do some more poking and see if we can't nail this down.

bmoore-msft
  • 8,376
  • 20
  • 22
  • I already tried #1 - using `resourceId()` - and got the same error. I could very well use a linked 'function' template (with `"resources": [ ]`) to accomplish this, though I'm not keen on having to host that helper template publicly. – JoeBrockhaus May 26 '16 at 19:02
  • Generally speaking, I didn't expect the `parameter['property-name']` indexing to work, except that I assumed it was based on javascript and name indexing objects is native. Hopefully this is a feature that was purposeful, and this is just an edge case for a less-commonly-used feature :) – JoeBrockhaus May 26 '16 at 19:05
  • ok, re: hosting the template in a public location, you don't have to, you can secure it via a sasToken as an option. This repo has a sample of what that looks like (see the nested template example). https://github.com/bmoore-msft/AzureRM-Samples if that doesn't help, feel free to email me bmoore at microsoft and we can talk through it... – bmoore-msft May 27 '16 at 22:26
  • we've looked at doing that, but it's just one more thing to manage from a devops perspective & another thing we'd have to automate, however. Supporting linked templates is on the roadmap, but not something we're undertaking at the moment. We've also learned a bit more about the cycles of the Linux vs Windows agents & extensions, and in this case it makes sense for us to use separate templates anyway. – JoeBrockhaus May 28 '16 at 00:41
  • Do you know if this usage (of indexing an object by property name) is intended to be supported? Seems like something that should be possible. Should I submit this on UserVoice as an req/bug? – JoeBrockhaus May 28 '16 at 00:51
  • 1
    I think what you're running into is related to the reference() function in the type property - and the pre-validation of the template. IOW, I don't think it's indexing but either way doesn't help at the moment. I've started an internal thread, but to keep us honest, please do file a UV/bug and post back a link. – bmoore-msft May 31 '16 at 15:26
  • Ok, looks like it might be 2 things... 1) since the reference() is looking at something not in the template, you do need the apiVersion parameter and 2) indexing the object by name is not supported - so you could throw that on UV as needed. – bmoore-msft Jun 01 '16 at 17:07