Finishing off this series of articles about IaC with Azure Pipelines, this article is going to follow on from IaC ARM Templates with Azure Pipelines and IaC Ansible with Azure Pipelines and focus on deploying the same simple infrastructure but this time using Terraform.
Azure Pipelines – Releases
For this pipeline I am going to change the Agent Specification to use Ubuntu.

As this is running on an hosted agent, the first thing to add is a task to install Terraform. Microsoft have a task for doing just that.

The Terraform task has a default version but it’s not the latest so I’ll update that.
Note: At the time of writing this the latest version was 0.12.26.

Next I need to add a Terraform task (another Microsoft addition), the task provides the basic Terraform commands, init, validate, plan, validate and apply and destroy.

The Terraform init task requires some configuration, the provider, as I am deploying to Azure this is ‘azurerm’, the configuration directory which is the azure/storage folder in the artifacts and contains the Terraform configuration file. For this example it is named storage.tf.


The task also requires the AzureRM backend configuration to be set.

I need to add the configuration folder as previously with the init command. Also I need to add command arguments to pass variables to my Terraform configuration. Variables are passed using multiple -var command line options.
-var="resource_group_name=$(storageGroup)" -var="resource_group_location=$(storageLocation)" -var="storage_name=$(storageName)"
Note: Terraform plan creates an execution plan to determine what changes are needed between the configuration and the actual state.

Now I need to apply the Terraform configuration and any changes detected by the plan step. As with the previous steps I need to add the configuration folder and add command arguments to pass variables to my Terraform configuration.

-var="resource_group_name=$(storageGroup)" -var="resource_group_location=$(storageLocation)" -var="storage_name=$(storageName)"
The configuration above uses a number of variables, so they need to be configured as well.

I initially thought that the AzureRM backend configuration might configure the resource group and storage account when it ran but sadly this is not the case and so further setup is required.
To setup the Azure storage for the AzureRM backend I will add an Azure CLI task.

And configure the Azure CLI to create the resource group, storage account and container that is required.

az group create --location $(storageLocation) --name $(terraformGroup)
az storage account create --name $(terraformStorageName) --resource-group $(terraformGroup) --location $(storageLocation) --sku $(terrformStorageSku)
az storage container create --name $(terraformContainerName) --account-name $(terraformStorageName)
Now it’s all configured let’s run the release and see if it succeeds

Hopefully everything created successfully in Azure, let’s have a look.


Looks like everything was created as expected including the state file in blob storage.

Azure Pipelines YAML
The previous articles cover creating the pipeline in the Azure DevOps portal and so here I will just include the YAML for the Terraform pipeline configuration. As with the other examples I will use a multi-stage, multi-job pipeline and the code is on GitHub.
The Terraform configuration storage.tf can also be found on GitHub.
# A pipeline with no CI trigger
trigger: none
# No PR triggers
pr: none
stages:
- stage: build_test
displayName: Build and Test
jobs:
- job: build_test
pool:
vmImage: 'windows-latest' # Currently Windows 2019 and Visual Studio 2019
steps:
- script: echo Code Built and Tested!
- stage: release
displayName: Release
dependsOn: build_test
jobs:
- job: deploy_terraform
pool:
vmImage: 'ubuntu-latest' # Currently Ubuntu 18.04
steps:
- task: AzureCLI@2
displayName: 'Azure CLI '
inputs:
azureSubscription: 'Twisters Portal'
scriptType: bash
scriptLocation: inlineScript
inlineScript: |
az group create --location $(storageLocation) --name $(terraformGroup)
az storage account create --name $(terraformStorageName) --resource-group $(terraformGroup) --location $(storageLocation) --sku $(terrformStorageSku)
az storage container create --name $(terraformContainerName) --account-name $(terraformStorageName)
addSpnToEnvironment: false
- task: TerraformInstaller@0
displayName: 'Install Terraform 0.12.26'
inputs:
terraformVersion: 0.12.26
- task: TerraformTaskV1@0
displayName: 'Terraform : Init Azure'
inputs:
workingDirectory: './azure/storage'
backendServiceArm: 'Twisters Portal'
backendAzureRmResourceGroupName: $(terraformGroup)
backendAzureRmStorageAccountName: $(terraformStorageName)
backendAzureRmContainerName: $(terraformContainerName)
backendAzureRmKey: $(terraformStateFilename)
- task: TerraformTaskV1@0
displayName: 'Terraform : Plan'
inputs:
command: plan
workingDirectory: './azure/storage'
commandOptions: '-var="resource_group_name=$(storageGroup)" -var="resource_group_location=$(storageLocation)" -var="storage_name=$(storageName)"'
environmentServiceNameAzureRM: 'Twisters Portal'
- task: TerraformTaskV1@0
displayName: 'Terraform : Apply'
inputs:
command: apply
workingDirectory: './azure/storage'
commandOptions: '-var="resource_group_name=$(storageGroup)" -var="resource_group_location=$(storageLocation)" -var="storage_name=$(storageName)"'
environmentServiceNameAzureRM: 'Twisters Portal'
- job: deploy_build
dependsOn: deploy_terraform
pool:
vmImage: 'windows-latest' # Currently Windows 2019 and Visual Studio 2019
steps:
- script: echo Deploying Code
Time to run the pipeline and see if it works.


All looks good, let’s see if everything is correct in Azure.



I hope that this article has been useful and is a good introduction to deploying Terrform configurations with Azure Pipelines.
One thought on “IaC Terraform with Azure Pipelines”
Comments are closed.