ansible

How to break a loop in Ansible when some condition matched?


I need a method to stop looping in Ansible like break in for statement in C++ or Bash. For example, I need to the last value before the loop scan to 0.

The default/main.yml

---
os_vars:
  - 8
  - 10
  - 15
  - 6
  - 0
  - 7
  - 25

The tasks/main.yml

- name: Debug variables
  ansible.builtin.set_fact:
    a: "{{ item }}"
  loop: "{{ os_vars }}"
  when: item > 0

And the output

TASK [test_role : Debug variables] *********************************************
ok: [localhost] => (item=8)
ok: [localhost] => (item=10)
ok: [localhost] => (item=15)
ok: [localhost] => (item=6)
skipping: [localhost] => (item=0)
ok: [localhost] => (item=7)
ok: [localhost] => (item=25)

I know I can set other bool variable to control the looping didn't assign a with following items, but I also need to save time to increase performance of this playbook, as sometime this looping body might be a huge array and we don't need to check the following items when some condition matched ...

Please share your comments. Thanks in advance.


Solution

  • Q: "I know I can set other bool variable to control the looping didn't assign a with following items"

    Right, as there are

    Similar Q&A

    and many more ...

    Q: "I need a method to stop looping in Ansible like break in for statement in C++ or Bash."

    Such is not available. You can't break out the loop, you can only implement to skip.

    This is because

    Q: "I also need to save time to increase performance of this playbook, as sometime this looping body might be a huge array and we don't need to check the following items when some condition matched."

    If you like or need to implement such behavior you may need to write something by yourself. See in example Should you develop a module? and Developing modules.

    An other approach can be to do some pre-processing on the data structure, os_vars list to have after that only

    os_vars:
      - 8
      - 10
      - 15
      - 6
    

    to provide for the loop. Then, no break or if then else construct would be necessary at all.

    Further Reading


    Based on the given comments and as I understood the Use Case a possible solution approach without BREAK, when: or any IF, THEN, ELSE construct.

    A minimal example playbook

    ---
    - hosts: localhost
      become: false
      gather_facts: false
    
      vars:
    
        os_vars:
          - 8
          - 10
          - 15
          - 6
          - 0
          - 7
          - 25
    
      tasks:
    
      - name: Loop up to idx
        debug:
          msg: "{{ item }}"
        loop: "{{ os_vars[:idx | int] }}"
        loop_control:
          extended: true
          label: "{{ ansible_loop.index }}"
        # Get index of zero (0) value
        vars:
          idx: "{{ os_vars.index(os_vars | min) }}"
    

    will result into an output of

    TASK [Loop up to idx] ********
    ok: [localhost] => (item=1) =>
      msg: 8
    ok: [localhost] => (item=2) =>
      msg: 10
    ok: [localhost] => (item=3) =>
      msg: 15
    ok: [localhost] => (item=4) =>
      msg: 6
    

    Based On