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

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

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