Conditionals - when: <var1> and <var2> is defined works in a weird way

208 views
Skip to first unread message

Roman Revyakin

unread,
Feb 3, 2014, 7:32:14 PM2/3/14
to ansible...@googlegroups.com
Hi,

I am not sure whether someone has come across this issue previously - trying to search the group for 'when' and 'is defined' did not yield me anything useful. So I am posting it as a new topic here.
I have encountered that in case I use 'when:' clause where I need to test whether one variable is set to 'true' and another one is defined, the following playbook triggers action even if the first variable is 'false':

cat > test_playbook.yaml <<EOF
---
- hosts: all
  gather_facts: false

  tasks:
    - name: Play only if var1 is true and var2 is defined
      local_action: command echo "Yes {{ var1 }} is true and {{ var2 }} is defined"
      when: var1 and var2 is defined
EOF

$ ansible-playbook -i host -v test_playbook.yaml --extra-vars "var1=false var2='something'"

PLAY [all] ******************************************************************** 

TASK: [Play only if var1 is true and var2 is defined] ************************* 
changed: [localhost] => {"changed": true, "cmd": ["echo", "Yes false is true and something is defined"], "delta": "0:00:00.003256", "end": "2014-02-04 11:19:56.720699", "rc": 0, "start": "2014-02-04 11:19:56.717443", "stderr": "", "stdout": "Yes false is true and something is defined"}

PLAY RECAP ******************************************************************** 
localhost                  : ok=1    changed=1    unreachable=0    failed=0   
 
Only if I change the conditions to be supplied on separate 'when:' lines, it works as expected:

cat > test1_playbook.yaml <<EOF
---
- hosts: all
  gather_facts: false

  tasks:
    - name: Play only if var1 is true and var2 is defined
      local_action: command echo "Yes {{ var1 }} is true and {{ var2 }} is defined"
      when: var2 is defined
      when: var1
EOF

$ ansible-playbook -i host -v test_playbook.yaml --extra-vars "var1=false var2='something'"

PLAY [all] ******************************************************************** 

TASK: [Play only if var1 is true and var2 is defined] ************************* 
skipping: [localhost]

PLAY RECAP ******************************************************************** 
localhost                  : ok=0    changed=0    unreachable=0    failed=0   

$ ansible-playbook -i host -v test_playbook.yaml --extra-vars "var1=true var2='something'"

PLAY [all] ******************************************************************** 

TASK: [Play only if var1 is true and var2 is defined] ************************* 
changed: [localhost] => {"changed": true, "cmd": ["echo", "Yes true is true and something is defined"], "delta": "0:00:00.002733", "end": "2014-02-04 11:22:20.289360", "rc": 0, "start": "2014-02-04 11:22:20.286627", "stderr": "", "stdout": "Yes true is true and something is defined"}

PLAY RECAP ******************************************************************** 
localhost                  : ok=1    changed=1    unreachable=0    failed=0   

However in this case it fails (not skips) when the var2 is undefined and var1 is true, which is not really a desired behaviour:

$ ansible-playbook -i host -v test_playbook.yaml --extra-vars "var1=true"

PLAY [all] ******************************************************************** 

TASK: [Play only if var1 is true and var2 is defined] ************************* 
fatal: [localhost] => One or more undefined variables: 'var2' is undefined

FATAL: all hosts have already failed -- aborting

PLAY RECAP ******************************************************************** 
           to retry, use: --limit @/Users/roman/test_playbook.yaml.retry

localhost                  : ok=0    changed=0    unreachable=1    failed=0   

The order of  'when's also matters, in case their order is reverted like follows

      when: var1
      when: var2 is defined

the playbook starts behaving like in the first example where 'when' conditions were supplied on one line using the 'and' operator.
If I use 

     when: var1==true and var2 is defined

the playbook would skip the action even all conditions are satisfied: 

$ ansible-playbook -i host -v test_playbook.yaml --extra-vars "var1=true var2='defined'"

PLAY [all] ******************************************************************** 

TASK: [Play only if var1 is true and var2 is defined] ************************* 
skipping: [localhost]

PLAY RECAP ******************************************************************** 
localhost                  : ok=0    changed=0    unreachable=0    failed=0   

The docs do not shed any more light on that strange behaviour.

Thanks a lot in advance,

With kind regards,
Roman

Roman Revyakin

unread,
Feb 3, 2014, 7:34:19 PM2/3/14
to ansible...@googlegroups.com
Forgot to mention that I use 

ansible-playbook 1.5 (devel 27199dc219) last updated 2013/12/04 20:39:15 (GMT +1100)

