DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
View Events Video Library
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Integrating PostgreSQL Databases with ANF: Join this workshop to learn how to create a PostgreSQL server using Instaclustr’s managed service

[DZone Research] Observability + Performance: We want to hear your experience and insights. Join us for our annual survey (enter to win $$).

Monitoring and Observability for LLMs: Datadog and Google Cloud discuss how to achieve optimal AI model performance.

Automated Testing: The latest on architecture, TDD, and the benefits of AI and low-code tools.

Related

  • Azure’s Infrastructure-As-Code: ARM Templates, Validation, and Deployment Using Azure DevOps
  • Build a Serverless App Fast With Zipper: Write TypeScript, Offload Everything Else
  • MuleSoft: Tactical and Strategical Role of an Application Template
  • Introduction To Template-Based Email Design With Spring Boot

Trending

  • Building AI Applications With Java and Gradle
  • Generative AI: A New Tool in the Developer Toolbox
  • Database Monitoring: Key Metrics and Considerations
  • Announcing DZone Core 2.0!

Conditions in ARM Templates (the Right Way)

Hot off Microsoft Build, Azure Resource Manager templates just got an overhaul, complete with new support for conditional logic.

Sam Cogan user avatar by
Sam Cogan
·
May. 24, 17 · Tutorial
Like (1)
Save
Tweet
Share
9.05K Views

Join the DZone community and get the full member experience.

Join For Free

At this month's Build conference, there were lot’s of new Azure announcements and, in particular, lots of new features for Azure Resource Manager (ARM) templates. Ryan Jones, PM on ARM templates, did a breakout session talking about all the new functionality, which is available now on Channel 9. I want to focus on one of the big improvements, at least from my perspective. We now have proper conditional logic in ARM templates! I blogged a few weeks ago about a workaround that would let you have this sort of logic using nested templates, but this was very much a temporary solution. With this new functionality, conditions are now fully implemented into the language!

Condition

The ARM template language now includes the “condition” key, which can be applied to a resource to determine whether or not that resource is executed. Let's take the example from the previous post again, where we wish to deploy a network card and we want to determine whether this NIC has a public IP or not via the means of a parameter. In this template, we supply a parameter called “NetworkInterfaceType” that can be “Public” or “Private”. In this template, we always deploy a vNet, and then the next step is to create a public IP resource. We only want this Public IP to exist if the “NetworkInterfaceType” is “Public”, so we add a condition to the Public IP resource:

        {
            "apiVersion": "2017-04-01",
            "condition": "[equals(parameters('NetworkInterfaceType'),'Public')]",
            "type": "Microsoft.Network/publicIPAddresses",
            "name": "[Concat(variables('NICName'),'-pip')]",
            "location": "[resourceGroup().location]",
            "tags": {
                "displayName": "[Concat(variables('NICName'),'-pip')]"
            },
            "properties": {
                "publicIPAllocationMethod": "[parameters('IPAllocationMethod')]",
                "dnsSettings": {
                    "domainNameLabel": "[Concat(variables('NICName'),'-pip')]"
                }
            }
        },


Very simple, we use the “condition” key, and supply a value that can be evaluated to true or false. In this case whether the parameter “NetworkInterface” equals the word “Public”. If it does we create this resource, if it does not we don’t. One thing to note is that if your condition evaluates to false then the system simply skips, or no-ops the section, it is still in the template, it still gets compiled (or whatever ARM templates do behind the scenes). This is important if you are doing something like new or existing, where subsequent resources will have a dependency on your conditional resource, they do still exist in the template so this won’t error.

Ok, so we now are only creating the Public IP when the parameter “NetworkInterfaceType” is set to “Public”, but we also need to control whether or not we assign the public IP to a NIC based on the parameter. This is where it is a little bit more complicated (although not much).

