Although there are plenty of post around using Pester to validate/test ARM templates, most of their approach is around validating the ARM Template contains the components you expect or deployed components are the ones you expect too. However, to me these aren’t the most common frustrations or time lost you get out of writting ARM Templates and those are as important as these tests too and the sooner you finding, the less troubleshooting you’ll need to do. Let alone more complex scenarios where you either do copy loop within the ARM Template or use linked templates for increasing reusability.
Real-world ARM Template Authoring
When I need to write an ARM Template, I always start out of the Azure Portal, using the UI, filling the fields with easy-to-remember values so at the last step, instead of deploying, I download the automation script. (yeah, I know you can type from scratch by using the ARM Reference but the other way feels easier) What happens next is some parameters would became variables, new parameters or variables may appear, ARM functions would replace inefficiencies in the template or to enforce corporate standards.
and the gotcha’s are…
Well, it’s always to expect to:
- Have forgotten some parameters that became variables or were renamed.
{ "parameters": { "computerName": { "type": "string" } }, "variables": { "networkInterfaceName": "[concat(parameters('virtualMachineName'),'_NIC01')]" } }
- Have forgotten some variables that became parameters or were renamed.
{ "parameters": { "virtualNetworkName": { "type": "string" }, "subnetName": { "type": "string" } } }
- Have a missing parenthesis or square brackets (this is a particularly painful one since depending on the location of the type, the error you get might be really misleading)
{ "resources": [ { "type": "Microsoft.KeyVault/vaults", "name": "[concat(parameters('resourcesPrefix'),'_Vault'] } ] }
and if we talk about reusability…
Generally, when you are in company, Azure Resources aren’t just the resource but a bunch of extra configurations which respond to increase (or apply) security; enabling monitoring and diagnostics; enabling log retention; enabling restore or etc. In this scenario, it’s a good practice to create ARM Templates for each component (containing the base resource + secret sauce) and creating a main ARM template for “orchestrating”/combining the others.
we have more gotcha’s (of course)
in this stage, we can get issues such as:
- Forgot to copy the linked ARM Template into a particular folder or have a type on its filename
- Not passing all the required parameters to the linked template or assuming parameter names that don’t match
The final result
Frustration. Basically you just realize of these things as you deploy to Azure and miserably fail. You end up wasting a hugemongo amount of time just getting things right and not even deploying a single component yet. Or all these might happen during a Build and Release process.
How can we identify issue earlier?
Simple answer: having tests looking for this scenarios and being a Powershell guy, I chose writting those tests in Pester. You can find the full script in my GitHub repo: azureDeploy.tests.ps1
How does it work?
The script will test any Azure ARM template found in the location where it’s being called from and their linked templates as well (it assumes linked templates to be in a folder, at the root, called ‘linked’).
A “Describe” will be generated per json file and a “Context” per each test group. These are the different test groups (or Context) an ARM Template is evaluated against:
Context: “JSON Structure”
Evaluates basic Azure ARM template structure such as being less than 1 MB, having up to 256 parameters and having the proper regions. “Parameters” and “Resources” are considered mandantory sections while “Variables” and “Outputs” are optional ones.
Context: “Referenced Parameters”
It reads through the template for any parameters(‘[Name]’) and verifies if it’s defined in the parameters section.
Context: “Referenced Variables”
It reads through the template for any variables(‘[Name]’) and check if it’s defined in the variables section.
Context “Missing opening or closing square brackets”
Just as it states, it reads line by line searching for lines with missing square brackets. If there aren’t any, it will not just generate an “It” clause. Otherwise, it will generate one “It” clause per missing square brackets including the line where it’s missing.
Context “Missing opening or closing parenthesis”
Same as “Missing opening or closing square brackets” context but for parenthesis.
Context “Azure API Validation”
If Powershell session is logged into Azure, it makes use of Test-AzureRmResourceGroupDeployment to validate the template. Running this cmdlet requires two thing:
- Target resource group must exist
- All parameters must be passed
To tackle this, the scripts will attemp to use a resource group called “PesterRG”, if it exists, it will be used (no changes will be made to it). Otherwise, it will create the Resource Group, run the cmdlet and then delete it. In order to be able to run the cmdlet, it will go through all the template parameters and provide dummy data for each one of them (that don’t have a “defaultValue”). Make sure linked templates are uploaded to the Uri their specify, otherwise it will fail.
Context “Nested Template: [template name].json”
If the template contains any resource of the type “Microsoft.Resources/deployments”, it will validate the linked template exists in “linked” folder and its parameters without defaultValue are specified in this template.
July 25, 2019 at 11:58
I don’t even know how I ended up here, but I thought this post was good. I do not know who you are but certainly you are going to a famous blogger if you are not already 😉 Cheers!|
LikeLike
July 19, 2019 at 19:02
My brother recommended I may like this website. He used to be totally right. This submit truly made my day. You can not imagine simply how much time I had spent for this information! Thank you!|
LikeLike
July 19, 2019 at 16:40
I love looking through an article that can make men and women think. Also, thank you for allowing me to comment!|
LikeLike
July 17, 2019 at 17:05
Hey There. I found your blog using msn. This is a really well written article. I’ll make sure to bookmark it and come back to read more of your useful info. Thanks for the post. I will definitely comeback.|
LikeLike
July 17, 2019 at 15:21
Hi there to every body, it’s my first pay a visit of this webpage; this website consists of awesome and truly good information in favor of visitors.|
LikeLike
July 17, 2019 at 02:26
Great work!, your post are always helping the world. Keep up the good job. I will be coming back more ofter
LikeLike
July 16, 2019 at 08:13
Right here is the perfect site for anyone who really wants to find out about this topic. You know so much its almost tough to argue with you (not that I really will need to…HaHa). You certainly put a fresh spin on a topic that has been discussed for ages. Great stuff, just great!|
LikeLike
July 15, 2019 at 20:07
so much great info on here, : D.
LikeLike
July 14, 2019 at 08:25
I went over this internet site and I think you have a lot of wonderful information, saved to fav (:.
LikeLike
July 13, 2019 at 04:25
You have observed very interesting details ! ps decent internet site.
LikeLike
October 7, 2018 at 13:23
You rock! I’ve been waiting for this for a long time.
Thanks and keep posting!
LikeLike