# Doubt regarding loops and conditionals

**URL:** <https://forum.ansible.com/t/doubt-regarding-loops-and-conditionals/32257>\
**Category:** Ansible Project\
**Created:** [February 17, 2020, 8:11pm UTC](https://forum.ansible.com/t/doubt-regarding-loops-and-conditionals/32257 "2020-02-17T20:11:07Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Nuno\_Jordao](https://avatars.discourse-cdn.com/v4/letter/n/a4c791/32.png) [@Nuno\_Jordao](https://forum.ansible.com/u/Nuno_Jordao)\
**Post date:** [February 17, 2020, 8:11pm UTC](https://forum.ansible.com/t/doubt-regarding-loops-and-conditionals/32257/1 "2020-02-17T20:11:07Z")

</div>

Hello,

I have a doubt regarding loops and conditionals that maybe someone can make it clear to me.  
In the documentation is stated that:

“When combining [Conditionals](https://docs.ansible.com/ansible/latest/user_guide/playbooks_conditionals.html#playbooks-conditionals) with a loop, the `when:` statement is processed separately for each item.”

But if I do this:

- name: “test loop”  
debug:  
msg: “test”  
loop: “{{nulo}}”  
when: nulo is defined

where “nulo” is an undefined variable. Here the task skips instead of failing. If I read the documentation to the letter it should fail as it would only do the test inside the loop.

Also, this issue:  
[https://github.com/ansible/ansible/issues/45976](https://github.com/ansible/ansible/issues/45976)

has a slightly different variation of my loop which fails instead of skipping.

My observed behaviour is of course the better one as allows to test the list before running loop, but should I trust it? It is the same in all versions of Ansible?

Thank you for your help. Regards,

Nuno Jordão

---

<div class="post-metadata">

**Author:** ![Mauricio\_Tavares](https://avatars.discourse-cdn.com/v4/letter/m/b5e925/32.png) [@Mauricio\_Tavares](https://forum.ansible.com/u/Mauricio_Tavares)\
**Post date:** [February 17, 2020, 8:41pm UTC](https://forum.ansible.com/t/doubt-regarding-loops-and-conditionals/32257/2 "2020-02-17T20:41:24Z")

</div>

> Hello,
> 
> I have a doubt regarding loops and conditionals that maybe someone can make it clear to me.  
> In the documentation is stated that:
> 
> "When combining Conditionals with a loop, the when: statement is processed separately for each item."

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;I am not sure since in your example the when is applied to the  
debug, i.e. if when is false the debug task is not run.

> But if I do this:
> 
> &nbsp;&nbsp;&nbsp;&nbsp;- name: "test loop"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;debug:  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg: "test"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop: "{{nulo}}"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when: nulo is defined

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;That is an interesting way to loop.

> where "nulo" is an undefined variable. Here the task skips instead of failing. If I read the documentation to the letter it should fail as it would only do the test inside the loop.  
> Also, this issue:  
> [https://github.com/ansible/ansible/issues/45976](https://github.com/ansible/ansible/issues/45976)
> 
> has a slightly different variation of my loop which fails instead of skipping.

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The differences are more than slightly. having "null\_var" as  
the when test is not the same as "null\_var is defined."

when: null\_var is defined

is testing whether null\_var is defined, returning true or false; it  
could not care less about its contents though. So, it does not break  
when it is not defined.

when: null\_var | default(False)

would also work since it also gives an option for when null\_var is not  
defined. I believe

when: null\_var

would work if (1) it is always defined and (2) you set it to true or  
false or something. Someone more knowledgeable can check my claims.

---

<div class="post-metadata">

**Author:** ![vbotka](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/vbotka/32/359_2.png) [@vbotka](https://forum.ansible.com/u/vbotka)\
**Post date:** [February 17, 2020, 9:09pm UTC](https://forum.ansible.com/t/doubt-regarding-loops-and-conditionals/32257/3 "2020-02-17T21:09:56Z")

</div>

Instead of testing whether the variable is defined or not, use the "default"  
filter. For example

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- name: "test loop"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;debug:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg: "test"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop: "{{ nulo|default() }}"

The loop will be skipped if "nulo" is undefined. Test "nulo" separately if  
you want the playbook to fail. For example

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- name: Fail when nulo undefined  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fail:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg: "Variable nulo undefined"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when: nulo if undefined

HTH,

&nbsp;&nbsp;-vlado

---

<div class="post-metadata">

**Author:** ![Nuno\_Jordao](https://avatars.discourse-cdn.com/v4/letter/n/a4c791/32.png) [@Nuno\_Jordao](https://forum.ansible.com/u/Nuno_Jordao)\
**Post date:** [February 18, 2020, 2:45pm UTC](https://forum.ansible.com/t/doubt-regarding-loops-and-conditionals/32257/4 "2020-02-18T14:45:34Z")

</div>

Hello,

Thank you for your responses.  
Some times I dont like to use the loop: “{{ nulo|default() }}” because it doesn’t say “skipping” and in complex playbook with lots of hosts I like to have that feedback.

I tested several options and and everything works, even the case of the issue [45976](https://github.com/ansible/ansible/issues/45976) (should have tested that one before). I think that, probably, the behaviour changed, and the documentation should be more clear in this regard… The conditional is not applied only per item but also to the task…

vars:  
tstbool: False  
tstnull:

tasks:

- name: “test loop”  
debug:  
msg: “test”  
loop: “{{nulo|default()}}”

- name: “test loop”  
debug:  
msg: “test”  
loop: “{{nulo}}”  
when: nulo is defined

- name: “test loop”  
debug:  
msg: “test”  
loop: “{{nulo}}”  
when: nulo|default(False)

- name: “test loop”  
debug:  
msg: “test”  
loop: “{{nulo}}”  
when: nulo|default()|length \> 0

- name: “test loop”  
debug:  
msg: “test”  
loop: “{{nulo}}”  
when: tstbool

- name: “test loop”  
debug:  
msg: “test”  
loop: “{{nulo}}”  
when: tstnull

Returns:

PLAY [localhost] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*

TASK [test loop] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*

TASK [test loop] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
skipping: [localhost]

TASK [test loop] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
skipping: [localhost]

TASK [test loop] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
skipping: [localhost]

TASK [test loop] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
skipping: [localhost]

TASK [test loop] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*[DEPRECATION WARNING]: evaluating None as a bare variable, this behaviour will go away and you might need to add

> bool to the expression in the future. Also see CONDITIONAL\_BARE\_VARS configuration toggle… This feature will be  
> removed in version 2.12. Deprecation warnings can be disabled by setting deprecation\_warnings=False in ansible.cfg.  
> skipping: [localhost]

PLAY RECAP \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*localhost : ok=0 changed=0 unreachable=0 failed=0 skipped=6 rescued=0 ignored=0

The final count for skipped is 6 but the first task doesn’t report skipping

---

<div class="post-metadata">

**Author:** ![racke](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/racke/32/4767_2.png) [@racke](https://forum.ansible.com/u/racke)\
**Post date:** [February 18, 2020, 3:05pm UTC](https://forum.ansible.com/t/doubt-regarding-loops-and-conditionals/32257/5 "2020-02-18T15:05:42Z")

</div>

> Hello,
> 
> Thank you for your responses.  
> Some times I dont like to use the loop: "{{ nulo|default() }}" because it doesn't say "skipping" and in complex  
> playbook with lots of hosts I like to have that feedback.
> 
> I tested several options and and everything works, even the case of the issue 45976  
> \<[https://github.com/ansible/ansible/issues/45976&gt](https://github.com/ansible/ansible/issues/45976&gt); (should have tested that one before). I think that, probably, the  
> behaviour changed, and the documentation should be more clear in this regard... The conditional is not applied only per  
> item but also to the task...

I suppose Ansible determines whether the conditional contains a loop variable. In that case it applies it for every  
item. In the other case it evaluates it only once and skips the task when the conditional results in a false value.

The documentation seems not be completely accurate.

Regards  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Racke

---

<div class="post-metadata">

**Author:** ![vbotka](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/vbotka/32/359_2.png) [@vbotka](https://forum.ansible.com/u/vbotka)\
**Post date:** [February 18, 2020, 7:22pm UTC](https://forum.ansible.com/t/doubt-regarding-loops-and-conditionals/32257/6 "2020-02-18T19:22:44Z")

</div>

> Some times I dont like to use the loop: "{{ nulo|default() }}" because it  
> doesn't say "skipping" and in complex playbook with lots of hosts I like to  
> have that feedback.

You might want to find a plugin which fits your needs  
[https://docs.ansible.com/ansible/latest/plugins/callback.html#plugin-list](https://docs.ansible.com/ansible/latest/plugins/callback.html#plugin-list)

> ... I think that, probably, the behaviour changed, and  
> the documentation should be more clear in this regard... The conditional is  
> not applied only per item but also to the task...
> 
> [...]  
> &nbsp;&nbsp;&nbsp;&nbsp;- name: "test loop"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;debug:  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg: "test"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop: "{{nulo}}"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when: nulo is defined

You're right. "when" is also applied before the loop starts. Let me point to  
2 more cases which describe the complexity. The task below

&nbsp;&nbsp;&nbsp;- debug:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg: "test"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop: "{{ nulo }}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- nulo is defined  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- item is search('PATTERN')

is skipped because "when" stops evaluating a conjunction after the first  
element fails

&nbsp;&nbsp;&nbsp;skipping: [localhost]

But when the order of the conditions is changed the task

&nbsp;&nbsp;&nbsp;&nbsp;- debug:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg: "test"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop: "{{ nulo }}"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- item is search('PATTERN')  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- nulo is defined

fails because the evaluation of "item" leads to the evaluation of "nulo"

&nbsp;&nbsp;&nbsp;&nbsp;fatal: [localhost]: FAILED! =\> {"msg": "'nulo' is undefined"}

As a result, I argue that "{{ nulo|default() }}" should be preferred in  
term of "keep it simple stupid".  
[https://en.wikipedia.org/wiki/KISS\_principle](https://en.wikipedia.org/wiki/KISS_principle)

It's been also discussed here  
[https://groups.google.com/forum/#!topic/ansible-project/Y1mGC3vrsng](https://groups.google.com/forum/#!topic/ansible-project/Y1mGC3vrsng)

HTH,

&nbsp;&nbsp;-vlado

---

<div class="post-metadata">

**Author:** ![Nuno\_Jordao](https://avatars.discourse-cdn.com/v4/letter/n/a4c791/32.png) [@Nuno\_Jordao](https://forum.ansible.com/u/Nuno_Jordao)\
**Post date:** [February 19, 2020, 11:37am UTC](https://forum.ansible.com/t/doubt-regarding-loops-and-conditionals/32257/7 "2020-02-19T11:37:18Z")

</div>

Well, after reading the other discussion, I think you are right. The safest is to use the default. The conditional can be unpredictable which was what I was afraid and why I started this thread.  
Ansible should avoid these situations. Or maybe provide a warning of potential unsafe situations.

About the plugins, I dont think it is possible to use those in AWX.

Thank you for your input.

Regards,

Nuno Jordão
