Consider this trivial ansible playbook and associated output below. Why does task 5 get executed? These tasks were run against debian. Task 1 fails as expected. So, why does and'ing it with 'ansible_lsb.major_release|int < 14' make it true? Does this have something to do with operator precedence?
-jk
---
- name: These tests run against debian
hosts: frontend001
vars:
- bcbio_dir: /mnt/bcbio
- is_ubuntu: "'{{ansible_distribution}}' == 'Ubuntu'"
- is_debian: "'{{ansible_distribution}}' == 'Debian'"
tasks:
- name: 1. Expect skip because test is_ubuntu
debug: msg="ansible distribution - {{ansible_distribution}}, release - {{ansible_distribution_release}}, {{ ansible_lsb.major_release }}"
when: is_ubuntu
- name: 2. Expect to print msg because test is_debian
debug: msg="ansible distribution - {{ansible_distribution}}, release - {{ansible_distribution_release}}, {{ ansible_lsb.major_release }}"
when: is_debian
- name: 3. Expect to print msg because release 7 of wheezy
debug: msg="ansible distribution - {{ansible_distribution}}, release - {{ansible_distribution_release}}, {{ ansible_lsb.major_release }}"
when: ansible_lsb.major_release|int < 14
- name: 4. Expect to print msg because true and true is true
debug: msg="ansible distribution - {{ansible_distribution}}, release - {{ansible_distribution_release}}, {{ ansible_lsb.major_release }}"
when: is_debian and ansible_lsb.major_release|int < 14
- name: 5. Expect to skip because false and true is false
debug: msg="ansible distribution - {{ansible_distribution}}, release - {{ansible_distribution_release}}, {{ ansible_lsb.major_release }}"
when: is_ubuntu and ansible_lsb.major_release|int < 14
$ ansible-playbook -i ~/.elasticluster/storage/ansible-inventory.jkcluster zbcbio.yml
PLAY [These tests run against debian] *****************************************
GATHERING FACTS ***************************************************************
ok: [frontend001]
TASK: [1. Expect skip because test is_ubuntu] *********************************
skipping: [frontend001]
TASK: [2. Expect to print msg because test is_debian] *************************
ok: [frontend001] => {
"msg": "ansible distribution - Debian, release - wheezy, 7"
}
TASK: [3. Expect to print msg because release 7 of wheezy] ********************
ok: [frontend001] => {
"msg": "ansible distribution - Debian, release - wheezy, 7"
}
TASK: [4. Expect to print msg because true and true is true] ******************
ok: [frontend001] => {
"msg": "ansible distribution - Debian, release - wheezy, 7"
}
TASK: [5. Expect to skip because false and true is false] *********************
ok: [frontend001] => {
"msg": "ansible distribution - Debian, release - wheezy, 7"
}
PLAY RECAP ********************************************************************
frontend001 : ok=5 changed=0 unreachable=0 failed=0
Edited: Listing the changes based on tedder42's answer below in case someone is following along at home.
1) Changed
- is_ubuntu: "'{{ansible_distribution}}' == 'Ubuntu'"
to
- is_ubuntu: "{{ansible_distribution == 'Ubuntu'}}"
2) change
when: is_ubuntu and ansible_lsb.major_release|int < 14
to
when: is_ubuntu|bool and ansible_lsb.major_release|int < 14
That did it!
-jk
The when clause is a raw Jinja2 expression without double curly braces (see group_by_module). When you run the task or playbook, Ansible evaluates the test for all hosts. On any host where the test passes (returns a value of True), Ansible runs that task.
To implement conditions in Ansible, we use the when keyword. The keyword takes Boolean expressions based on a value or a variable from previous tasks or facts gathered from the remote hosts.
Traditional programming language usually uses the if-else statement when more than one outcome is expected. In Ansible, 'when' statement is used instead to determine the outcome of a variable. So instead of using the if-else statement, you define what you want to happen.
TLDR: your variable is being output as a string, not evaluated. Fix the evaluation using jinja2 and then filter the var as |bool
.
You're only missing one thing to debug this problem. Here's what I ran on my local OSX box:
- name: stackoverflow 26188055
hosts: local
vars:
- bcbio_dir: /mnt/bcbio
- is_ubuntu: "'{{ansible_distribution}}' == 'Ubuntu'"
- is_debian: "'{{ansible_distribution}}' == 'Debian'"
tasks:
- debug: var=is_ubuntu
- debug: var=is_debian
- debug: msg="this shows the conditional passes even though it shouldnt"
when: is_ubuntu and true
And the output:
TASK: [debug var=is_ubuntu] ***************************************************
ok: [127.0.0.1] => {
"is_ubuntu": "'MacOSX' == 'Ubuntu'"
}
TASK: [debug var=is_debian] ***************************************************
ok: [127.0.0.1] => {
"is_debian": "'MacOSX' == 'Debian'"
}
TASK: [debug msg="this shows the conditional passes even though it shouldnt"] ***
ok: [127.0.0.1] => {
"msg": "this shows the conditional passes even though it shouldnt"
}
As far as I know, you can't really evaluate down to a boolean. Typically this is done by unrolling the variable (placing it in every "when"). However, it can be accomplished as you can get a boolean as a string, then cast it to a bool as hinted on the Variables ansible page (search for "boolean value").
- name: stackoverflow 26188055
hosts: local
vars:
- bcbio_dir: /mnt/bcbio
- is_ubuntu: "{{ansible_distribution == 'Ubuntu'}}"
- is_debian: "{{ansible_distribution == 'Debian'}}"
tasks:
- debug: var=is_ubuntu
- debug: var=is_debian
- debug: msg="this shows the conditional passes even though it shouldnt"
when: is_ubuntu|bool and true
And here's the output.
TASK: [debug var=is_ubuntu] ***************************************************
ok: [127.0.0.1] => {
"is_ubuntu": "False"
}
TASK: [debug var=is_debian] ***************************************************
ok: [127.0.0.1] => {
"is_debian": "False"
}
TASK: [debug msg="this shows the conditional passes even though it shouldnt"] ***
skipping: [127.0.0.1]
Note you may want to take advantage of Ansible's version_compare filter. Usage is left as an exercise to the reader.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With