Skip the whole loop in Ansible
Asked Answered
M

3

6

What should I do if I want to skip the whole loop in Ansible?

According to guidelines,

While combining when with with_items (see Loops), ... when statement is processed separately for each item.

Thereby while running the playbook like that

---
- hosts: all
  vars:
    skip_the_loop: true
  tasks:
    - command: echo "{{ item }}"
      with_items: [1, 2, 3]
      when: not skip_the_loop

I get

skipping: [localhost] => (item=1) 
skipping: [localhost] => (item=2) 
skipping: [localhost] => (item=3)

Whereas I don't want a condition to be checked every time.

Then I came up with the idea of using inline conditions

- hosts: all
  vars:
    skip_the_loop: true
  tasks:
    - command: echo "{{ item }}"
      with_items: "{{ [1, 2, 3] if not skip_the_loop else [] }}"

It seems to solve my problem, but then I get nothing as output. And I want only one line saying:

skipping: Loop has been skipped
Mufti answered 22/6, 2016 at 9:45 Comment(4)
I don't think you can get a better result than your second one. You could just add a debug statement afterwards if you really need something printed outAntipope
@SztupY, I've already done it, but still it is not the desired result, unfortunatelyMufti
any reason you don't want the condition to run for each loop? Is it only because of the ugly output, or because the conditional checks take a lot of time / resource?Antipope
mostly because of ugly output; besides, not only does this condition have nothing in common with an item in loop, but it may be quite complex as wellMufti
S
3

You should be able to make Ansible evaluate the condition just once with Ansible 2's blocks.

---
- hosts: all
  vars:
    skip_the_loop: true
  tasks:
    - block:
      - command: echo "{{ item }}"
        with_items: [1, 2, 3]
      when: not skip_the_loop

This will still show skipped for every item and every host but, as udondan pointed out, if you want to suppress the output you can add:

display_skipped_hosts=True

to your ansible.cfg file.

Stellate answered 22/6, 2016 at 13:2 Comment(6)
That seems to be what I asked for, but it still does not suppress output. For the output is about skipping every task, not about skipping the block. Is there any way to override the output?Mufti
Does this really work? I would have thought the when just gets passed down to the contained tasks of the block. But if that works that is great!Equalitarian
@NickRoz You can not suppress output on task level. Though you can disable the output of skipped tasks globally in your ansible config: docs.ansible.com/ansible/…Equalitarian
@undondan, don't know how it really works, every command under the block will be marked as skipped in the terminal. Although the loop is not the best example, but in case you have multiple commands to do it seems to be a beneficial optionMufti
I was more addressing the conditional evaluation in the event that it's complicated because I'm not sure I see the benefit in suppressing the output. I'll edit my answer to include the Ansible config change to suppress skipped output as well if that's what you really wantStellate
not to mention large loops take many minutes to print to the screen , i'm trying to save time more than anythingSheerness
B
1

If there's a lot of items, you might find this solution runs faster. It loops over the empty list when skip_the_loop is true.

---
- hosts: all
  vars:
    skip_the_loop: true
  tasks:
    - command: echo "{{ item }}"
      loop: "{{ skip_the_loop | ternary([], [1, 2, 3]) }}"
Baccivorous answered 30/5, 2023 at 3:7 Comment(0)
M
0

This can be done easily using include along with condition:

hosts: all
  vars:
    skip_the_loop: true
  tasks:
    - include: loop
      when: not skip_the_loop

Whereas somewhere in tasks/ there is a file called loop.yml:

- command: echo "{{ item }}"
  with_items: [1, 2, 3]
Mufti answered 1/7, 2016 at 8:51 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.