Ansible casting string to bool

Viewed 211

I am trying to ask the user if they would like the new user they are creating to be a sudor or not.

    - hosts: localhost
      vars_prompt:
        - name: is_sudoer
          prompt: Is the new user a sudoer (Y/N)?
          private: no
      tasks:
        - name: debugTruth
          debug:
            msg: "Statement True"
          when: is_sudoer|default(false)|bool == true
        - name: debugFalse
          debug:
            msg: "Statement False"
          when: is_sudoer|default(false)|bool == false

However, no matter what I input, the script always defaults to false. I thought "y", "Y", "yes" etc always evaluated to true in the ansible.

Here is the output I get:

ansible-playbook manageUsers.yml

Is the new user a sudoer (Y/N)?: y
...    
    
TASK [debugTruth] **********************************************
skipping: [localhost]
    
TASK [debugFalse] **********************************************
ok: [localhost] => {
  "msg": "Statement False"
    }

As you can see I always get a false response.

2 Answers

I thought "y","Y","yes" etc always evaluated to true in the ansible.

That statement is not correct, as you can see here: https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/filter/core.py#L76 values that resolve to boolean true by the filter are the strings "1", "on", "yes", and "true" (case insensitive), or the numeral 1 (so, NOT "y"):

if isinstance(a, string_types):
    a = a.lower()
if a in ('yes', 'on', '1', 'true', 1):
    return True
return False

Additionally, the more correct way to implement the conditionals as suggested in the comments by @P, is

- name: debugTruth
  debug:
    msg: "Statement True"
  when: is_sudoer | bool

- name: debugFalse
  debug:
    msg: "Statement False"
  when: not is_sudoer | bool

The default(false) is not needed because the empty string (ie. the user typing just the enter key at the (Y/N) prompt) will be False in the when. Finally, avoid the ==.

"Y/N" is not automatically converted to boolean in Ansible. Both "Y" and "N" are simply non-empty strings and will be evaluated as True. The solution is simple. Test the string, for example

    - debug:
        msg: User is sudoer
      when: is_sudoer|lower == 'y'

For details about the "truthie/falsie" see below. Given the lists

    list1:
      - true
      - yes
      - Y
      - y
      - x
    list2:
      - false
      - no
      - N
      - n
      - x

Test truthy of list1

    - debug:
        msg: "{{ item }} is Truthy [{{ item is truthy }}]"
      loop: "{{ list1 }}"

gives

  msg: True is Truthy [True]
  msg: True is Truthy [True]
  msg: Y is Truthy [True]
  msg: y is Truthy [True]
  msg: x is Truthy [True]

and list2

    - debug:
        msg: "{{ item }} is Truthy [{{ item is truthy }}]"
      loop: "{{ list2 }}"

gives

  msg: False is Truthy [False]
  msg: False is Truthy [False]
  msg: N is Truthy [True]
  msg: n is Truthy [True]
  msg: x is Truthy [True]

Test falsy of list1

    - debug:
        msg: "{{ item }} is Falsy [{{ item is falsy }}]"
      loop: "{{ list1 }}"

gives

  msg: True is Falsy [False]
  msg: True is Falsy [False]
  msg: Y is Falsy [False]
  msg: y is Falsy [False]
  msg: x is Falsy [False]

and list2

    - debug:
        msg: "{{ item }} is Falsy [{{ item is falsy }}]"
      loop: "{{ list2 }}"

gives

  msg: False is Falsy [True]
  msg: False is Falsy [True]
  msg: N is Falsy [False]
  msg: n is Falsy [False]
  msg: x is Falsy [False]
Related