Azure, Azure Pipelines, DevOps, Terraform

IaC Terraform with Azure Pipelines

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.