At current client, we potentially have to create +50 Private DNS Zones, so I was looking at optimizing the ARM templates as to not have hundreds of lines of code with basically the same info.
Furthermore the DNS zones have to be linked to two VNets (where the custom DNS servers reside).
This can be achieved using copy loop with a mix of arrays and objects.
The ARM template including parameters file is available on Github.
The list of private DNS zones (see full list here) is specified in an array and to loop through this list, a copy loop is used on the privateDnsZones resource, I have marked in red below the relevant lines.
For the virtual network links, a similar copy loop is used. In addition, an object is used as a parameter to make a bit nicer. The object contains two sets of info with link name and VNet resource ID for the two VNets, see more info on using objects here.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"privateZoneNames": {
"type": "array"
},
"vnetSettings": {
"type": "object",
"metadata": {
"description": "Object containing vlink name and vnet ID"
}
}
},
"resources": [
{
"apiVersion": "2018-09-01",
"type": "Microsoft.Network/privateDnsZones",
"name": "[concat(parameters('privateZoneNames')[copyIndex()])]",
"location": "global",
"dependsOn": [],
"tags": {},
"properties": {},
"copy": {
"name": "PrivateZoneCopy",
"count": "[length(parameters('privateZoneNames'))]"
}
},
{
"type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks",
"apiVersion": "2018-09-01",
"name": "[concat(parameters('privateZoneNames')[copyIndex()], '/', parameters('vnetSettings').vlink[0].name)]",
"location": "global",
"dependsOn": [
"[resourceId('Microsoft.Network/privateDnsZones', concat(parameters('privateZoneNames')[copyIndex()]))]"
],
"properties": {
"registrationEnabled": false,
"virtualNetwork": {
"id": "[parameters('vnetSettings').vlink[0].vnetId]"
}
},
"copy": {
"name": "vlinkWeuCopy",
"count": "[length(parameters('privateZoneNames'))]"
}
},
{
"type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks",
"apiVersion": "2018-09-01",
"name": "[concat(parameters('privateZoneNames')[copyIndex()], '/', parameters('vnetSettings').vlink[1].name)]",
"location": "global",
"dependsOn": [
"[resourceId('Microsoft.Network/privateDnsZones', concat(parameters('privateZoneNames')[copyIndex()]))]"
],
"properties": {
"registrationEnabled": false,
"virtualNetwork": {
"id": "[parameters('vnetSettings').vlink[1].vnetId]"
}
},
"copy": {
"name": "vlinkSwcCopy",
"count": "[length(parameters('privateZoneNames'))]"
}
}
]
}
--------------------------------
Param file:
--------------------------------
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"privateZoneNames": {
"value": [
"privatelink.blob.core.windows.net",
"privatelink.vaultcore.azure.net"
]
},
"vnetSettings": {
"value": {
"vlink": [
{
"name": "vlink-vnet-conn-weu-001",
"vnetId": "/subscriptions/XXX/resourceGroups/rg-netw-conn-001/providers/Microsoft.Network/virtualNetworks/vnet-conn-weu-001"
},
{
"name": "vlink-vnet-conn-weu-002",
"vnetId": "/subscriptions/XXX/resourceGroups/rg-netw-conn-001/providers/Microsoft.Network/virtualNetworks/vnet-conn-weu-002"
}
]
}
}
}
}