cueedee
cueedee

Reputation: 1873

Why does `default( None )` not always appear to produce `None`

Is there a logical reasoning that explains why the two debug tasks in the Ansible playbook below respectively output "NONE" and "FALSE" and not both "NONE"?

- hosts:  'all'

  tasks:

    - debug:
        msg: '{{ foo | default( None ) | ternary( "TRUE", "FALSE", "NONE" ) }}'

    - debug:
        msg: '{{ bar | ternary( "TRUE", "FALSE", "NONE" ) }}'

  vars:

    bar: '{{ foo | default( None ) }}'

I observed this with [email protected] btw


[edit@2019-10-16]

As inferred from @VladimirBotka's answer, one could say the real "problem" is that None isn't transitive with respect to substitution. My use of default(...) was needlessly complicating matters and the example can be simplified to:

- hosts: 'all'
  tasks:
    - debug:
        msg: '{{ None | ternary( "TRUE", "FALSE", "NONE" ) }}'

    - debug:
        msg: '{{ bar | ternary( "TRUE", "FALSE", "NONE" ) }}'

  vars:
    bar: '{{ None }}'

... and still produce the exact same output.

Upvotes: 6

Views: 8161

Answers (1)

Vladimir Botka
Vladimir Botka

Reputation: 68254

  • foo|default(None) evaluates to null
  • {{ foo|default(None) }} evaluates to an empty string ""

The task

- debug:
    msg: bar is empty string
  when: bar|length == 0

gives

"msg": "bar is empty string"

But the task

- debug:
    msg: foo is empty string
  when: foo|default(None)|length == 0

fails with the error:

"... object of type 'NoneType' has no len() ... "

As a result in ternary, an empty string will select FALSE and null will select NONE.


Notes

1) See the Note in Omitting Parameters

2) Both null and empty string "" select FALSE in ternary if the third parameter is omitted. The tasks

   - debug:
        msg: "{{ bar|ternary('TRUE', 'FALSE') }}"
    - debug:
        msg: "{{ foo|default(None)|ternary('TRUE', 'FALSE') }}"

give

"msg": "FALSE"
"msg": "FALSE"

Upvotes: 2

Related Questions