Adam Heath

unread,
Feb 3, 2014, 7:38:24 PM2/3/14
to ansible...@googlegroups.com
"false" != false. You have a string/boolean issue. Aka, the var1 is
not the boolean value false, but the string value "false".
> <http://docs.ansible.com/playbooks_conditionals.html#the-when-statement> do
> not shed any more light on that strange behaviour.
>
> Thanks a lot in advance,
>
> With kind regards,
> Roman
>
> --
> You received this message because you are subscribed to the Google
> Groups "Ansible Project" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to ansible-proje...@googlegroups.com.
> To post to this group, send email to ansible...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.

Roman Revyakin

unread,
Feb 3, 2014, 7:51:27 PM2/3/14
to ansible...@googlegroups.com
Hi Adam,

I do not think so, please see my example above with the 

ansible-playbook -i host -v test_playbook.yaml --extra-vars "var1=false var2='something'"

being executed as expected (skipped). In case var1 was a string, the 

      when: var2 is defined
      when: var1

conditions would evaluate to true IMHO and the action would be triggered.




an email to ansible-project+unsubscribe@googlegroups.com.
To post to this group, send email to ansible-project@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.

--
You received this message because you are subscribed to a topic in the Google Groups "Ansible Project" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ansible-project/YPfK1KYpQeI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ansible-project+unsubscribe@googlegroups.com.
To post to this group, send email to ansible-project@googlegroups.com.

Adam Morris

unread,
Feb 3, 2014, 8:33:45 PM2/3/14
to ansible...@googlegroups.com


I'm not certain but...

According to the documentation when: takes a jinja 2 expression.

I don't know the order of precedence in jinja 2, but 
var1 and var2 is defined
could be read as 
(var1 and var2) is defined
or 
var1 and (var2 is defined)

I suspect that you are looking for the second one, but you MIGHT be getting the first.  have you considered grouping the relevant parts so that you have
(var1) and (var2 is defined)
To me, that seems a lot clearer as to the intent.

Adam

Jesse Keating

unread,
Feb 3, 2014, 9:17:53 PM2/3/14
to ansible...@googlegroups.com
On 2/3/14, 4:32 PM, Roman Revyakin wrote:
> cat > test_playbook.yaml <<EOF
> ---
> - hosts: all
> gather_facts: false
>
> tasks:
> - name: Play only if var1 is true and var2 is defined
> local_action: command echo "Yes {{ var1 }} is true and {{ var2 }}
> is defined"
> when: var1 and var2 is defined
> EOF
>
> $ ansible-playbook -i host -v test_playbook.yaml --extra-vars
> "var1=false var2='something'"
>
> PLAY [all]
> ********************************************************************
>
> TASK: [Play only if var1 is true and var2 is defined]
> *************************
> changed: [localhost] => {"changed": true, "cmd": ["echo", "Yes false is
> true and something is defined"], "delta": "0:00:00.003256", "end":
> "2014-02-04 11:19:56.720699", "rc": 0, "start": "2014-02-04
> 11:19:56.717443", "stderr": "", "stdout": "Yes false is true and
> something is defined"}

You most certainly have a string to bool comparison issue going on.

You can change this by using the bool filter.

when: var1|bool and var2 is defined

When I use this, var1 being "false" will still cause the task to be
skipped as expected.


-jlk

Roman Revyakin

unread,
Feb 3, 2014, 10:00:46 PM2/3/14
to ansible...@googlegroups.com
Hi Jesse,

Thanks for getting to the bottom of this and providing a working solution! Works as charm indeed! Jinja framework is crazy IMHO.

Adam: grouping does not help, I tried it before submitting my first request, as well as swapping the order.

The issue is solved, thank you! I wonder what is the process of altering documentation on docs.ansible.com, googling for it provided me a link which does not contain the text that is shown in the search preview. 
Does submitting an issue to the Ansible repo sound like a proper idea?



Jesse Keating

unread,
Feb 3, 2014, 11:38:24 PM2/3/14
to ansible...@googlegroups.com
On 2/3/14, 7:00 PM, Roman Revyakin wrote:
>
> The issue is solved, thank you! I wonder what is the process of altering
> documentation on docs.ansible.com <http://docs.ansible.com>, googling
> for it provided me a link which does not contain the text that is shown
> in the search preview.
> Does submitting an issue to the Ansible repo
> <https://github.com/ansible/ansible> sound like a proper idea?

Yeah, the docs are driven from the ansible code base -- so an issue (or
better yet a pull request) is appropriate.


-jlk
Reply all
Reply to author
Forward
0 new messages