Q: set_fact only if all of the items in the loop are true or if one of them is false
A: Count the items. For example
- set_fact:
dirs_missing: "{{ _all|int - _exist|int }}"
vars:
_all: "{{ dir_check.results|length }}"
_exist: "{{ dir_check.results|
map(attribute='stat.exists')|
select|length }}"
gives (in your case)
dirs_missing: '1'
Now, you can set whatever you want, e.g.
- name: check all of the dirs are created
set_fact:
all_dirs_created: true
when: dirs_missing|int == 0
- debug:
msg: "Not all dirs are created!
(Exactly {{ dirs_missing }} missing.)"
when: all_dirs_created is not defined
gives
TASK [check all of the dirs are created] ********************************
skipping: [localhost]
TASK [debug] ************************************************************
ok: [localhost] =>
msg: Not all dirs are created! (Exactly 1 missing.)
You can simplify the code by using the filter counter from the latest collection Community.General. See Counting elements in a sequence, e.g.
- name: check all of the dirs are created
set_fact:
all_dirs_created: true
when: _counts[false] is not defined
vars:
_counts: "{{ dir_check.results|
map(attribute='stat.exists')|
community.general.counter }}"
The solutions above counted the items of the list to enable the evaluation of the option if one of them is false. The code can be simplified further if the counting of the items is not necessary. For example, test if all items are true
- name: check all of the dirs are created
set_fact:
all_dirs_created: true
when: dir_check.results|map(attribute='stat.exists') is all
However, then you have to test the existence of the variable all_dirs_created. More practical is setting both values. Ultimately, the expected functionality of your last two tasks can be reduced to the code below
- name: check all of the dirs are created
set_fact:
all_dirs_created: "{{ dir_check.results|
map(attribute='stat.exists') is all }}"
- debug:
msg: Not all dirs are created!
when: not all_dirs_created