As I mentioned, you apply the condition at the resource level — you can’t apply it to sections inside the resource. So what we can’t do is have a single network card resource and choose which child sections are run. What we instead have to do is create two network card resources and set the condition to control which one actually gets created. One thing to note is that you can’t have the “name” property be the same for both NICs. Even though you will only create one or the other, the template still needs to compile with both in, and it will throw an error if they are named the same. To get around this, I have used the conditional parameter value in the name. This means later when you come to assign the NIC to a VM you can simply do something like [concat(variables(‘NICName’),’-‘,parameters(‘NetworkInterfaceType’))]

 {
            "apiVersion": "2017-04-01",
            "condition": "[equals(parameters('NetworkInterfaceType'),'Public')]",
            "type": "Microsoft.Network/networkInterfaces",
            "name": "[concat(variables('NICName'),'-public')]",
            "location": "[resourceGroup().location]",
            "tags": {
                "displayName": "parameters('NICName')"
            },
            "dependsOn": [
                "[concat('Microsoft.Network/publicIPAddresses/', variables('NICName'),'-pip')]"
            ],
            "properties": {
                "ipConfigurations": [
                    {
                        "name": "ipconfig1",
                        "properties": {
                            "privateIPAllocationMethod": "[parameters('IPAllocationMethod')]",
                            "subnet": {
                                "id": "[concat(resourceId('Microsoft.Network/virtualNetworks', variables('NetworkName')), '/subnets/',variables('Subnet1Name'))]"
                            },
                            "publicIPAddress": {
                                "id": "[resourceId('Microsoft.Network/publicIPAddresses',Concat(variables('NICName'),'-pip'))]"
                            }
                        }
                    }
                ]
            }
        },
        {
            "apiVersion": "2017-04-01",
            "condition": "[equals(parameters('NetworkInterfaceType'),'Private')]",
            "type": "Microsoft.Network/networkInterfaces",
            "name": "[concat(variables('NICName'),'-private')]",
            "location": "[resourceGroup().location]",
            "tags": {
                "displayName": "parameters('NICName')"
            },
            "dependsOn": [],
            "properties": {
                "ipConfigurations": [
                    {
                        "name": "ipconfig1",
                        "properties": {
                            "privateIPAllocationMethod": "[parameters('IPAllocationMethod')]",
                            "subnet": {
                                "id": "[concat(resourceId('Microsoft.Network/virtualNetworks', variables('NetworkName')), '/subnets/',variables('Subnet1Name'))]"
                            }
                        }
                    }
                ]
            }
        }



Again, if NetworkInterfaceType is set to “Public”, we create the first NIC which has a public IP, and if it is set to “Private” we create the second.

Functions

To go along with conditions, we also have a load of new functions that help with creating our conditional statements:

  • equals()
  • less()
  • lessOrEquals()
  • greater()
  • greaterOrEquals()

These are fairly self-explanatory and can be used either on their own or in combination with other functions. For example:

"[greater(length(parameters('NetworkInterfaceType')),6)]"


That would be true if the length of the string “NetworkInterfaceType” is greater than 6 characters.

Ryan also announced a number of set-based functions that could also be useful for conditions:

  • contains()
  • empty()
  • intersection()
  • union()
  • first()
  • last()
  • indexOf()
  • lastIndexOf
  • startsWith()
  • endsWith()
  • max()
  • min()
  • range()

Summary

This is a significant improvement in the ARM language and adds a lot more flexibility to templates. It removes the need for nested templates purely for conditions (although they are still a good idea for modularity) and provides many additional types of conditions than can be achieved with this method.

I would encourage you to view the presentation from Build with all the new changes to the ARM language, which also include serial copies, cross resource group deployments, and conversions, as well as new managed applications. I will be covering many of these over the next few weeks.

Template Arm (geography)

Published at DZone with permission of Sam Cogan, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Azure’s Infrastructure-As-Code: ARM Templates, Validation, and Deployment Using Azure DevOps
  • Build a Serverless App Fast With Zipper: Write TypeScript, Offload Everything Else
  • MuleSoft: Tactical and Strategical Role of an Application Template
  • Introduction To Template-Based Email Design With Spring Boot

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: