Simple and easy resource provisioning

One of the reasons I really like Azure is how easy it makes it to provision your infrastructure quickly and easily on the portal.

However, what's even nicer is the support of Azure Resource Manager (ARM) templates for individual resources.

What is an ARM template?

An ARM template is a way to deploy one individual resource or a full resource group through Powershell, C#, Ruby or even the CLI.

ARM templates can be found in two places. Either as part of the individual resource (or the resource group) or by using the Resource Explorer service.

Something worth mentioning is that the usage of the http://resources.azure.com alternative isn't recommended as some templates of preview features or in-depth info are missing from this section.

The ARM template consists of two files. The main template and the parameters. Both files are json files.

They usually consist of 4 parts.

  • The parameters
  • The variables
  • The resources
  • The outputs

In the parameters section, you can define the values of the template that can be moved to parameters in order to provide a more generic template. That way, you can deploy multiple resources of that type using the same template but with different configuration each time. An example would be 4 different instances of CosmosDB in 4 different locations with just a single template.
You are limited to 255 parameters in a template. You can reduce the number of parameters by using objects that contain multiple properties.

In the variables section, you construct values that can be used throughout your template. You do not need to define variables, but they often simplify your template by reducing complex expressions.

In the resources section, you get to define which resources you want to create/update. Simple stuff. It can however get hectic because some of the templates, when exported, have several unnecessary values. A cleanup is recommended.

Outputs, as the name implies, is the ability to have values outputted from the template to use somewhere else.

You can retrieve the output of a template by using the following powershell command.

(Get-AzureRmResourceGroupDeployment -ResourceGroupName <resource-group-name> -Name <deployment-name>).Outputs.resourceID.value

Here is how the ARM template for CosmosDB looks like.

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "cosmosdbname": {
      "defaultValue": "cosmosdbnameValue",
      "type": "string"
    }
  },
  "variables": {},
  "resources": [
    {
      "comments": "",
      "type": "Microsoft.DocumentDB/databaseAccounts",
      "kind": "GlobalDocumentDB",
      "name": "[parameters('cosmosdbname')]",
      "apiVersion": "2015-04-08",
      "location": "UK West",
      "tags": {
        "defaultExperience": "DocumentDB"
      },
      "scale": null,
      "properties": {
        "databaseAccountOfferType": "Standard",
        "consistencyPolicy": {
          "defaultConsistencyLevel": "Session",
          "maxIntervalInSeconds": 5,
          "maxStalenessPrefix": 100
        },
        "name": "[parameters('cosmosdbname')]"
      },
      "dependsOn": []
    }
  ]
}

The parameters file for this template looks like this.

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "cosmosdbname": {
      "value": "newCosmosDb"
    } 
  }
}

As we can see in the template itself, when run this template will create a CosmosDB resource in the UK West region.

The parameter has a defaultValue which in the template is cosmosdbnameValue.
If there was no parameter named cosmosdbname in the parameters file then when created the name of the CosmosDB instance would be the default one. However the parameters fill will override any defaulvalue from the main template.

Running the template

There are several ways to run this ARM template. The easiest way if you are also creating/developing it through Visual Studio is to Right click at the project level and click "Deploy". Keep in mind that this requires the Azure SDK to be installed for Visual Studio.

When a visual studio project of type "Azure Resource Group" is created it will also come out of the box with a powershell script called Deploy-AzureResourceGroup.ps1. This is the file that will do all the work for you, work-out your subscription based on the logged in account and use this data to create the resource on the right place.

Here is what the feedback of the powershell script looks like when run.

- Launching PowerShell script with the following command:
- 'Deploy-AzureResourceGroup.ps1' -StorageAccountName '' -ResourceGroupName '<<omitted>>' -ResourceGroupLocation 'ukwest' -TemplateFile 'azuredeploy.json' -TemplateParametersFile 'azuredeploy.parameters.json' -ArtifactStagingDirectory '.' -DSCSourceFolder '.\DSC'
- Account          : <<omitted>>
- SubscriptionName : <<omitted>>
- SubscriptionId   : <<omitted>>
- TenantId         : <<omitted>>
- Environment      : AzureCloud
- 
- VERBOSE: Performing the operation "Replacing resource group ..." on target "".
- VERBOSE: - Created resource group '<<omitted>>' in location 'ukwest'
- 
- ResourceGroupName : <<omitted>>
- Location          : ukwest
- ProvisioningState : Succeeded
- Tags              : 
- TagsTable         : 
- ResourceId        : /subscriptions/<<omitted>>/resourceGroups/<<omitted>>
- 
- VERBOSE: Performing the operation "Creating Deployment" on target "<<omitted>>".
- Template is valid.
- Create template deployment 'azuredeploy-<<omitted>>'
- Checking deployment status in 5 seconds
- Successfully deployed template 'azuredeploy.json' to resource group '<<omitted>>'.

Deploying with Octopus

Octupus Deploy makes the whole process way too easy.
All you need to do is deploy your provisioning projects as a package and then create a step using the built in "Deploy an Azure Resource Group" step option.

I will be showing this part of the process in depth on another blog.

Keep in mind that if you're planning to deploy your resource templates using Octopus, it is a best practice to parameterize the templates using the octupus deploy variable way, example #{ParamaterName}. That way you can create multiple steps with the same template and parameters file and the only thing that changes is the scope of the options on each step.

More info on https://octopus.com/docs/deploying-applications/azure-deployments/resource-groups