7

I am trying to execute an Azure Devops Job on a specific pool based on a condition. The goal is to switch between self-hosted agent and microsoft agent. Here is the configuration:

parameters:
  custom_agent: true

jobs:
  - job: Test
    displayName: Test job
  - ${{ if eq(parameters.custom_agent, true) }}:
    - pool:
      name: mypool
      demands:
        - agent.os -equals Linux
  - ${{ if eq(parameters.custom_agent, false) }}:
    - pool:
        vmImage: 'ubuntu-latest'
    steps:
      - task: npmAuthenticate@0

enter image description here

Any ideas ?

user2382684
  • 125
  • 2
  • 6
  • I believe the main issue is with the dashes. Dash means an item of a list. Without dash, it is a dictionary entry. In the "jobs" property, there is a list of length 3 -- the first item is a dictionary with keys "job" and "displayName", the other two are single-element dictionaries whose keys start with `${{ `... The conditions should be at the same level as the `job` and `displayName` entries. Also, they should contain a dictionary, not a list. – Palec Jan 09 '23 at 15:55

5 Answers5

7

The below example solved my requirement

parameters:
  - name: 'vmImage'
    type: string
    default: 'ubuntu-latest'
  - name: 'agentPool'
    type: string
    default: ''

jobs:
  - job: 'Example'
    pool:
      ${{ if ne(parameters.agentPool, '') }}:
        name: ${{ parameters.agentPool }}
      ${{ if eq(parameters.agentPool, '') }}:
        vmImage: ${{ parameters.vmImage }}
    steps:
      - script: example
Marius
  • 99
  • 1
  • 1
  • 2
    Note: this works fine if the pool definition is inside a job definition, but for some reason it isn't allowed if the pool definition is higher up (e.g. at release level). – Vince Bowdren Nov 09 '21 at 11:21
4

We can specify conditions under which a step, job, or stage will run. We can configure the jobs in the pipeline with different condition entries, and set demands based on those conditions.

A skeleton version looks like this:

parameters:
- name: custom_agent
  displayName: Pool Image
  type: boolean
  default: True

jobs:
  - job: selfhostedagent
    condition: eq(${{ parameters.custom_agent }}, True)
    displayName: 'self_hosted agent'
    pool:
      name: Default
      demands:
        - Agent.Name -equals WS-VITOL-01
    steps:
      - script: echo self_hosted agent

  - job: hostedagent
    condition: eq(${{ parameters.custom_agent }}, False)
    displayName: 'hosted agent'
    pool:
      vmImage: 'ubuntu-latest'
      
    steps:
      - script: echo hosted agent

Update1

In addition, we can configure task template, then use the template in the steps.

Result:

enter image description here

Vito Liu
  • 7,525
  • 1
  • 8
  • 17
4

Another apporach to conditionally select pools if you use non-vm pools:

variables:
- ${{ if eq(parameters.custom_agent, true) }}:
  - name: testJobPool
    value: mypool
- ${{ if eq(parameters.custom_agent, false) }}:
  - name: testJobPool
    value: mypool_second

jobs:
- job: Test
  displayName: Test job
  pool:
    name: $(testJobPool)
  steps:
    - task: npmAuthenticate@0

This has proved working.

GY_
  • 398
  • 3
  • 17
0

The one thing I haven't seen fully clarified is that while this isn't possible at the "pipeline" level (ie set it once globally) because parameters are a runtime scoped thing and setting pool: at the pipeline level isn't able to wait for the runtime parameters, BUT you can still EASILY override the agent per stage, job, or step.

To do it in a straightforward and consistent fashion, you can use a templated stage/job/step that accepts the agentPool as a parameter (but only the vmImage: portion), then you can use a YAML conditional to detect whether it is one of the valid Azure DevOps managed agents windows-latest/ubuntu-latest/macos-latest/etc with the few specific versions, IF NOT then you can assume it is a self hosted pool and use that as the name: attribute of pool: vs vmImage:.

Thanks to Vito, Marius and GY for their helpful examples.

azure-pipelines.yml

parameters:
- name: agentPool
  type: string
  default: windows-latest
  # Valid Azure images: https://github.com/actions/runner-images#available-images
  values:
    - selfHosted1
    - selfHosted2
    - windows-latest
    - windows-2019
    - macos-latest
    - ubuntu-latest

stages:
  - template: azure-deploy.yml
    parameters:
      agentPool: ${{ parameters.agentPool }}

azure-deploy.yml

parameters:
- name: agentPool
  type: string
  default: windows-latest

stages:
- stage: Deploy
  displayName: Deploy Bicep
  pool:
    ${{ if or(or(startsWith(parameters.agentPool, 'windows'), startsWith(parameters.agentPool, 'macos')), startsWith(parameters.agentPool, 'ubuntu')) }}:
      vmImage: ${{ parameters.agentPool }}
    ${{ if not(or(or(startsWith(parameters.agentPool, 'windows'), startsWith(parameters.agentPool, 'macos')), startsWith(parameters.agentPool, 'ubuntu'))) }}:
      name: ${{ parameters.agentPool }}
  jobs: <snipped to avoid too much boilerplate>
dragon788
  • 3,583
  • 1
  • 40
  • 49
-2

It looks like pool is not a valid property of a job type

Try switching your job to a deployment type:

jobs:

  - deployment: Test
  - ${{ if eq(parameters.custom_agent, true) }}:
     pool:
      name: mypool
      demands:
        agent.os -equals Linux
    strategy:
        runOnce:    
          deploy:
            steps:
DreadedFrost
  • 2,602
  • 1
  • 11
  • 29
  • Ok thanks :) I did not test this but I presume you did it and it works. But I don't like the idea of use a deployment for make a test. It seems strange !? No ? – user2382684 Aug 07 '20 at 13:39
  • I have not tested with your specific YAML. The deployment job type is the delivery aspect of the YAML Pipleline. Thus even if it is a test site deployment is just the term that code/infrastructure is being deployed to a given environment. – DreadedFrost Aug 07 '20 at 14:09
  • 1
    I tested this, it can't be parsed. `pool:` after `- ${{ if eq(parameters.custom_agent, true) }}:` is invalid. – GY_ Mar 25 '21 at 18:41