Commit de707c33 by Feanil Patel

Don't convert nulls to strings.

This change is similar to https://github.com/ansible/ansible/pull/10465

It extends the logic there to also support none types.  Right now if you have
a '!!null' in yaml, and that var gets passed around, it will get converted to
a string.

eg. defaults/main.yml
```
ENABLE_AWESOME_FEATURE: !!null # Yaml Null
OTHER_CONFIG:
  secret1: "so_secret"
  secret2: "even_more_secret"

CONFIG:
  hostname: "some_hostname"
  features:
    awesame_feature: "{{ ENABLE_AWESOME_FEATURE}}"
  secrets: "{{ OTHER_CONFIG }}"
```

If you output `CONFIG` to json or yaml, the feature flag would get represented in the output
as a string instead of as a null, but secrets would get represented as a dictionary.  This is
a mis-match in behaviour where some "types" are retained and others are not.  This change
should fix the issue.

I also updated the template test to test for this and made the changes to v2.

Added a changelog entry.
parent 0efd4617
......@@ -5,6 +5,10 @@ Ansible Changes By Release
Major Changes:
- big_ip modules now support turning off ssl certificate validation (use only for self signed)
* big_ip modules now support turning off ssl certificate validation (use only for self signed)
* template code now retains types for bools, Numbers and nulls instead of turning them into strings
If you need the old behaviour, quote the value and it will get passed around as a string. In the
case of nulls, the output used to be an empty string.
- template code now retains types for bools and Numbers instead of turning them into strings
- If you need the old behaviour, quote the value and it will get passed around as a string
......
......@@ -32,6 +32,7 @@ import pwd
import ast
import traceback
from numbers import Number
from types import NoneType
from ansible.utils.string_functions import count_newlines_from_end
from ansible.utils import to_bytes, to_unicode
......@@ -343,7 +344,7 @@ def template_from_string(basedir, data, vars, fail_on_undefined=False):
var_name = only_one.group(1)
if var_name in vars:
resolved_val = vars[var_name]
if isinstance(resolved_val, (bool, Number)):
if isinstance(resolved_val, (bool, Number, NoneType)):
return resolved_val
def my_finalize(thing):
......
......@@ -3,6 +3,7 @@ templated_var_loaded
{
"bool": true,
"multi_part": "1Foo",
"null_type": null,
"number": 5,
"string_num": "5"
}
......@@ -5,10 +5,12 @@ string_num: "5"
bool_var: true
part_1: 1
part_2: "Foo"
null_type: !!null
templated_dict:
number: "{{ number_var }}"
string_num: "{{ string_num }}"
null_type: "{{ null_type }}"
bool: "{{ bool_var }}"
multi_part: "{{ part_1 }}{{ part_2 }}"
......@@ -33,6 +33,7 @@ from ansible.template.vars import AnsibleJ2Vars
from ansible.utils.debug import debug
from numbers import Number
from types import NoneType
__all__ = ['Templar']
......@@ -41,7 +42,7 @@ __all__ = ['Templar']
SINGLE_VAR = re.compile(r"^{{\s*(\w*)\s*}}$")
# Primitive Types which we don't want Jinja to convert to strings.
NON_TEMPLATED_TYPES = ( bool, Number )
NON_TEMPLATED_TYPES = ( bool, Number, NoneType )
JINJA2_OVERRIDE = '#jinja2:'
JINJA2_ALLOWED_OVERRIDES = ['trim_blocks', 'lstrip_blocks', 'newline_sequence', 'keep_trailing_newline']
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment