Reputation: 1873
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
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