Menu Close

ARM Template what-if deployment

Last year at Microsoft Ignite, the private preview of the ARM template what-if option was introduced. Since about a month, this new option for PowerShell has gone into public preview and it is really a great new feature, that can help a lot with your template development. In this post, I want to show you how you can use ARM Template what-if deployment, how it can be integrated in a Azure DevOps pipeline and what this means for my PowerShell module ARMHelper.

What is the what-if functionality

By using what-if, you are able to get a preview of what an ARM template would do to your environment. When a lot of resources are deployed through a template, it is easy to overlook something or have a typo somewhere. Especially with templates running in complete mode, this can cause you to accidentally remove resources you wanted to keep or deploy the wrong resources. What-if will give you an overview of what resources will be added, changed, removed and ignored.

Preview

The what-if operation is still in preview, which means the output is not perfect yet. There can be noise in the output, which means the output says something has changed when it didn’t. This is something to keep in mind when using it. If you find noise or behavior you don’t expect, you can report that at GitHub to help improve the tool.

Install what-if

If you want to start using WhatIf straight away, you can do so by loading the 1.12.1-preview version of the Az.Resources module.

Install-Module Az.Resources -RequiredVersion 1.12.1-preview -AllowPrerelease

Keep in mind is that the newest module for az.Resources at this time is 1.13, so you need to make sure you are not using that version.

How does it work?

So what can it do? Let’s start with a simple storage account. I use this template for the examples. If you want to follow along, copy it to your working folder under the name azuredeploy.json. Don’t forget to create a Resource group for it in your Azure tenant.

What-if

First, we will see the what-if option. For this, you run New-AzResourcegroupdeployment like you would do for your deployment, but you use the parameter -whatif

Note: As you can see, I use splatting for the parameters. This means I store the parameters in a hashtable and give them back to the cmdlet with @Parameters. It increases readablitity. Read more about it here.

$Parameters = @{
    ResourcegroupName    = "ARMTesting"
    Templatefile         = ".\azuredeploy.json"
    StorageAccountPrefix = "arm"
    Mode                 = 'Incremental'
}
New-AzResourceGroupDeployment @Parameters -WhatIf

The action will look something like this:
(the collection of the resources take a while)

ARM Template what-if deployment

In green, it shows what resource will be created.

Now, let’s see what happens if the storage account already exists. To do this, first we deploy the storage account. After that, we run the cmdlet again.

ARM Template what-if deployment

As you can see, it checks the resource group and there are no changes.
Let’s try it with a different storage account name:

$Parameters = @{
    ResourcegroupName    = "ARMTesting"
    Templatefile         = ".\azuredeploy.json"
    StorageAccountPrefix = "arm2"
    Mode                 = 'Incremental'
}
New-AzResourceGroupDeployment @Parameters -WhatIf

ARM Template what-if deployment

As you see, The output now shows 1 new resource that will be deployed and 1 that will be ignored.

When we change the deployment mode to Complete, it will delete all resources in the resource group that are not in the template.

$Parameters = @{
    ResourcegroupName    = "ARMTesting"
    Templatefile         = ".\azuredeploy.json"
    StorageAccountPrefix = "arm2"
    Mode                 = 'Complete'
}
New-AzResourceGroupDeployment @Parameters -WhatIf

The result now shows one resource will be deleted and one will be created.

If you have worked with Terraform, this will all look very familiar. This output is very similar to the Terraform Plan output. It is important to remember that Terraform uses a state file though, where this module compares directly to Azure.

It gives you a lot of control over the deployment before you run it.

Confirm

Besides to -Whatif, you also have the option to use the parameter -Confirm
You use it the same way you would use -whatif, but in this case after the results you can choose to run the deployment straight away.

Error handling

The goal of what-if is clear, but I found it comes with a great extra feature, better error handling options!

If we change the prefix of the storage account to arm!, the deployment will fail, as no special characters are allowed in storage account names. Before what-if was available, you would use Test-AzResourceGroupDeployment and the output would be this:

Well if it isn’t our friend General Error. There is no information on here and I would have to look further to find out what is going wrong.

Let’s do the same deployment with New-AzResourceGroupDeployment @Parameters -Whatif

ARM Template what-if deployment

Now, it actually tells us what is wrong with the deployment. That is a great timesaver when you are creating new templates.

Use in Azure DevOps pipelines

So we talked about how these cmdlets can help you when you are interactively running ARM templates. How about when you are running them in Azure DevOps pipelines.
I did some blogposts about how you can create an Azure DevOps pipeline for ARM template, both through the visual designer, through YAML and in a multi-stage pipeline. Let’s see how the new options fit in these pipelines.

To give the flexibility you need for automation, you would use the cmdlet Get-AzResourceGroupDeploymentWhatIfResult, As this gives you an object to work with when assigned to a variable.

$Parameters = @{
        ResourcegroupName    = "ARMTesting"
        Templatefile         = ".\azuredeploy.json"
        StorageAccountPrefix = "arm"
        Mode                 = 'Incremental'
    }
$Result = Get-AzResourceGroupDeploymentWhatIfResult @Parameters

When you call $Result, it will give the same result as New-AzResourceGroupDeployment -WhatIf. But let’s see what possibilities we have by using Get-Member.

ARM Template what-if deployment

As you see, we have some nice properties to work with in an automation pipeline.

Check output

By calling the Changes property, we can get more information on what would happen with this deployment

You could use the properties for your own needs in a pipeline.

  • With the ChangeType Property, you can select what kind of changes (Create, Change or Delete) are expected in the deployment.
  • The before and after properties can give you information on what the resource was like before and what is changed into after.
  • The Delta will show just the changes between the before and after situation.

So here we have some nice options to create an auditing trail of perform pester testing against the results.

The simplest way though is to just call the $Result in the pipeline. This would be a way to do that:

And the result would be like this:

This way you have the option to manually check what an ARM template would do before pushing the deployment.

Check for deletion

A use case you might have, is to perform a check for resources that might get deleted because you are running in Complete mode. If you run the following task in a pipeline, it would stop the pipeline if any resources would be deleted.

What about ARMHelper?

People who have followed me for a while know I am the owner of the PowerShell module ARMHelper.
I built ARMHelper about a year ago to fill in some gaps in ARM Template management:
– I was missing the Plan-step that I knew from Terraform
– The general errors were annoying me, so I made a cmdlet that collected the error from the Azure logs
– I wanted to have some sort of security if Resources would be deleted

Sounds familiar? 🙂

The what-if functionality provides exactly the functionality that I had created ARMHelper for. And I must say this is one of the best ways to get obsolete. The new options are developed by Microsoft and better than anything I could have created.

I have decided to stop development on ARMHelper and instead put my energy on helping the ARM template team by creating issues for bugs that might still be present in these cmdlets. If we all do the same, ARM what-if can get into General Availability as soon as possible.
I will keep ARMHelper in the gallery as I know it is used in pipelines actively by people, which I don’t want to break. In the coming weeks I will put out some disclaimers on there to give notice that development has been stopped. Thank you to the people that have helped by using ARMHelper, promoting it and creating issues.

Leave a Reply

Your email address will not be published. Required fields are marked *