skip to Main Content

In an Azure DevOps pipeline template I need to pass variables as a dictionary to another template which will use an ansible task to process all keys in the dictionary.

The type: object seems appropriate, but I’m looking for a working example.

main-template.yml

trigger:
- main

stages:
- stage: Deploy
  jobs:
  - job: DeployJob
    pool:
      vmImage: 'ubuntu-latest'
    steps:
    - template: ansible-template.yml
      parameters:
        ansibleVars:
          var1: value1
          var2: value2

ansible-template.yml

parameters:
- name: ansibleVars
  type: object
  default: {}

jobs:
- job: AnsibleJob
  pool:
    vmImage: 'ubuntu-latest'
  steps:
  - task: UsePythonVersion@0
    inputs:
      versionSpec: '3.x'
      addToPath: true

  - script: |
      python -m pip install ansible-core
    displayName: 'Install Ansible'

  - script: |
      echo "${{ parameters.ansibleVars  }}" > vars.yml
    displayName: 'Create vars file'

  - task: Ansible@0
    displayName: 'Run playbook'
    inputs:
      ansibleInterface: 'agentMachine'
      playbookPathOnAgentMachine: './ansible/playbook.yml'
      inventoriesAgentMachine: 'file'
      inventoryFileOnAgentMachine: './ansible/inventory/hosts'
      args: -vv -e @vars.yaml
    failOnStdErr: false

2

Answers


  1. According to the documentation, you can use vars from a JSON or YAML file:

    ansible-playbook release.yml --extra-vars "@some_file.json"
    ansible-playbook release.yml --extra-vars "@some_file.yaml"
    

    In your pipeline you can use convertToJson to convert a parameter to a json string and then generate a json file and use it in your Ansible@0 task.

    Example

    parameters:
      - name: ansibleVars
        type: object
        default:
          version: 1.0.0
          other_varialbe: foo
      - name: varsFile
        type: string
        default: $(Agent.TempDirectory)/ansible-vars.json
    
    trigger: none
    
    pool:
      vmImage: 'ubuntu-latest'
    
    steps:
      - script: |
          echo ${ANSIBLE_VARS} > ${ANSIBLE_VARS_FILE}
          cat ${ANSIBLE_VARS_FILE}
        displayName: Create json variables file
        env:
          ANSIBLE_VARS_FILE: ${{ parameters.varsFile }}
          ANSIBLE_VARS: ${{ convertToJson(parameters.ansibleVars) }}
      
      - task: Ansible@0
        displayName: 'Run playbook'
        inputs:
          ansibleInterface: 'agentMachine'
          playbookPathOnAgentMachine: './ansible/playbook.yml'
          inventoriesAgentMachine: 'file'
          inventoryFileOnAgentMachine: './ansible/inventory/hosts'
          args: -vv -e @${{ parameters.varsFile }}  # <-------------- use generated json file
        failOnStdErr: false
    

    Please note I’m assigning the json string to a task environment variable instead of using it directly in the script body – this way I don’t need to bother escaping quotes and other special characters:

      - script: |
          # ...
        env:
          ANSIBLE_VARS: ${{ convertToJson(parameters.ansibleVars) }}
    
    Login or Signup to reply.
  2. You can reference the sample below to pass dictionary into the template YAML:

    1. The template YAML
    # templates/steps.yml
    
    parameters:
    - name: vars
      type: object
      default: []
    
    steps:
    - powershell: |
        Write-Host "var1 = $env:var1"
        Write-Host "var2 = $env:var2"
        Write-Host "var3 = $env:var3"
      displayName: 'Show all vars'
      env:
        ${{ parameters.vars }}
    
    - ${{ each var in parameters.vars }}:
      - powershell: |
          Write-Host "Key = ${{ var.Key }}"
          Write-Host "Value = ${{ var.Value }}"
        displayName: 'Show var - ${{ var.Key }}'
    
    1. The main YAML.
    # azure-pipelines.yml
    
    steps:
    - template: templates/steps.yml
      parameters:
        vars:
          var1: valu1
          var2: valu2
          var3: valu3
    

    enter image description here


    If you want to pass all the key-value pairs to the args field of the Ansible@0 task, you can set the template like as below.

    # templates/steps.yml
    
    parameters:
    - name: vars
      type: object
      default: []
    
    steps:
    - powershell: Write-Host "##vso[task.setvariable variable=argVar;]empty"
      displayName: 'Set argVar'
    
    - ${{ each var in parameters.vars }}:
      - powershell: |
          Write-Host "Key = ${{ var.Key }}"
          Write-Host "Value = ${{ var.Value }}"
          if ("$(argVar)" -ne "empty" ) {
            Write-Host "##vso[task.setvariable variable=argVar;]$(argVar) ${{ var.Key }}=${{ var.Value }}"
          }
          else {
            Write-Host "##vso[task.setvariable variable=argVar;]${{ var.Key }}=${{ var.Value }}"
          }
        displayName: 'Show var - ${{ var.Key }}'
    
    - powershell: Write-Host "$(argVar)"
      displayName: 'Show var argVar'
    
    - task: Ansible@0
      displayName: 'Run playbook'
      inputs:
        playbookPathOnAgentMachine: path/to/playbook.yml
        inventoriesAgentMachine: file
        inventoryFileOnAgentMachine: path/to/hosts
        args: '$(argVar)'
    

    enter image description here


    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search