ARM Templates - Resource Delay
I really love the ARM templates, how they are structured, their functions and usability. But like with every thing in this world, it can get better and richer - we just have to think of a way to make it so.
There was a time when I needed to put a delay between two resource deployments. Searching the web gave me few results, however, each and everyone of them required a VM/Service deployment for a simple 'Start-Sleep' PowerShell one-liner. This wasn't going to fly, and only because it is an exaggerated way of executing a one-liner. Secondly, because it can eventually cost you more than required or expected. And to add to the frustration, Microsoft itself is not rushing to help you with a native method for now...
For anyone curious about other method please read the following article:
Introducing a Simple, Cheap (free) and Fast Delay method
My quest for the 'Delay' brought me to a simple, yet native way of delaying an ARM template. Only one culprit - it is not so accurate...
It first starts with a resource group dedicated solely to the 'Delay' function. This resource group is free and can have deployments executed in a procedural manner.
Now, when creating a deployment in a template, we will only name it and leave it empty with 0 resources. This way, it will just take time to create a deployment, and literally will not create anything but a cover.
Considering the time it took to create that deployment (between 5 to 10 seconds), we can now multiply it to create a longer creation time.
To summarize what will be required:
The Code
The code is really simple, and uses a 'nested template' approach. It is divided into two parts, as I couldn't get them to run together without assigning it through a blueprint.
First part - Resource Group deployment
{?
? "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
? ? "contentVersion": "1.0.0.0",
? ? "parameters": {},
? ? "variables": {
? ? ? ? "locationSettings": {
? ? ? ? ? ? "westeurope": {
? ? ? ? ? ? ? ? "abbreviation": "weu"
? ? ? ? ? ? },
? ? ? ? ? ? "switzerlandnorth": {
? ? ? ? ? ? ? ? "abbreviation": "chn"
? ? ? ? ? ? },
? ? ? ? ? ? "eastus2": {
? ? ? ? ? ? ? ? "abbreviation": "eus2"
? ? ? ? ? ? },
? ? ? ? ? ? "eastasia": {
? ? ? ? ? ? ? ? "abbreviation": "ea"
? ? ? ? ? ? }
? ? ? ? },
? ? ? ? "rgLocation": "[resourceGroup().location]",
? ? ? ? "rgName": "[concat('rg-delay-', variables('locationSettings')[resourceGroup().location].abbreviation)]"
? ? },
? ? "resources": [
? ? ? ? {
? ? ? ? ? ? "type": "Microsoft.Resources/deployments",
? ? ? ? ? ? "apiVersion": "2021-04-01",
? ? ? ? ? ? "name": "[concat('DeployRG--', variables('rgName'))]",
? ? ? ? ? ? "location": "[variables('rgLocation')]",
? ? ? ? ? ? "subscriptionId": "[subscription().subscriptionId]",
? ? ? ? ? ? "properties": {
? ? ? ? ? ? ? ? "mode": "Incremental",
? ? ? ? ? ? ? ? "expressionEvaluationOptions": {
? ? ? ? ? ? ? ? ? ? "scope": "Outer"
? ? ? ? ? ? ? ? },
? ? ? ? ? ? ? ? "template": {
? ? ? ? ? ? ? ? ? ? "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
? ? ? ? ? ? ? ? ? ? "contentVersion": "1.0.0.1",
? ? ? ? ? ? ? ? ? ? "parameters": {},
? ? ? ? ? ? ? ? ? ? "variables": {},
? ? ? ? ? ? ? ? ? ? "resources": [
? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? "type": "Microsoft.Resources/resourceGroups",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "apiVersion": "2018-05-01",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "name": "[variables('rgName')]",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "location": "[variables('rgLocation')]",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "properties": {}
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ],
? ? ? ? ? ? ? ? ? ? "outputs": {}
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ]
}
Second part - Delay loop
{? ?
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
? ? "contentVersion": "1.0.0.0",
? ? "parameters": {
? ? ? ? "counter": {
? ? ? ? ? ? "type": "int",
? ? ? ? ? ? "defaultValue": 5
? ? ? ? }
? ? },
? ? "variables": {
? ? ? ? "locationSettings": {
? ? ? ? ? ? "westeurope": {
? ? ? ? ? ? ? ? "abbreviation": "weu"
? ? ? ? ? ? },
? ? ? ? ? ? "switzerlandnorth": {
? ? ? ? ? ? ? ? "abbreviation": "chn"
? ? ? ? ? ? },
? ? ? ? ? ? "eastus2": {
? ? ? ? ? ? ? ? "abbreviation": "eus2"
? ? ? ? ? ? },
? ? ? ? ? ? "eastasia": {
? ? ? ? ? ? ? ? "abbreviation": "ea"
? ? ? ? ? ? }
? ? ? ? },
? ? ? ? "rgName": "[concat('rg-delay-', variables('locationSettings')[resourceGroup().location].abbreviation)]"
? ? },
? ? "resources": [
? ? ? ? {
? ? ? ? ? ? "type": "Microsoft.Resources/deployments",
? ? ? ? ? ? "apiVersion": "2021-04-01",
? ? ? ? ? ? "name": "[concat('DelayDeployment--', variables('rgName'))]",
? ? ? ? ? ? "resourceGroup": "[variables('rgName')]",
? ? ? ? ? ? "properties": {
? ? ? ? ? ? ? ? "mode": "Incremental",
? ? ? ? ? ? ? ? "expressionEvaluationOptions": {
? ? ? ? ? ? ? ? ? ? "scope": "Inner"
? ? ? ? ? ? ? ? },
? ? ? ? ? ? ? ? "template": {
? ? ? ? ? ? ? ? ? ? "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
? ? ? ? ? ? ? ? ? ? "contentVersion": "1.0.0.0",
? ? ? ? ? ? ? ? ? ? "parameters": {
? ? ? ? ? ? ? ? ? ? ? ? "counter": {
? ? ? ? ? ? ? ? ? ? ? ? ? ? "type": "int"
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? },
? ? ? ? ? ? ? ? ? ? "resources": [
? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? "type": "Microsoft.Resources/deployments",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "apiVersion": "2021-04-01",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "copy": {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "count": "[parameters('counter')]",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "name": "delayLoop",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "mode": "Serial",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "batchSize": 1
? ? ? ? ? ? ? ? ? ? ? ? ? ? },
? ? ? ? ? ? ? ? ? ? ? ? ? ? "name": "[concat('Delay-Loop-', copyIndex('delayLoop'))]",
? ? ? ? ? ? ? ? ? ? ? ? ? ? "properties": {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "mode": "Incremental",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "template": {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "contentVersion": "1.0.0.0",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "resources": []
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ]
? ? ? ? ? ? ? ? },
? ? ? ? ? ? ? ? "parameters": {
? ? ? ? ? ? ? ? ? ? "counter": {
? ? ? ? ? ? ? ? ? ? ? ? "value": "[parameters('counter')]"
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ]
}
Now lets break it down so it is clearly understood what's the result and how it exactly works.
领英推荐
The deployment works by regions, so there are no parameters to select except a resource group, and counter:
The code has a built-in abbreviation for regions that creates the names for the 'delay' resource groups:
? ? "variables": {
? ? ? ? "locationSettings": {
? ? ? ? ? ? "westeurope": {
? ? ? ? ? ? ? ? "abbreviation": "weu"
? ? ? ? ? ? },
? ? ? ? ? ? "switzerlandnorth": {
? ? ? ? ? ? ? ? "abbreviation": "chn"
? ? ? ? ? ? },
? ? ? ? ? ? "eastus2": {
? ? ? ? ? ? ? ? "abbreviation": "eus2"
? ? ? ? ? ? },
? ? ? ? ? ? "eastasia": {
? ? ? ? ? ? ? ? "abbreviation": "ea"
? ? ? ? ? ? }
? ? ? ? },
? ? ? ? "rgName": "[concat('rg-delay-', variables('locationSettings')[resourceGroup().location].abbreviation)]"
? ? }
This is an example for 4 regions. It is possible to add more.
With this method the final result will be a resource group name 'rg-delay-weu' or 'rg-delay-chn', etc.
These variables are present in both deployment scripts, and are used to keep the deployments clean without human errors.
The result of running the first RG deployment will look similar to this:
The result of running the 'Delay' deployment will look similar to this:
Conclusion and Takeaways
With this method you can easily integrate a delay into any deployment without spending money on expensive services.
Once a 'Delay' resource group is deployed, you will not need to redeploy it each time you use the delay, but make sure it exists in the correct region before trying to delay deployments.
It is possible to bind the delay resource group to a single location, however, that may result in higher deployment delays if the resources are different locations, but that may be something irrelevant and totally subject to individual opinion and use cases.
Lastly, keep the delay resource group clean and separate from everything else. The deployments history shows the deployments like 'Delay-Loop-0', 'Delay-Loop-1', etc. These deployments are replaceable and repeatable, and show only what you need. Deploying other things to the resource group will pollute the log.