Skip to content
| Marketplace
Sign in
Azure DevOps>Azure Pipelines>Azure Pipelines Terraform Tasks

Azure Pipelines Terraform Tasks

Charles Zipp

|
9,114 installs
| (17) | Preview
Tasks to execute terraform commands during Azure Pipelines

Terraform Tasks for Azure Pipelines

The tasks in this extension allow for running terraform cli commands from Azure Pipelines. The motivation for this extension was to provide terraform pipeline tasks that could execute on all build agent operating systems and provide guided task configuration.

Supported Commands

The Terraform CLI task supports executing the following commands

  • version
  • init
  • validate
  • plan
  • apply
  • destroy
  • show
  • refresh
  • import
  • output
  • force-unlock
  • fmt

Compatible with Linux Build Agents

The tasks can execute on all supported build agent operating systems including Ubuntu and MacOS.

Separate Task for Terraform Installation

The dedicated Terraform Installer task allows for complete control over how frequently and on which agents terraform is installed. This prevents from having to install terraform before executing each terraform task. However, if necessary, this can be installed multiple times to support pipelines that span multiple build agents

Install Latest Version

The installer task supports installing the latest terraform version by using the keyword latest as the version specified. This is the default option when the installer is added to a pipeline. Specifying latest will instruct the task to lookup and install the latest version of the terraform executable.

- task: TerraformInstaller
    displayName: install terraform
    inputs:
        terraformVersion: latest

If terraformVersion not provided, task defaults to latest

- task: TerraformInstaller
    displayName: install terraform

Install Specific Version

- task: TerraformInstaller
    displayName: install terraform
    inputs:
        terraformVersion: 0.14.3

Azure Service Connection / Service Principal Integration

When executing commands that interact with Azure such as plan, apply, and destroy, the task will utilize an Azure Service Connection to authorize operations against the target subscription. This is specified via the environmentServiceName input

- task: TerraformCLI
    displayName: 'terraform apply'
    inputs:
        command: apply
        environmentServiceName: 'My Azure Service Connection'

Execute Azure CLI From Local-Exec Provisioner

When an azure service connection is provided and runAzLogin is set to true, the terraform cli task will run az login using the service connection credentials. This is intended to enable templates to execute az cli commands from a local-exec provisioner.

Setting runAzLogin to true will indicate the task should execute az login with specified service connection.

- task: TerraformCLI
    displayName: 'terraform apply'
    inputs:
        command: apply
        environmentServiceName: 'My Azure Service Connection'
        # indicate az login should be run as part of this command
        runAzLogin: true

Setting runAzLogin to false will indicate the task should not execute az login with specified service connection.

- task: TerraformCLI
    displayName: 'terraform apply'
    inputs:
        command: apply
        environmentServiceName: 'My Azure Service Connection'
        # indicate az login should be run as part of this command
        runAzLogin: true

runAzLogin will default to false when not specified; indicating the task should NOT run az login

- task: TerraformCLI
    displayName: 'terraform apply'
    inputs:
        command: apply
        environmentServiceName: 'My Azure Service Connection'
        # indicate az login should be run as part of this command
        runAzLogin: true

This should allow the following template configuation to be run using this task

resource "azurerm_storage_account" "st_core" {
  name                      = "my-storage-account"
  location                  = "eastus"
  resource_group_name       = azurerm_resource_group.rg_core.name
  account_kind              = "StorageV2"
  account_tier              = "Standard"
  account_replication_type  = "LRS"
  

  # can now be run by the terraform cli task from azure pipelines
  provisioner "local-exec" {
          command = "az storage blob service-properties update --account-name ${azurerm_storage_account.st_core.name} --static-website --index-document index.html --404-document index.html"
  }
}

Remote, Local and Self-configured Backend State Support

The task currently supports the following backend configurations

  • local (default for terraform) - State is stored on the agent file system.
  • azurerm - State is stored in a blob container within a specified Azure Storage Account.
  • self-configured - State configuration will be provided using environment variables or command options. Environment files can be provided using Secure Files Library in AzDO and specified in Secure Files configuration field. Command options such as -backend-config= flag can be provided in the Command Options configuration field.

If azurerm selected, the task will prompt for a service connection and storage account details to use for the backend.

- task: TerraformCLI
    displayName: 'terraform init'
    inputs:
        command: init
        backendType: azurerm
        backendServiceArm: 'My Azure Service Connection'
        # create backend storage account if doesn't exist
        ensureBackend: true
        backendAzureRmResourceGroupName: 'my-backend-resource-group'
        # azure location shortname of the backend resource group and storage account
        backendAzureRmResourceGroupLocation: 'eastus'
        backendAzureRmStorageAccountName: 'my-backend-storage-account'
        # azure storage account sku, used when creating the storage account
        backendAzureRmStorageAccountSku: 'Standard_RAGRS'
        # azure blob container to store the state file
        backendAzureRmContainerName: 'my-backend-blob-container'
        # azure blob file name
        backendAzureRmKey: infrax.tfstate

Automated Remote Backend Creation

The task supports automatically creating the resource group, storage account, and container for remote azurerm backend. To enable this, set the ensureBackend input to true and provide the resource group, location, and storage account sku. The defaults are 'eastus' and 'Standard_RAGRS' respectively. The task will utilize AzureCLI to create the resource group, storage account, and container as specified in the backend configuration.

Secure Variable Secrets

