Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ansible "when variable == true" not behaving as expected

I have the following tasks in a playbook I'm writing (results listed next to the debug statement in <>):

  - debug: var=nrpe_installed.stat.exists <true>
  - debug: var=force_install <true>
  - debug: var=plugins_installed.stat.exists <true>

  - name: Run the prep 
    include: prep.yml
    when: (nrpe_installed.stat.exists == false or plugins_installed.stat.exists == true or force_install == true)
    tags: ['prep']

  - debug: var=nrpe_installed.stat.exists <true>
  - debug: var=force_install <true>
  - debug: var=force_nrpe_install <false>

  - name: Install NRPE
    include: install-nrpe.yml
    when: (nrpe_installed.stat.exists == false or force_install == true or force_nrpe_install == true)
    tags: ['install_nrpe']
    vars:
      nrpe_url: 'http://url.goes.here'
      nrpe_md5: 3921ddc598312983f604541784b35a50
      nrpe_version: 2.15
      nrpe_artifact: nrpe-{{ nrpe_version }}.tar.gz
      nagios_ip: {{ nagios_ip }}
      config_dir: /home/ansible/config/

And I'm running it with the following command:

ansible-playbook install.yml -i $invFile --extra-vars="hosts=webservers force_install=True"

The first include runs, but the second skips with this output:

 skipping: [server1] => {"changed": false, "skip_reason": "Conditional check failed", "skipped": true}

I'm under the impression that the conditional check should pass for all of them as force_install == true evaluates to true which should make the whole when evaluate to true (since it's a series of 'OR's).

How do I get the when to run when the variables are set appropriately?


Edit:

Changing the second when for the Install NRPE include to the following works, but doesn't explain why the other one, Run the prep runs appropriately:

Working:

when: (not nrpe_installed.stat.exists or force_install or force_nrpe_install)

Also working:

when: (nrpe_installed.stat.exists == false or plugins_installed.stat.exists == true or force_install == true)

Not working:

when: (nrpe_installed.stat.exists == false or force_install == true or force_nrpe_install == true)

The truncated (duplicates removed) output of that particular section of the play is:

TASK [debug] *******************************************************************
ok: [server2] => {
    "nrpe_installed.stat.exists": true
}

TASK [debug] *******************************************************************
ok: [server2] => {
    "plugins_installed.stat.exists": true
}

TASK [debug] *******************************************************************
ok: [server2] => {
    "force_install": true
}

TASK [Run the prep] ************************************************************
included: /tasks/nrpe-install/prep.yml for server2, server3, server4, server5, server6, server7

TASK [Prep and configure for installation | Install yum packages] **************
ok: [server6] => (item=[u'gcc', u'glibc', u'glibc-common', u'gd', u'gd-devel', u'make', u'net-snmp', u'openssl-devel', u'unzip', u'tar', u'gzip', u'xinetd']) => {"changed": false, "item": ["gcc", "glibc", "glibc-common", "gd", "gd-devel", "make", "net-snmp", "openssl-devel", "unzip", "tar", "gzip", "xinetd"], "msg": "", "rc": 0, "results": ["gcc-4.1.2-55.el5.x86_64 providing gcc is already installed", "glibc-2.5-123.el5_11.3.i686 providing glibc is already installed", "glibc-common-2.5-123.el5_11.3.x86_64 providing glibc-common is already installed", "gd-2.0.33-9.4.el5_4.2.x86_64 providing gd is already installed", "gd-devel-2.0.33-9.4.el5_4.2.i386 providing gd-devel is already installed", "make-3.81-3.el5.x86_64 providing make is already installed", "net-snmp-5.3.2.2-20.el5.x86_64 providing net-snmp is already installed", "openssl-devel-0.9.8e-40.el5_11.x86_64 providing openssl-devel is already installed", "unzip-5.52-3.el5.x86_64 providing unzip is already installed", "tar-1.15.1-32.el5_8.x86_64 providing tar is already installed", "gzip-1.3.5-13.el5.centos.x86_64 providing gzip is already installed", "xinetd-2.3.14-20.el5_10.x86_64 providing xinetd is already installed"]}

TASK [Prep and configure for installation | Make nagios group] *****************
ok: [server2] => {"changed": false, "gid": 20002, "name": "nagios", "state": "present", "system": false}

TASK [Prep and configure for installation | Make nagios user] ******************
ok: [server6] => {"append": false, "changed": false, "comment": "User for Nagios NRPE", "group": 20002, "home": "/home/nagios", "move_home": false, "name": "nagios", "shell": "/bin/bash", "state": "present", "uid": 20002}

TASK [debug] *******************************************************************
ok: [server2] => {
    "nrpe_installed.stat.exists": true
}

TASK [debug] *******************************************************************
ok: [server2] => {
    "force_install": true
}

TASK [debug] *******************************************************************
ok: [server2] => {
    "force_nrpe_install": false
}

