23

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.

guido
  • 18,864
  • 6
  • 70
  • 95
m_messiah
  • 2,115
  • 2
  • 15
  • 12

5 Answers5

26

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
Petro026
  • 1,269
  • 8
  • 6
7

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
nitzmahone
  • 13,720
  • 2
  • 36
  • 39
6

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.

lonix
  • 14,255
  • 23
  • 85
  • 176
2

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'

Kevin Gigiano
  • 101
  • 1
  • 1
0

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
Deepali Mittal
  • 996
  • 13
  • 20
  • your statement that "ansible's when condition works on complete task and not on individual items" is wrong: the condition is evaluated individually for each item. see http://docs.ansible.com/ansible/playbooks_conditionals.html#loops-and-conditionals – guido May 12 '16 at 17:50
  • You got me wrong, i myself said the same thing what you are saying. See in my answer i also mentioned this "This task will check the condition for all three line items 1,2 and 3". By above statement i meant that this when condition would not work only for one item but for all which means for whole task. – Deepali Mittal May 14 '16 at 07:10