Can I have an ARM template resource with a COPY array from 0 to N

I am deploying an ARM template that uses a copy resource block to deploy 1 or more data disks in a virtual machine. What I would like to do is change this to 0 or more.

Parameter used

"VirtualMachineDiskSizeArray": { "type": "array", "defaultValue": [ "100" ] }, 

which is then called in the resource:

  "resources": [ { "name": "[parameters('virtualMachineName')]", "type": "Microsoft.Compute/virtualMachines", "apiVersion": "2016-04-30-preview", "location": "[parameters('rgLocation')]", "dependsOn": [ "[concat('Microsoft.Storage/storageAccounts/', parameters('rgStorageAccountName'))]" ], "properties": { "osProfile": { ... }, "hardwareProfile": { ... }, "storageProfile": { "imageReference": { ... }, "osDisk": { ... }, "copy": [ { "name": "dataDisks", "count": "[length(parameters('VirtualMachineDiskSizeArray'))]", "input": { "lun": "[copyIndex('dataDisks')]", "name": "[concat(parameters('vmDataDiskNameStub'), add(copyIndex('dataDisks'),1), '.vhd')]", "diskSizeGB": "[parameters('VirtualMachineDiskSizeArray')[copyIndex('dataDisks')]]", "createOption": "Empty", "vhd": { "uri": "[concat(concat(reference(resourceId(parameters('rgName'), 'Microsoft.Storage/storageAccounts', parameters('rgStorageAccountName')), '2015-06-15').primaryEndpoints['blob'], 'vhds/'), concat(parameters('vmDataDiskNameStub'), add(copyIndex('dataDisks'),1), '.vhd') )]" } } } ] } } }, 

However, when I pass an array of data disks with 0 elements, I get this error, as expected:

 Validation returned the following errors: : Deployment template validation failed: 'The template 'copy' definition at line '0' and column '0' has an invalid copy count. The co py count must be a postive integer value and cannot exceed '800'. Please see https://aka.ms/arm-copy for usage details.'. Template is invalid. 

I would like to try to get around this somehow - I tried to add a condition to the copy:

 "condition": "[ greater(length(parameters('VirtualMachineDiskSizeArray')), 0)]", 

But that returned the same error.

I am exploring nested patterns, but this does not look good for the resource section.

+7
azure azure-resource-manager
source share
4 answers

The easiest way to get around this:

 { "condition": "[if(equals(parameters('numberOfDataDisks'), 0), bool('false'), bool('true'))]", "apiVersion": "2017-03-30", "type": "Microsoft.Compute/virtualMachines", "name": "[variables('vmName')]", "location": "[resourceGroup().location]", "properties": { "storageProfile": { "imageReference": { xxx }, "osDisk": { xxx }, "copy": [ { "name": "dataDisks", "count": "[if(equals(parameters('numberOfDataDisks'), 0), 1, parameters('numberOfDataDisks'))]", "input": { "diskSizeGB": "1023", "lun": "[copyIndex('dataDisks')]", "createOption": "Empty" } } ] } } } 

it will cost you to transfer 0 data disks and at the same time will not use this vm. all you have to do is add another vm resource. But it must be with a different name (otherwise the template will fail), or you can use the nested template to deploy vm with the same name

+4
source share

So, in the Interest of Time, I changed my approach to this, but I don't really like it ...

Now I have two deployable json files, VMDeploy.json and VMDeploy-NoDataDisks.json .

They are identical except for the storageProfile section of the VM resource:

VMDeploy.json :

 "storageProfile": { "imageReference": { ... }, "osDisk": { ... }, "copy": [ { "name": "dataDisks", "count": "[length(parameters('VirtualMachineDiskSizeArray'))]", "input": { "lun": "[copyIndex('dataDisks')]", "name": "[concat(parameters('vmDataDiskNameStub'), add(copyIndex('dataDisks'),1), '.vhd')]", "diskSizeGB": "[parameters('VirtualMachineDiskSizeArray')[copyIndex('dataDisks')]]", "createOption": "Empty", "vhd": { "uri": "[concat(concat(reference(resourceId(parameters('rgName'), 'Microsoft.Storage/storageAccounts', parameters('rgStorageAccountName')), '2015-06-15').primaryEndpoints['blob'], 'vhds/'), concat(parameters('vmDataDiskNameStub'), add(copyIndex('dataDisks'),1), '.vhd') )]" } } } ] } 

VMDeploy-NoDataDisks.json :

 "storageProfile": { "imageReference": { ... }, "osDisk": { ... }, "dataDisks": [] } 

And I have a Powershell switch between two json files:

 if ($DriveArray.Count -eq 0) { $TemplateFile = $TemplateFile.Replace('.json','-NoDataDisks.json') } 
+3
source share

I am going to use this answer to use the link to my research on nested templates.

Looking at here I see an approach that would have two nested patterns, for example:

 "resources": [ { "name": "MultiDataDisk", "type": "Microsoft.Compute/virtualMachines", "apiVersion": "2016-04-30-preview", "location": "[parameters('rgLocation')]", "dependsOn": [ "[concat('Microsoft.Storage/storageAccounts/', parameters('rgStorageAccountName'))]" ], "properties": { "osProfile": { ... }, "hardwareProfile": { ... }, "storageProfile": { "imageReference": { ... }, "osDisk": { ... }, "copy": [ { "name": "dataDisks", "count": "[length(parameters('VirtualMachineDiskSizeArray'))]", "input": { "lun": "[copyIndex('dataDisks')]", "name": "[concat(parameters('vmDataDiskNameStub'), add(copyIndex('dataDisks'),1), '.vhd')]", "diskSizeGB": "[parameters('VirtualMachineDiskSizeArray')[copyIndex('dataDisks')]]", "createOption": "Empty", "vhd": { "uri": "[concat(concat(reference(resourceId(parameters('rgName'), 'Microsoft.Storage/storageAccounts', parameters('rgStorageAccountName')), '2015-06-15').primaryEndpoints['blob'], 'vhds/'), concat(parameters('vmDataDiskNameStub'), add(copyIndex('dataDisks'),1), '.vhd') )]" } } } ] } } } ] 

and one such:

 "resources": [ { "name": "ZeroDataDisk", "type": "Microsoft.Compute/virtualMachines", "apiVersion": "2016-04-30-preview", "location": "[parameters('rgLocation')]", "dependsOn": [ "[concat('Microsoft.Storage/storageAccounts/', parameters('rgStorageAccountName'))]" ], "properties": { "osProfile": { ... }, "hardwareProfile": { ... }, "storageProfile": { "imageReference": { ... }, "osDisk": { ... }, "dataDisks": [] } } } ] 

And refer to them from the parent template:

 "parameters": { "nestedType": { "type": "string", "defaultValue": "ZeroDataDisk", "allowedValues": [ "ZeroDataDisk", "MultiDataDisk" ], } }, "resources": [ { "name": "[concat("nested-",parameters('virtualMachineName')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2015-01-01", "properties": { "mode": "Incremental", "templateLink": { "uri": "[concat('https://someplace.on.the.internet/nested/',parameter('nestedType'),".json")], "contentVersion": "1.0.0.0" }, "parameters": { "rgStorageAccountName": { "value": "[parameters(rgStorageAccountName)]" }, "OtherParms": { "value": "[parameters('otherParms')]" } . . . } } ] } 

However, I don’t think it’s better / easier than what I did in response to the “interest of the time”, because

  • The section that interests me (dataDisks) is surrounded by a bunch of other json that does not change me, leaving me with the same crappy problem that you need to manually synchronize the code between two files.
  • Now I have to not only support two json files for the embedded resources, but I have to publish them through the public URL.

Basically, if I can’t get a copy of the 0-N section (and not 1-N) or only attach the section, my two files using the powershell switch seem to be the least overhead.

+1
source share

Working sample https://github.com/mariuszdotnet/azure-resource-manager-tutorial/blob/master/azuredeploy.json

Here is a summary:

  • Move the disks to a variable and use iteration of the variables.
  • If numDisks = 0, then diskLoop = 1 (this prevents an error in the variable copy)
  • Create a variable copy object with count = diskLoop
 "copy": [ { "name": "dataDisks", "count": "[if(equals(parameters('numberOfDataDisks'),0),1, parameters('numberOfDataDisks'))]", "input": { "lun": "[copyIndex('dataDisks')]", "createOption": "Empty", "diskSizeGB": "1023" } } ] 
  • In the VM resource for data disks.
  • On the VM resource, if numDisk = 0, then datadisks = json ('null) else datadisks = variable
 "dataDisks": "[if(equals(parameters('numberOfDataDisks'),0),json('null'),variables('dataDisks'))]" }, 
0
source share

All Articles