Dynamically Assigning an Availability Set to a VM in an ARM Template

Recently I was creating an ARM template for a client.  The idea for the ARM template was that we were going to create two VMs, and it would also create an Availability Set and assign the VMs to the Availability Set.  So that’s no problem.Cloudflare being the cloud

We then got a request to also create an ARM template for one VM without the Availability Set.  I didn’t want to create (and then have to manage) a second template. I wanted one template.  So I added a parameter to the ARM template called “SingleMachineInstall” which accepted “Yes” no “No” to the parameters section like this.

“SingleMachineInstall”: {
“type”: “string”,
“allowedValues”: [ “Yes”, “No” ],
“defaultValue”: “No”,
“metadata”: {
“description”: “Check this if this should be installed as a single VM. This will prevent the ILB, Availability Set and the second VM from being created.”
}
},

For all the objects that I didn’t want to create when this parameter had a value of “Yes” I simply added a condition statement to each object like this.

“condition”: “[equals(parameters(‘SingleMachineInstall’), ‘No’)]”,

Then came the complex part of this.  When there are two VMs being created, each VM needed to be dependent on the Availability Set. But when there’s only one VM, I’m not creating the Availability Set, so if the dependency is still there, the deployment will fail.  One thing that I found in my testing, is that you can set a resource to be dependant on the same resource multiple times.  So what I did in the dependsOn section of the VM template, I combined this with an IF statement. In the IF statement, I put down that if the Parameter is set to “No” then we pass in the resourceId for the Availability Set. if the Parameter is set for “Yes” then we pass in the NIC again, which makes the dependsOn succeed either way.

“dependsOn”: [
“[concat(parameters(‘VM1_Name’), ‘_nic0’)]”,
“[if(equals(parameters(‘SingleMachineInstall’), ‘No’), resourceId(‘Microsoft.Network/loadBalancers’, parameters(‘AvailabilitySet_Name’)), concat(parameters(‘VM1_Name’), ‘_nic0’))]”
],

The final thing that we needed to figure out was the properties.availabilitySet value within the Virtual Machine configuration.  The problem with this value is that it expects to have a sub-Id called id like this.

“availabilitySet”: {
“id”: “[resourceId(‘Microsoft.Compute/availabilitySets’, parameters(‘AvailabilitySet_Name’))]”
},

Now, this couldn’t be wrapped in a simple IF statement, because then the id that is being passed in, is a blank string, which throws an error message.

There’s another syntax for this parameter which came in really handy for this.  That syntax is to pass in the ID, without specifying that it is an id like is shown here.

“availabilitySet”: “[resourceId(‘Microsoft.Compute/availabilitySets’, parameters(‘AvailabilitySet_Name’))]”,

Now, this syntax is important to us because we can use this to help us not put in an Availability Set if the parameter is set to not create the Availability Set.

We create one additional thing to make this work, first we create a variable within the ARM template.  I called this variable “availabilitySet”.  Because of the way ARM works, no error will be thrown if there’s no Availability Set created.

“availabilitySet”: {
“id”: “[resourceId(‘Microsoft.Compute/availabilitySets’, parameters(‘AvailabilitySet_Name’))]”
}

Back within the VM section of the ARM template, we need to tell the ARM template to use the variable if it needs, and if it isn’t needed we send is a NULL value.  This way if we need an Availability Set, we specify the child value, otherwise, we pass in nothing.

“availabilitySet”: “[if(equals(parameters(‘SingleMachineInstall’), ‘No’), variables(‘availabilitySet’), json(‘null’))]”,

When I was able to do this, I was using “apiVersion”: “2019-03-01” so this may not work in later version of the API, so be warned about that.

When I was searching around on Google I couldn’t find any examples that showed how to do this. They may be out there, but I couldn’t find them.

Hopefully, this technique works for you in the few places that you need this sort of technique.

Denny

The post Dynamically Assigning an Availability Set to a VM in an ARM Template appeared first on SQL Server with Mr. Denny.

Share

2 Responses

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Trust DCAC with your data

Your data systems may be treading water today, but are they prepared for the next phase of your business growth?