complex when conditions

770 views
Skip to first unread message

Arie Skliarouk

unread,
Mar 4, 2014, 7:11:51 AM3/4/14
to ansible...@googlegroups.com
Hi,

I am migrating ansible from 0.9 to 1.5 and complex when condition don't work anymore:

  vars:
    not_main: "'$c_main' == 'no'"
    is_main: "'$c_main' == 'yes'"
    not_lxc: "'$lxc' != 'yes'"

  tasks:
  # This does not work properly, it is always being applied
  - name: test0.conf
    action: template src=/tmp/test.conf.j2 dest=/tmp/test0.conf owner=ops group=ops mode=0444
    when: not_main and not_lxc
 # This works but prints warnings about using ${foo} or $foo. This is what I used in the past with ansible 0.9 (with only_if).
  - name: test1.conf
    action: template src=/opt/opsfs/tmp/test.conf.j2 dest=/tmp/test1.conf owner=ops group=ops mode=0444
    when: $not_main and $not_lxc
# This works but is longer to type and not as readable as the first example
  - name: test2.conf
    action: template src=/opt/opsfs/tmp/test.conf.j2 dest=/tmp/test2.conf owner=ops group=ops mode=0444
    when: c_main == 'no' and lxc != 'yes'

What is the correct way to use complex when conditions?

--
Arie

Michael DeHaan

unread,
Mar 4, 2014, 7:49:44 AM3/4/14
to ansible...@googlegroups.com
The following tricks are available:

---
- hosts: all

  vars:
    x: 1
    y: 2
    alpha: x > 2
    beta:  y > 3

  tasks:

    - shell: echo hi 1
      when: alpha

    - shell: echo hi 2
      when:
        - alpha
        - beta

Note that 'when: "alpha and beta"' is ambigious to the system, and won't do what you want, because it has a hard time understanding whether a variable is a variable expression or a string or not.




--
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.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/8d870518-5473-4e44-826c-f6674d1fc306%40googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Arie Skliarouk

unread,
Mar 4, 2014, 8:28:44 AM3/4/14
to ansible...@googlegroups.com
In my scripts I also use "or" expression... How would I do that? And what about the poor souls that want to use complex boolean expression?...

--
Arie

Michael DeHaan

unread,
Mar 4, 2014, 8:34:15 AM3/4/14
to ansible...@googlegroups.com
Complex conditionals and or statements are fine.

when:  x > 2 or y >3

and complex conditionals are fine as well:

when:  (x > 2 or y > 3) and (zebras == 4)

etc




Arie Skliarouk

unread,
Mar 4, 2014, 8:41:35 AM3/4/14
to ansible...@googlegroups.com
Will it be easier for ansible to recognize pre-defined condition if I put it in brackets?

  vars:
    amazon: "yes"
    lxc: "no"
    is_amazon: (amazon == "yes")
    is_lxc:  (lxc == "yes")

  tasks:
    - shell: echo hi 1
      when: is_amazon or is_lxc

It would be sad if there is no way to use short syntax like this...

Michael DeHaan

unread,
Mar 4, 2014, 8:50:25 AM3/4/14
to ansible...@googlegroups.com
You'll have to be sad then, at least for now.

Too much fuzzy logic is involved for the system to know what is a condition and what is a string, so only bare words
are evaluated as conditionals.




Arie Skliarouk

unread,
Mar 4, 2014, 10:06:47 AM3/4/14
to ansible...@googlegroups.com
The ansible documentation has this example:

vars:
  epic: true
Then a conditional execution might look like:
tasks:
    - shell: echo "This certainly is epic!"
      when: epic

Would it be possible for ansible to interpret conditionals in vars: section and assign proper true/false values to the variables? So that in example below is_amazon is assigned true?
amazon: "yes"
is_amazon: (amazon == "yes")

Michael DeHaan

unread,
Mar 4, 2014, 10:11:50 AM3/4/14
to ansible...@googlegroups.com
Yes, it can go one level deep.

You can't build conditional expressions out of conditional expressions, but variables will expand.

I'd suggest writing a test playbook and trying it out!


Arie Skliarouk

