Can I loop over properties in ARM templates?
Indeed you can! Copy does work with properties!
Create a parameter or variable like this (this example will use parameter array):
"lbRules": {
"type": "array",
"defaultValue": [
{
"name": "httpPort",
"frontendPort": "80",
"backendPort": "80",
"protocol": "tcp"
},
{
"name": "customAppPort",
"frontendPort": "8080",
"backendPort": "8888",
"protocol": "tcp"
},
{
"name": "httpsPort",
"frontendPort": "443",
"backendPort": "443",
"protocol": "tcp"
}
]
}
Use this parameter in the Loadbalancer resource using copy like this that will create that many probes and rules that you defined in your parameter array:
{
"apiVersion": "[variables('lbApiVersion')]",
"type": "Microsoft.Network/loadBalancers",
"name": "[parameters('myLoadBalancer')]",
"location": "[parameters('computeLocation')]",
"dependsOn": [
"[concat('Microsoft.Network/publicIPAddresses/',concat(parameters('lbIPName'),'-','0'))]"
],
"properties": {
"frontendIPConfigurations": [
{
"name": "LoadBalancerIPConfig",
"properties": {
"publicIPAddress": {
"id": "[resourceId('Microsoft.Network/publicIPAddresses',concat(parameters('lbIPName'),'-','0'))]"
}
}
}
],
"backendAddressPools": [
{
"name": "LoadBalancerBEAddressPool",
"properties": {}
}
],
"copy": [
{
"name": "probes",
"count": "[length(parameters('lbRules'))]",
"input": {
"name": "[concat(parameters('lbRules')[copyIndex('probes')].name,'Probe')]",
"properties": {
"intervalInSeconds": 5,
"numberOfProbes": 2,
"port": "[parameters('lbRules')[copyIndex('probes')].backendPort]",
"protocol": "[parameters('lbRules')[copyIndex('probes')].protocol]"
}
}
},
{
"name": "loadBalancingRules",
"count": "[length(parameters('lbRules'))]",
"input": {
"name": "[parameters('lbRules')[copyIndex('loadBalancingRules')].name]",
"properties": {
"frontendIPConfiguration": {
"id": "[concat(resourceId('Microsoft.Network/loadBalancers', parameters('myLoadBalancer')),'/frontendIPConfigurations/LoadBalancerIPConfig')]"
},
"frontendport": "[parameters('lbRules')[copyIndex('loadBalancingRules')].frontendport]",
"backendport": "[parameters('lbRules')[copyIndex('loadBalancingRules')].backendport]",
"enableFloatingIP": false,
"idleTimeoutInMinutes": "5",
"protocol": "[parameters('lbRules')[copyIndex('loadBalancingRules')].protocol]",
"backendAddressPool": {
"id": "[concat(resourceId('Microsoft.Network/loadBalancers', parameters('myLoadBalancer')),'/backendAddressPools/LoadBalancerBEAddressPool')]"
},
"probe": {
"id": "[concat(variables('lbID0'),'/probes/', parameters('lbRules')[copyIndex('loadBalancingRules')].name,'Probe')]"
}
}
}
}
],
"inboundNatPools": []
},
}
}
More info can be found here:
- https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-multiple#property-iteration
- https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/copy-properties
You can only apply the copy object to a top-level resource.
You cannot apply it to a property on a resource type, or to a child resource.
"resources": [
{
"type": "{provider-namespace-and-type}",
"name": "parentResource",
"copy": {
/* yes, copy can be applied here */
},
"properties": {
"exampleProperty": {
/* no, copy cannot be applied here */
}
},
"resources": [
{
"type": "{provider-type}",
"name": "childResource",
/* copy can be applied if resource is promoted to top level */
}
]
}
]
Source of Quotation: Deploy multiple instances of resources in Azure Resource Manager templates
You can loop over properties in ARM Template ONLY IF the copy object is applied to a top-level resource, which is in your case the "Microsoft.Network/loadBalancers", but that will also create multiple copy of the said resource.
If this is not what you want to achieve, I would recommend you to keep your existing way until ARM Template support copy object to property on a resource type in the future.