1
votes

I have a Azure DevOps YAML Pipeline to execute a Terraform deployment using the Terraform by MS DevLabs extension and an Azure Resource Manager service connection.

The last working state was using a pipeline template yaml file however I had to configure a parameter within the template and call the variable using the template expression syntax.

...
...
stages:
- stage: Plan
  displayName: Terrafom Plan
  jobs:  
  - job: DEV PLAN
    displayName: Plan (DEV)
    pool:
      vmImage: "ubuntu-latest"
    variables:
      az_service_connection: "MyServiceConnection"
      tf_environment: "DEV"
      tf_state_rg: "DEV"
      tz_state_location: "canadacentral"
      tf_state_stgacct_name: "mystorageaccuontname1231231"
      tf_state_container_name: "tfstate"
    steps:
    - template: templates/terraform-plan.yml
      parameters:
        az_service_connection: ${{ variables.az_service_connection }}
...
...
steps:
  - task: terraformInstaller@0
    displayName: "Install Terraform $(tf_version)"
    inputs:
      terraformVersion: $(tf_version)
  - task: TerraformTaskV1@0
    displayName: "Run > terraform init"
    inputs:
      command: "init"
      commandOptions: "-input=false"
      backendServiceArm: ${{ parameters.az_service_connection }}
...
...

I believe the reason why this works is because the template expression syntax ${{ variables.varname}} evaluates at compile time vs. runtime. If I didn't do it this way, i'd either get $(az_service_connection) passed into the backendServiceArm input or an empty value.

With the introduction of variable groups, i'm now facing similar behavior. I expect that the variable group evaluates after the template expression variable which causes ${{ variables.az_service_connection }} to have an empty value. I am unsure how to get this working.

How can I use variable groups with a pipeline template that uses a service connection?

1

1 Answers

1
votes

I used $() syntax to pass arm connection to template:

Template file:

parameters:
- name: 'instances'
  type: object
  default: {}
- name: 'server'
  type: string
  default: ''
- name: 'armConnection'
  type: string
  default: ''

steps:
- task: TerraformTaskV1@0
  inputs:
    provider: 'azurerm'
    command: 'init'
    backendServiceArm: '${{ parameters.armConnection }}'
    backendAzureRmResourceGroupName: 'TheCodeManual'
    backendAzureRmStorageAccountName: 'thecodemanual'
    backendAzureRmContainerName: 'infra'
    backendAzureRmKey: 'some-terrform'
- ${{ each instance in parameters.instances }}:
  - script: echo ${{ parameters.server }}:${{ instance }}

Main file:

trigger:
  branches:
    include:
      - master
  paths:
    include:
      - stackoverflow/09-array-parameter-for-template/*

# no PR triggers
pr: none

pool:
  vmImage: 'ubuntu-latest'

variables:
- group: my-variable-group
- name: my-passed-variable
  value: $[variables.myhello] # uses runtime expression

steps:
- template: template.yaml
  parameters:
    instances: 
    - test1
    - test2
    server: $(myhello)
    armConnection: $(armConnection)

Note: Group my-variable-group contains armConnection variable