TASK [Install NRPE] ************************************************************
skipping: [server2] => {"changed": false, "skip_reason": "Conditional check failed", "skipped": true}
like image 493
Mitch Avatar asked Jun 17 '16 19:06

Mitch


People also ask

What is Group_vars Ansible?

The group_vars in Ansible are a convenient way to apply variables to multiple hosts at once. Group_vars is an Ansible-specific folder as part of the repository structure. This folder contains YAML files created to have data models, and these data models apply to all the devices listed in the hosts.

Can we define multiple conditions in Ansible?

Defining multiple when conditions in Ansible I want to reboot Debian or Ubuntu Linux system after kernel update, and the inventory hostname must be aws-proxy-server . If both conditions are true, then issue the reboot command using the Ansible reboot module. Otherwise, skip the reboot option.

Does Ansible do until loop?

To use this loop in task you essentially need to add 3 arguments to your task arguments: until - condition that must be met for loop to stop. That is Ansible will continue executing the task until expression used here evaluates to true. retry - specifies how many times we want to run the task before Ansible gives up.


2 Answers

You need to convert the variable to a boolean:

force_install|bool == true 

I don't claim I understand the logic behind it. In python any non-empty string should be truthy. But when directly used in a condition it evaluates to false.

The bool filter then again interprets the strings 'yes', 'on', '1', 'true' (case-insensitive) and 1 as true (see source). Any other string is false.

You might want to also set a default value in case force_install is not defined, since it would result in an undefined variable error:

force_install|default(false)|bool == true 
like image 53
udondan Avatar answered Oct 09 '22 01:10

udondan


Yeah... certainly requires testing. I recommend

  • | bool is good unless you expect undefined vars
  • var is defined and (var | bool) if you expect undefined vars

default(False) is OK as long and you are happy that these are true if the input is not parsed from YAML. I.e. variables defined through --extra_vars CLI parameter are strings.

 "false"  "null"  "defined string"  

Hope this helps:

#!/usr/bin/env ansible-playbook --- - name: Test truthiness   hosts: localhost   gather_facts: False   vars:     truthy_vars:     # TRUE     - True     - 1     - "true"     # FALSE     - "false"     - null     - False     - 0     # ERROR (invalid sytax error stops the loop of the first of these)     - "null"     - "defined string"     # ERROR     # truthy_var_undefined     # FALSE     truthy_var_defined:   tasks:   - name: Test truthy     debug:       msg: "is truthy"     ignore_errors: True # beware, the loo     when: item     loop: "{{ truthy_vars }}"     loop_control:       label: Test {{ item }}   - name: truthy_var_undefined     debug:     when: truthy_var_undefined     ignore_errors: true   - name: truthy_var_defined     debug:     when: truthy_var_defined  - name: Test | default(False)   hosts: localhost   gather_facts: False   vars:     default_pipe_vars:     # TRUE     - True     - 1     - "true"     # beware these:     - "false"     - "null"     - "defined string"      # FALSE     - null     - False     - 0     # FALSE     # default_pipe_undefined     # FALSE     default_pipe_defined:   tasks:   - name: Test | default(False)     debug:       msg: "is not | default(False)"     when: item | default(False)     loop: "{{ default_pipe_vars }}"     loop_control:       label: Test {{ item }}   - name: default_pipe_undefined | default(False)     debug:     when: default_pipe_undefined | default(False)   - name: default_pipe_defined | default(False)     debug:     when: default_pipe_defined | default(False)  - name: Test | bool   hosts: localhost   gather_facts: False   vars:     bool_vars:     # TRUE     - True     - 1     - "true"     # FALSE     - "defined string"     - "null"     - "false"     - null     - False     - 0     # ERROR     # bool_undefined     # FALSE     bool_defined:   tasks:   - name: Test bool parsing     debug:       msg: "parsed as true booleans"     when: item | bool     loop: "{{ bool_vars }}"     loop_control:       label: Test {{ item }}   - name: bool_undefined | bool     debug:     when: bool_undefined | bool     ignore_errors: true   - name: bool_defined var | bool     debug:     when: bool_defined | bool   - name: Test is defined and | bool   hosts: localhost   gather_facts: False   vars:     defined_bool_vars:     # TRUE     - True     - 1     - "true"     # FALSE     - "defined string"     - "null"     - "false"     - null     - False     - 0     # FALSE     # defined_bool_undefined     # FALSE     defined_bool_defined:   tasks:   - name: Test bool parsing     debug:       msg: "parsed as true booleans"     when:     - item is defined     - item | bool     loop: "{{ defined_bool_vars }}"     loop_control:       label: Test {{ item }}   - name: defined_bool_undefined | bool     debug:     when:     - defined_bool_undefined is defined     - defined_bool_undefined | bool     ignore_errors: true   - name: defined_bool_defined var | bool     debug:     when:     - defined_bool_defined is defined     - defined_bool_defined | bool 

https://gist.github.com/kcd83/4ea23d201c271b58f1c4ef7844408657

like image 28
KCD Avatar answered Oct 09 '22 00:10

KCD