How Exactly Does Ansible Parse Boolean Variables?
Asked Answered
D

2

45

In Ansible, there are several places where variables can be defined: in the inventory, in a playbook, in variable files, etc. Can anyone explain the following observations that I have made?

  1. When defining a Boolean variable in an inventory, it MUST be capitalized (i.e., True/False), otherwise (i.e., true/false) it will not be interpreted as a Boolean but as a String.
  2. In any of the YAML formatted files (playbooks, roles, etc.) both True/False and true/false are interpreted as Booleans.

For example, I defined two variables in an inventory:

abc=false
xyz=False

And when debugging the type of these variables inside a role...

- debug:
    msg: "abc={{ abc | type_debug }}  xyz={{ xyz | type_debug }}"

... then abc becomes unicode but xyz is interpreted as a bool:

ok: [localhost] => {
    "msg": "abc=unicode  xyz=bool"
}

However, when defining the same variables in a playbook, like this:

  vars:
    abc: false
    xyz: False

... then both variables are recognized as bool.

I had to realize this the hard way after executing a playbook on production, running something that should not have run because of a variable set to 'false' instead of 'False' in an inventory. Thus, I'd really like to find a clear answer about how Ansible understands Booleans and how it depends on where/how the variable is defined. Should I simply always use capitalized True/False to be on the safe side? Is it valid to say that booleans in YAML files (with format key: value) are case-insensitive, while in properties files (with format key=value) they are case-sensitive? Any deeper insights would be highly appreciated.

Disconcerted answered 18/12, 2017 at 22:38 Comment(0)
P
95

Variables defined in YAML files (playbooks, vars_files, YAML-format inventories)


YAML principles

Playbooks, vars_files, and inventory files written in YAML are processed by a YAML parser first. It allows several aliases for values which will be stored as Boolean type: yes/no, true/false, on/off, defined in several cases: true/True/TRUE (thus they are not truly case-insensitive).

YAML definition specifies possible values as:

y|Y|yes|Yes|YES|n|N|no|No|NO
|true|True|TRUE|false|False|FALSE
|on|On|ON|off|Off|OFF

Ansible docs confirm that:

You can also specify a boolean value (true/false) in several forms:

create_key: yes
needs_agent: no
knows_oop: True
likes_emacs: TRUE
uses_cvs: false

However, Ansible documentation now also states:

Use lowercase ‘true’ or ‘false’ for boolean values in dictionaries if you want to be compatible with default yamllint options.

So keep that in mind if you use tools like ansible-lint, that will not be happy by default (Truthy value should be one of [false, true])



Variables defined in INI-format inventory files


Python principles

When Ansible reads an INI-format inventory, it processes the variables using Python built-in types:

Values passed in using the key=value syntax are interpreted as Python literal structure (strings, numbers, tuples, lists, dicts, booleans, None), alternatively as string. For example var=FALSE would create a string equal to FALSE.

If the value specified matches string True or False (starting with a capital letter) the type is set to Boolean, otherwise it is treated as string (unless it matches another type).



Variables defined through --extra_vars CLI parameter


All strings

All variables passed as extra-vars in CLI are of string type. You can work around that by using JSON syntax. Example:

--extra-vars '{"abc": false}'

abc will then be of type bool.

Payoff answered 18/12, 2017 at 22:42 Comment(6)
Thanks a lot for the detailed answer. It really helped a lot. But still it lead me to yet another confusion: What causes Ansible to evaluate 'false and true' as 'true'?Disconcerted
great answer and this explains what to do to force variables as boolean anyways: https://mcmap.net/q/374248/-ansible-quot-when-variable-true-quot-not-behaving-as-expected (use the bool filter)Arturo
You can also pass variables as json to force them to be interpreted as booleans without needing to change your playbooks.Araucaria
While true, extra-vars in Tower/AWX jobs are not from the CLI; they really are YAML (well, the YAML ones are) and thus are subject to the same parsing/processing as other YAML vars. So for booleans, not all extra-vars are strings. Only the CLI ones.Homothallic
Beware: ansible-lint now warn you if you use something else than yes or no: Truthy value should be one of [false, true]Shlomo
I added an example on how to pass boolean values via --extra-vars. Feel free to roll back if you disagree.Picked
C
1

The YAML principles define the possible Boolean values that are accepted by Ansible. However after parsing only two values remain (true and false), these are valid in JSON too, so if you do some things with these values in Ansible, then true and false are good choices. Also the Ansible documentation states

Use lowercase ‘true’ or ‘false’ for boolean values in dictionaries if you want to be compatible with default yamllint options.

#!/usr/bin/env ansible-playbook
---

- name: true or false?
  hosts: all
  gather_facts: false

  tasks:

    - name: "all these boolean inputs evaluate to 'true'"
      debug:
        msg: "{{ item }}"
      with_items:
        - true
        - True
        - TRUE
        - yes
        - Yes
        - YES
        - on
        - On
        - ON

    - name: "all these boolean inputs evaluate to 'false'"
      debug:
        msg: "{{ item }}"
      with_items:
        - false
        - False
        - FALSE
        - no
        - No
        - NO
        - off
        - Off
        - OFF
Coprophilia answered 7/10, 2021 at 12:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.