There are multiple methods to provide secrets within the vars provided to terraform commands. The commandOptions input can be used to specify individual -var inputs. When using this approach pipeline variables can be used as -var secret=$(mySecretPipelineVar). Additionally, either a terraform variables file or a env file secured in Secure Files Library of Azure DevOps pipeline can be specified. Storing sensitive var and env files in the Secure Files Library not only provides encryption at rest, it also allows the files to have different access control applied than that of the Source Repository and Build/Release Pipelines.

- task: TerraformCLI@0
    displayName: 'terraform plan'
    inputs:
        command: plan
        environmentServiceName: 'My Azure Service Connection'
        # guid for the secure file to use. Can be standard terraform vars file or .env file.
        secureVarsFile: 446e8878-994d-4069-ab56-5b302067a869
        # specify a variable input via pipeline variable
        commandOptions: '-var secret=$(mySecretPipelineVar)'

Secure Env Files

If the Secure Variables file name is *.env, it is referred as .env file. This task loads environment variables from the .env file.

.env file example

KEY1=VALUE1
KEY2=VALUE2

Terraform Output to Pipeline Variables

The TerraformCLI task supports running the Terraform output command. When this is run, pipeline variables will be created from each output variable emitted from the terraform output command. Sensitive variables will be set as secret pipeline variables and their values will not be emitted to the pipeline logs.

For example, an output variable named some_string will set a pipeline variable named TF_OUT_SOME_STRING.

This feature currently only supports primitive types string, bool, and number. Complex typed outputs such as tuple and object will be excluded from the translation.

Template has output defined

output "some_string" {
  sensitive = false
  value = "somestringvalue"
}

output "some_sensitive_string" {
  sensitive = true
  value = "some-string-value"
}

Pipeline configuration to run terraform output command

- task: TerraformCLI@0
    displayName: 'terraform output'
    inputs:
        command: output

Use output variables as pipeline variables

- bash: |
        echo 'some_string is $(TF_OUT_SOME_STRING)'        
        echo 'some_sensitive_string is $(TF_OUT_SOME_SENSITIVE_STRING)'
    displayName: echo tf output vars

Note that $(TF_OUT_SOME_SENSITIVE_STRING) will be redacted as *** in the pipeline logs.

Terraform Plan View (NEW)

The extension includes a feature to render terraform plans within the pipeline run summary. To use this feature publishPlanResults input must be provided when running terraform plan via the TerraformCLI task. Then input should be set to the name that should be assigned to the plan.

- task: TerraformCLI@0
    displayName: 'terraform plan'
    inputs:
        command: plan
        environmentServiceName: 'My Azure Service Connection'
        publishPlanResults: 'my_plan_name'

Terraform Plan View Has Results

If the publishPlanResults input is not provided, then no plans will be published. In this case, the view will render empty with a message indicating no plans were found.

Terraform Plan View No Results

**Note The name set on publishPlanResults is only used for rendering in the view. It does not cause the cli to implicitly save plan output on the agent with that name.

Terraform Plan Change Detection

When running terraform plan with -detailed-exitcode, a pipeline variable will be set to indicate if any changes exist in the plan. TERRAFORM_PLAN_HAS_CHANGES will be set to true if plan detected changes. Otherwise, this variable will be set to false. This can be used in conjunction with Custom Condition expression under Control Options tab of the task to skip terraform apply if no changes were detected.

- task: TerraformCLI@0
    displayName: 'terraform plan'
    inputs:
        command: plan
        environmentServiceName: 'My Azure Service Connection'
        commandOptions: '-out=$(System.DefaultWorkingDirectory)/terraform.tfplan -detailed-exitcode'

Run apply only if changes are detected.

- task: TerraformCLI@0
    displayName: 'terraform apply'
    condition: and(succeeded(), eq(variables['TERRAFORM_PLAN_HAS_CHANGES'], 'true'))
    inputs:
        command: apply
        environmentServiceName: 'My Azure Service Connection'
        commandOptions: '$(System.DefaultWorkingDirectory)/terraform.tfplan'

Terraform Plan Destroy Detection

The task now has the ability to set a pipeline variable TERRAFORM_PLAN_HAS_DESTROY_CHANGES if a generated plan has destroy operations. To utilize this, run terraform plan and set the -out=my-plan-file-path to write the generated plan to a file. Then run terraform show and provide the path to the generated plan file in the Target Plan or State File Path input field. If show, detects a destroy operation within the plan file, then the pipeline variable TERRAFORM_PLAN_HAS_DESTROY_CHANGES will be set to true.

- task: TerraformCLI@0
    displayName: 'terraform plan'
    inputs:
        command: plan
        environmentServiceName: 'My Azure Service Connection'
        commandOptions: '-out=$(System.DefaultWorkingDirectory)/terraform.tfplan'

Run show to detect destroy operations

- task: TerraformCLI@0
    displayName: 'terraform show'
    inputs:
        command: show
        inputTargetPlanOrStateFilePath: '$(System.DefaultWorkingDirectory)/terraform.tfplan'

Skip apply if destroy operations

- task: TerraformCLI@0
    displayName: 'terraform apply'
    condition: and(succeeded(), eq(variables['TERRAFORM_PLAN_HAS_DESTROY_CHANGES'], 'false'))
    inputs:
        command: apply
        environmentServiceName: 'My Azure Service Connection'
        commandOptions: '$(System.DefaultWorkingDirectory)/terraform.tfplan'
  • Contact us
  • Jobs
  • Privacy
  • Terms of use
  • Trademarks
© 2019 Microsoft