I'm deploying an ARM template that uses a copy resource block to deploy 1 or more data disks to a VM. What I'd like to do is change this to 0 or more.
The parameter I use is
"VirtualMachineDiskSizeArray": {
"type": "array",
"defaultValue": [ "100" ]
},
Which is then called in a 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 in 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 work around this somehow - I tried adding a condition on the copy:
"condition": "[ greater(length(parameters('VirtualMachineDiskSizeArray')), 0)]",
But that returned the same error.
I'm researching nested templates, but that doesn't look good for a section of a resource.
Regarding the Disksize I can help you out. What I have actually done is reference to a JSON template file where the size, name, and caching is defined for disk creation.
These can easily be parsed to the deployment
The issue remains that is part of the VM deployment, so there is no option to select a Null value if you want to deploy a VM without extra disks.
I have tried to move the disk creation to the variables section of the template, but than it is not possible to use the VMName as part of the name of the disks you want to create. This is because the copy loop for the VM is not yet initialized, so It will give the wrong name.
I would like to share our solution based many of the answers already here. This is a simple example to have an input array of disks - values being their sizes - and create with those with your vm. works from 0-n. n needs to be smaller than supported disks of your VM size and other azure limits :) This should also help with this comment
Working sample https://github.com/mariuszdotnet/azure-resource-manager-tutorial/blob/master/azuredeploy.json
Here is the summary:
So in the Interest of Time, I have changed my approach to this, but don't really like it...
I now have two deploy json files,
VMDeploy.json
andVMDeploy-NoDataDisks.json
.They are identical other than the storageProfile section of the VM resource:
VMDeploy.json
:VMDeploy-NoDataDisks.json
:And I have a Powershell block switches between the two json files:
I'm going to use this answer to use a reference on my research into nested templates.
Looking at here I can see an approach that would have two nested templates, one like this:
and one like this:
And reference them from a parent template:
However, I don't believe this is better/easier than what I did in my "Interest of Time" answer because
So basically, unless I can have a copy of 0-N of a section (rather than 1-N) or nest just a section, my two file hack with the powershell switch seems to be the least overhead.
The workaround I've used for myself doesn't need linked templates or complicated logic; it's based on this:
If the array is empty, create another array with only one item in it with the value of
"EMPTY_ARRAY_INDICATOR"
.Also, in my
copy
loop, I have added this condition:"condition": "[not(equals(variables('input')[0]), "EMPTY_ARRAY_INDICATOR")]"
so that it doesn't deploy when the first element of the array is"EMPTY_ARRAY_INDICATOR"
.Having a look at your template, I guess I can rewrite it this way:
Please note the
condition
in thecopy
loop, and the usage ofvariables('VirtualMachineDiskSizeArray')
instead ofparameters(VirtualMachineDiskSizeArray)
.I have tested it for my own template, but haven't run your template. Please let me know if it works or not.