I’ve recently been looking into linked ARM templates and how they can simplify templates and allow us to apply the single responsibility principle to the templates that define our infrastructure as we do in the code we write for our applications; linked templates are a very easy way to allow us to apply these principles and I’ve found them extremely easy to get set up both running locally and when deploying them through Azure DevOps.
One common thing that tends to come up in all projects is naming conventions for Azure Resources, in our case the client would typically have their own naming convention that we’d need to adhere to or in some cases the client would decide to adopt our convention. Now, the question is how do we manage these naming conventions across all of our ARM templates and make them easy to change? There’s a couple of typical scenarios I’ve seen when working with ARM templates, the first one is that resource names will be hardcoded in the parameter files and the second one is that the resource names are generated within the templates; both of these scenarios mean that our naming conventions are controlled at the individual template level rather than sharing the same logic across all templates created in the organisation.
In this blog post I’m going to run through a solution I’ve defined whereby a separate linked template is created to output the name of each resource we are creating, below I’ll run through a quick demo of the solution and show how easy it is to implement.
Typically when using linked ARM templates you will have a parent template that usually represents the resources within your resource group, you will then have multiple deployments within the template that reference your linked templates that you have created to represent each type of resource; this allows you to create a standard set of templates for each resource type and share those templates across multiple projects promoting reusability and standardisation.
In the example below we want to deploy a set of resources to a resource group, which includes:
- A Function App and its associated Storage Account
- A Key Vault
To deploy this we would have 3 ARM templates:
- armdeploy.json – my parent template to represent my resource group
- functionApp.json – to represent my function app and it’s storage account
- keyVault.json – to represent my key vault
Represented as a diagram my deployment looks something like below:
Each of the templates that represents a resource type will have parameters to allow us to specify the names of the resources to be created e.g. the template for my function app will have a parameter called functionAppName and a parameter called storageAccountName. This allows us to inject the resource names from my parent template getting us one step towards applying the single responsibility principal as the templates to generate each resource type are no longer responsible for defining the name.
To get us to our ideal solution whereby we assign resource names from a central place we can create another linked template called namingConventions.json that contains the following:
This template accepts the following parameters:
It then takes those parameters and generates a name for the resource in the format:
If we pass the template the following parameters for a deployment to a resource group in West Europe:
- clientName = Adatis
- projectAbbreviation = Test
- environment = dev
- resourceType = functionApp
- instanceNumber = 01
We’d get the following output in the resourceName property:
The template does not deploy any resources and it’s only responsibility is to generate resource names and output them to the parent template. We can use the output of the template in a subsequent deployment using an expression like below:
Using this solution we can standardise items such as the abbreviation used for each resource and the abbreviations used for each Azure region and ensure that all resources follow the same convention. In our use case we can keep a standard set of ARM templates to use across projects and adjust the naming conventions file to reflect the naming conventions used by the client we are working for. This means we can avoid situations we see daily where a mixture of naming conventions are in use for resources across a tenant.
To pull all of this together we can reference our naming conventions template in our parent deployment and inject the resource names that are returned into our subsequent deployments creating something like the diagram below:
An example of the naming conventions template being used in a deployment can be found on my GitHub at https://github.com/benjarvis18/ARMNamingConventions.
As we’ve shown above, linked ARM templates are a good first step towards applying the single responsibility principle to our ARM templates however, if we enhance the pattern slightly and add in a naming conventions template we can centralise the generation of names for our Azure resources and ensure that standards are applied across all of our ARM templates.
As always, this solution is something I have implemented to solve a problem I’ve faced however, I’m interested to see how others are solving this so if you’ve got a different approach then feel free to contact me on Twitter @BenJarvisBI or comment below.