Search code examples
loopsazure-devopsyamlazure-pipelines-yaml

ADO YAML pipeline - Passing object parameter to a template


I've got a yaml pipeline calling a template:

parameters:
  - name: Food1
    type: string
  - name: Food2
    type: string
  - name: Food3
    type: string

jobs:
  - template: .\testLoop.yml
    parameters: 
      foodObject: |
        Food1: ${{ parameters.Food1 }}
        Food2: ${{ parameters.Food2 }}
        Food3: ${{ parameters.Food3 }}

The template's input parameter is of "object" type:

parameters:
  - name: foodObject
    type: object
    default:
    - Food1: 'Apple'
    - Food2: 'Bread'
    - Food3: 'Cheese'
jobs:
  - job: test_loop
    displayName: 'Test Loop'
    pool: 
      vmImage: windows-latest
    steps:
      - ${{ each food in parameters.foodObject }} :
        - powershell: |
            Write-Host "Food name is '${{ food.key }}' and value is '${{ food.value }}'"

However I get an error:

error regarding template input

If the pipeline has an object parameter and I send that to the template, it works.

It seems like by "building" the object myself from string parameters, it never actually becomes a "mapping" (???) even though there are key value pairs separated by ":".

I've tried different formatting using " or ' or multiple lines or spaces and whatnot, and can't get this to work.

The error doesn't seem to refer to the input parameter, but rather to the "each" loop that is on line 9.

Any ideas how to fix this?


Solution

  • I can reproduce the same issue when using your YAML sample.

    The cause of the issue can be that the format of the object parameters has issue when you pass to the template.

    To solve this issue, you can use the following sample:

    Main YAML:

    parameters:
      - name: Food1
        type: string
      - name: Food2
        type: string
      - name: Food3
        type: string
    
    jobs:
      - template: .\testLoop.yml
        parameters: 
          foodObject: 
          - name: food1
            value: ${{ parameters.Food1 }}
          - name: food2
            value: ${{ parameters.Food2 }}
          - name: food3
            value: ${{ parameters.Food3 }}
    

    Template YAML:

    parameters:
      - name: foodObject
        type: object
        default:
        - name: food1
          value: apple
        - name: food2
          value: Bread
        - name: food3
          value: Cheese
    jobs:
      - job: test_loop
        displayName: 'Test Loop'
        pool: 
          vmImage: windows-latest
        steps:
          - ${{ each food in parameters.foodObject }} :
            - powershell: |
                Write-Host "Food name is '${{ food.name }}' and value is '${{ food.value }}'"
    

    Result:

    enter image description here

    Update:

    Here is another format of the YAML sample

    Main:

    parameters:
      - name: Food1
        type: string
      - name: Food2
        type: string
      - name: Food3
        type: string
    
    jobs:
      - template: .\testLoop.yml
        parameters: 
          foodObject: 
            Food1: ${{ parameters.Food1 }}
            Food2: ${{ parameters.Food2 }}
            Food3: ${{ parameters.Food3 }}
    

    Template:

    parameters:
      - name: foodObject
        type: object
        default:
        - Food1: 'Apple'
        - Food2: 'Bread'
        - Food3: 'Cheese'
    jobs:
      - job: test_loop
        displayName: 'Test Loop'
        pool: 
          vmImage: windows-latest
        steps:
          - ${{ each food in parameters.foodObject }} :
            - powershell: |
                Write-Host "Food name is '${{ food.key }}' and value is '${{ food.value }}'"