Azure Resource Manager Templates in your Continuous Delivery Pipeline
Infrastructure as Code
What is an ARM Template
There are a number of ways to setup your Azure environment to run your systems. You can use the Azure portal to manually click and type in your configurations. This is where most people start. You can also use a couple of terminal options with the Azure CLI and Azure Powershell. The third option is using Azure Resource Management (ARM) templates which are defined as:
ARM templates enable Infrastructure as Code scenarios but what does this actually mean? It allows you to declare what you want your Azure environment to look like. You write a configuration file as JSON that tells the Azure cloud you want two databases, a web app and a storage account. You also have to declare the dependencies of those items so in our contrived example you would also have to add a database server to run your database as well as a app service plan to run your web app.
The high level sections of an ARM template are parameters, variables, outputs and resources.
Parameters allow you to specify values such as username, password and prefixes for object names. These have types, optional default values and options to supply descriptions that inform other developers and tooling in certain cases of the purpose of the parameter.
Variables allow you to augment values with template functions such as string concatenation, uri and a useful unique string generator that assist in creating resource names that need to have a globally unique name.
Finally resources are the things you want built-apps, virtual machines, databases etc. Here you supply names, locations (regions), parameters specific to the resource you are creating, tags so that you can query on your related resources and dependencies.
Outputs are useful for sharing values that are calculated with in the processing of your arm template and make them available to other processes downstream in your pipeline. A good example of this is related to the uniqueString function. You might have a database server created in your ARM template and you need that server name to participate in a connection string later on in your deployment. This is useful as there are are some naming rules and restrictions for resources in Azure and you don't have to hard code those values into your deployment variables.
One of the nice features of ARM templates is that you can reference one template from another. If you wanted you could organize your templates by object so that you had all your networking, databases and virtual machines contained in their respective template files. This would get a little unwieldy given the occasions when dependencies might make this counter productive.
Another method might be for different environments where you choose to have specific differences in your test environment that what you have in production.
The method that I've been using currently is based on my Continuous Delivery pipeline stages. The lowest run in the ladder is getting the application to compile, run unit tests and most likely some category of tests that are required to make calls to third-party APIs or a database. Here I usually select a ARM template that can fulfill these minimum requirements for just these build/basic-tests.
Further up where more advanced testing requires more components is where I would leverage a template that has more objects. These could be where you actually deploy a sub-set of your system ,for example, a database and a web app that would then execute some style of UI automation tests to actually drive the application. Or at the staging or production level it would be everything that is included in the system.
Using the minimum template in your build
What might these steps look like in a pseudo build system?
It's really just a typical build setup with the exception of having the Continuous Delivery process building up some Azure environment components.
The CI build uses the database template which results in a shiny new Azure Resource Group and the database necessary for the integration tests to run against it.
After the tests have passed the deploy-able artifacts are packaged up into your deployment platforms favorite package format and ready for consumption further along the pipeline.
At the end of the run the temporary environment is destroyed and the credit card linked to the Azure Subscription stops vibrating and will help in keeping some of the costs down.
Depending on the level of parallelism of your builds, size of your teams, branching strategy or commit frequency you can investigate Azure Resource Group naming conventions ranging from static names all the way up through using the variable systems in your build & deployment platforms.
Using the full in your CI, Dev, UAT, etc
Now that you CI build has successfully completed your might have some tests that are appropriate to run against your actual running application. It's critical that your build artifacts are available for the pipeline to use for your deployment so make sure that your ARM templates are also published in your CI step. These are necessary in the next steps and assist in telling the story of infrastructure as code.
In this CI Deployment pipeline step we are using a different template in our arsenal.
This one contains the web app that will run our UI tests. The hook here is that there is a dependency on the database template so that will also get created in this deployment. There doesn't need to necessarily need to be a direct DependsOn called out from the web application to the database but just a Deployment dependency that wires up the templates to one another.
At this time it would be a good time to run those migrations to make sure that there are no database related surprises as you promote through your environments. Our other tests are run that, again, drive the application on behalf of the users and if all went well the deployment succeeds.
From here you can have your upstream environments use the full ARM template and all your artifacts will be deployed.
With these deployment steps being very similar, if not just a variable change that is supplised to deploy full template.
Hopefully you can get the sense of how you can use ARM template directly in your build to keep your infrastructure in the same process as your source code. Getting some additional deployment verification steps would also add value to your overall deployment system as well. This way you can verify some business assertions on what your templates and deployment process are actually creating.