unread,
Mar 4, 2014, 10:45:53 AM3/4/14
to ansible...@googlegroups.com
I tested various combinations, and in no case the is_var_evaluatedX got assigned value True...

vars:
    amazon: "no"
    is_var_evaluated1: (amazon == 'no')
    is_var_evaluated2: amazon == 'no'
    is_var_evaluated3: $amazon == 'no'
    is_var_evaluated4: "'$amazon' == 'no'"

I would like to file feature request on adding conditional expression evaluation in vars section... Is there ansible's BTS?

Michael DeHaan

unread,
Mar 4, 2014, 11:41:14 AM3/4/14
to ansible...@googlegroups.com
"Is there ansible's BTS?"


However, it's *already* true that conditionals in the vars section work.

You still have some legacy variables in the bottom half, which is why 3 and 4 don't work.

    amazon: "no"
    is_var_evaluated1: (amazon == 'no')
    is_var_evaluated2: amazon == 'no'
 

The first two should be true, and I've confirmed that they work on my end at least.

Note that if you forget to quote the no, it will be stored as a False, and this is even cleaner.

when: amazon










Arie Skliarouk

unread,
Mar 23, 2014, 7:42:04 AM3/23/14
to ansible...@googlegroups.com
The following playbook does not work properly - the action is always executed, why is that?

---
- hosts: *
  vars:
    x: 5
    y: 7
    
    is_false1: x>y
    is_false2: x>y
  tasks:

  - name: either is true
    shell: echo either is true
    when: is_false1 or is_false2

Michael DeHaan

unread,
Mar 23, 2014, 10:05:00 AM3/23/14
to ansible...@googlegroups.com
You can't load a "saved" conditional that way (at least currently) as the conditional loader doesn't do recursive lookups.

-- Michael
--
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.

Arie Skliarouk

unread,
Mar 24, 2014, 4:56:56 AM3/24/14
to ansible...@googlegroups.com
What is the recommended way to use "saved" conditionals?

Something like this:

ansible_hosts has this:
machine1 amazon=yes

vars:
  is_amazon: (amazon == "yes")
tasks:
  shell: echo we are on amazon
  when: is_amazon

Can ansible treat expressions in brackets in vars: section as "saved" conditional? E.g. evaluate it and store in the value boolean True or False? This way the conditional loader does not need to do any lookups, just evaluate the expression as is.

Another question I have - whether the values of variables should be quoted? Double or single quote? From my experience, the quotes in ansible are treated as part of the value.

--
Arie

Michael DeHaan

unread,
Mar 24, 2014, 8:13:07 AM3/24/14
to ansible...@googlegroups.com
"  when: is_amazon"

This is fine.

"whether the values of variables should be quoted?"

Only if they are strings.




Tomasz Kontusz

unread,
Mar 23, 2014, 9:05:17 AM3/23/14
to ansible...@googlegroups.com
On 23.03.2014 12:42, Arie Skliarouk wrote:
> The following playbook does not work properly - the action is always
> executed, why is that?
>
> ---
> - hosts: *
> vars:
> x: 5
> y: 7
>
> is_false1: x>y
> is_false2: x>y
Here you set is_false1 and is_false2 to strings "x>y", not to a result
of evaluating it (and it would be the same if you put {{ }} around it)
> tasks:
>
> - name: either is true
> shell: echo either is true
> when: is_false1 or is_false2
And here you check if either is_false1 or is_false2 is true-like - which
they both are, as they are non-empty strings. What would work is putting
them in {{ }} like this:

when: '{{ is_false1 }} or {{ is_false2 }}'

which looks bad, and tells you about {{ }} not being needed (which is
not true in this case...).

Michael DeHaan

unread,
Mar 24, 2014, 10:50:09 AM3/24/14
to ansible...@googlegroups.com
"which looks bad, and tells you about {{ }} not being needed (which is not true in this case...)."

The real fix would be to evaluate things as far recursively as we can, IMHO.

So as long as we have a ticket for that (let's be sure we have one) {{ foo }} will become uneeded and we don't need to change the warning.




--
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-project+unsubscribe@googlegroups.com.
To post to this group, send email to ansible-project@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/532EDC0D.9040803%40gmail.com.

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

Reply all
Reply to author
Forward
0 new messages