m_messiah
m_messiah

Reputation: 2264

Skip certain items on condition in ansible with_items loop

Is it possible to skip some items in Ansible with_items loop operator, on a conditional, without generating an additional step?

Just for example:

- name: test task
    command: touch "{{ item.item }}"
    with_items:
      - { item: "1" }
      - { item: "2", when: "test_var is defined" }
      - { item: "3" }

in this task I want to create file 2 only when test_var is defined.

Upvotes: 27

Views: 43320

Answers (5)

Kevin Gigiano
Kevin Gigiano

Reputation: 111

I recently ran into this problem and none of the answers I found were exactly what I was looking for. I wanted a way to selectively include a with_item based on another variable. Here is what I came up with:

- name: Check if file exists
  stat: 
    path: "/{{item}}"
  with_items: 
    - "foo"
    - "bar"
    - "baz"
    - "{% if some_variable == 'special' %}bazinga{% endif %}"
   register: file_stat

- name: List files
  shell: echo "{{item.item | basename}}"
  with_items:
    - "{{file_stat.results}}"
  when: 
    - item.stat | default(false) and item.stat.exists

When the above plays are run, the list of items in file_stat will only include bazinga if some_variable == 'special'

Upvotes: 3

lonix
lonix

Reputation: 20591

I had a similar problem, and what I did was:

...
with_items:
  - 1
  - 2
  - 3
when: (item != 2) or (item == 2 and test_var is defined)

Which is simpler and cleaner.

Upvotes: 8

nitzmahone
nitzmahone

Reputation: 13940

The when: conditional on the task is evaluated for each item. So in this case, you can just do:

...
with_items:
- 1
- 2
- 3
when: item != 2 and test_var is defined

Upvotes: 7

Deepali Mittal
Deepali Mittal

Reputation: 1032

What you want is that file 1 and file 3 always gets created but file 2 is created only when test_var is defined. If you use ansible's when condition it works on complete task and not on individual items like this :

- name: test task
  command: touch "{{ item.item }}"
  with_items:
      - { item: "1" }
      - { item: "2" }
      - { item: "3" }
  when: test_var is defined

This task will check the condition for all three line items 1,2 and 3.

However you can achieve this by two simple tasks :

- name: test task
  command: touch "{{ item }}"
  with_items:
      - 1 
      - 3

- name: test task
  command: touch "{{ item }}"
  with_items:
      - 2
  when: test_var is defined

Upvotes: 0

Petro026
Petro026

Reputation: 1309

The other answer is close but will skip all items != 2. I don't think that's what you want. here's what I would do:

- hosts: localhost
  tasks:
  - debug: msg="touch {{item.id}}"
    with_items:
    - { id: 1 }
    - { id: 2 , create: "{{ test_var is defined }}" }
    - { id: 3 }
    when: item.create | default(True) | bool

Upvotes: 29

Related Questions