Merge pull request #10465 from feanil/feanil/fix_templates_for_ints_bools
Don't convert numbers and booleans to strings.
This commit is contained in:
commit
de52cfb5d7
6 changed files with 71 additions and 7 deletions
|
@ -4,7 +4,10 @@ Ansible Changes By Release
|
||||||
## 2.0 "TBD" - ACTIVE DEVELOPMENT
|
## 2.0 "TBD" - ACTIVE DEVELOPMENT
|
||||||
|
|
||||||
Major Changes:
|
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 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
|
||||||
|
|
||||||
New Modules:
|
New Modules:
|
||||||
cloudtrail
|
cloudtrail
|
||||||
|
|
|
@ -31,6 +31,7 @@ import datetime
|
||||||
import pwd
|
import pwd
|
||||||
import ast
|
import ast
|
||||||
import traceback
|
import traceback
|
||||||
|
from numbers import Number
|
||||||
|
|
||||||
from ansible.utils.string_functions import count_newlines_from_end
|
from ansible.utils.string_functions import count_newlines_from_end
|
||||||
from ansible.utils import to_bytes, to_unicode
|
from ansible.utils import to_bytes, to_unicode
|
||||||
|
@ -81,6 +82,11 @@ class Flags:
|
||||||
|
|
||||||
FILTER_PLUGINS = None
|
FILTER_PLUGINS = None
|
||||||
_LISTRE = re.compile(r"(\w+)\[(\d+)\]")
|
_LISTRE = re.compile(r"(\w+)\[(\d+)\]")
|
||||||
|
|
||||||
|
# A regex for checking to see if a variable we're trying to
|
||||||
|
# expand is just a single variable name.
|
||||||
|
SINGLE_VAR = re.compile(r"^{{\s*(\w*)\s*}}$")
|
||||||
|
|
||||||
JINJA2_OVERRIDE = '#jinja2:'
|
JINJA2_OVERRIDE = '#jinja2:'
|
||||||
JINJA2_ALLOWED_OVERRIDES = ['trim_blocks', 'lstrip_blocks', 'newline_sequence', 'keep_trailing_newline']
|
JINJA2_ALLOWED_OVERRIDES = ['trim_blocks', 'lstrip_blocks', 'newline_sequence', 'keep_trailing_newline']
|
||||||
|
|
||||||
|
@ -109,7 +115,6 @@ def lookup(name, *args, **kwargs):
|
||||||
def template(basedir, varname, templatevars, lookup_fatal=True, depth=0, expand_lists=True, convert_bare=False, fail_on_undefined=False, filter_fatal=True):
|
def template(basedir, varname, templatevars, lookup_fatal=True, depth=0, expand_lists=True, convert_bare=False, fail_on_undefined=False, filter_fatal=True):
|
||||||
''' templates a data structure by traversing it and substituting for other data structures '''
|
''' templates a data structure by traversing it and substituting for other data structures '''
|
||||||
from ansible import utils
|
from ansible import utils
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if convert_bare and isinstance(varname, basestring):
|
if convert_bare and isinstance(varname, basestring):
|
||||||
first_part = varname.split(".")[0].split("[")[0]
|
first_part = varname.split(".")[0].split("[")[0]
|
||||||
|
@ -123,10 +128,13 @@ def template(basedir, varname, templatevars, lookup_fatal=True, depth=0, expand_
|
||||||
except errors.AnsibleError, e:
|
except errors.AnsibleError, e:
|
||||||
raise errors.AnsibleError("Failed to template %s: %s" % (varname, str(e)))
|
raise errors.AnsibleError("Failed to template %s: %s" % (varname, str(e)))
|
||||||
|
|
||||||
if (varname.startswith("{") and not varname.startswith("{{")) or varname.startswith("["):
|
# template_from_string may return non strings for the case where the var is just
|
||||||
eval_results = utils.safe_eval(varname, locals=templatevars, include_exceptions=True)
|
# a reference to a single variable, so we should re_check before we do further evals
|
||||||
if eval_results[1] is None:
|
if isinstance(varname, basestring):
|
||||||
varname = eval_results[0]
|
if (varname.startswith("{") and not varname.startswith("{{")) or varname.startswith("["):
|
||||||
|
eval_results = utils.safe_eval(varname, locals=templatevars, include_exceptions=True)
|
||||||
|
if eval_results[1] is None:
|
||||||
|
varname = eval_results[0]
|
||||||
|
|
||||||
return varname
|
return varname
|
||||||
|
|
||||||
|
@ -323,10 +331,20 @@ def template_from_file(basedir, path, vars, vault_password=None):
|
||||||
|
|
||||||
def template_from_string(basedir, data, vars, fail_on_undefined=False):
|
def template_from_string(basedir, data, vars, fail_on_undefined=False):
|
||||||
''' run a string through the (Jinja2) templating engine '''
|
''' run a string through the (Jinja2) templating engine '''
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if type(data) == str:
|
if type(data) == str:
|
||||||
data = unicode(data, 'utf-8')
|
data = unicode(data, 'utf-8')
|
||||||
|
|
||||||
|
# Check to see if the string we are trying to render is just referencing a single
|
||||||
|
# var. In this case we don't wont to accidentally change the type of the variable
|
||||||
|
# to a string by using the jinja template renderer. We just want to pass it.
|
||||||
|
only_one = SINGLE_VAR.match(data)
|
||||||
|
if only_one:
|
||||||
|
var_name = only_one.group(1)
|
||||||
|
if var_name in vars:
|
||||||
|
resolved_val = vars[var_name]
|
||||||
|
if isinstance(resolved_val, (bool, Number)):
|
||||||
|
return resolved_val
|
||||||
|
|
||||||
def my_finalize(thing):
|
def my_finalize(thing):
|
||||||
return thing if thing is not None else ''
|
return thing if thing is not None else ''
|
||||||
|
|
|
@ -1 +1,8 @@
|
||||||
templated_var_loaded
|
templated_var_loaded
|
||||||
|
|
||||||
|
{
|
||||||
|
"bool": true,
|
||||||
|
"multi_part": "1Foo",
|
||||||
|
"number": 5,
|
||||||
|
"string_num": "5"
|
||||||
|
}
|
||||||
|
|
|
@ -1 +1,3 @@
|
||||||
{{ templated_var }}
|
{{ templated_var }}
|
||||||
|
|
||||||
|
{{ templated_dict | to_nice_json }}
|
||||||
|
|
|
@ -1 +1,14 @@
|
||||||
templated_var: templated_var_loaded
|
templated_var: templated_var_loaded
|
||||||
|
|
||||||
|
number_var: 5
|
||||||
|
string_num: "5"
|
||||||
|
bool_var: true
|
||||||
|
part_1: 1
|
||||||
|
part_2: "Foo"
|
||||||
|
|
||||||
|
templated_dict:
|
||||||
|
number: "{{ number_var }}"
|
||||||
|
string_num: "{{ string_num }}"
|
||||||
|
bool: "{{ bool_var }}"
|
||||||
|
multi_part: "{{ part_1 }}{{ part_2 }}"
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,17 @@ from ansible.template.template import AnsibleJ2Template
|
||||||
from ansible.template.vars import AnsibleJ2Vars
|
from ansible.template.vars import AnsibleJ2Vars
|
||||||
from ansible.utils.debug import debug
|
from ansible.utils.debug import debug
|
||||||
|
|
||||||
|
from numbers import Number
|
||||||
|
|
||||||
__all__ = ['Templar']
|
__all__ = ['Templar']
|
||||||
|
|
||||||
|
# A regex for checking to see if a variable we're trying to
|
||||||
|
# expand is just a single variable name.
|
||||||
|
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 )
|
||||||
|
|
||||||
JINJA2_OVERRIDE = '#jinja2:'
|
JINJA2_OVERRIDE = '#jinja2:'
|
||||||
JINJA2_ALLOWED_OVERRIDES = ['trim_blocks', 'lstrip_blocks', 'newline_sequence', 'keep_trailing_newline']
|
JINJA2_ALLOWED_OVERRIDES = ['trim_blocks', 'lstrip_blocks', 'newline_sequence', 'keep_trailing_newline']
|
||||||
|
|
||||||
|
@ -125,6 +134,18 @@ class Templar:
|
||||||
if isinstance(variable, basestring):
|
if isinstance(variable, basestring):
|
||||||
result = variable
|
result = variable
|
||||||
if self._contains_vars(variable):
|
if self._contains_vars(variable):
|
||||||
|
|
||||||
|
# Check to see if the string we are trying to render is just referencing a single
|
||||||
|
# var. In this case we don't wont to accidentally change the type of the variable
|
||||||
|
# to a string by using the jinja template renderer. We just want to pass it.
|
||||||
|
only_one = SINGLE_VAR.match(variable)
|
||||||
|
if only_one:
|
||||||
|
var_name = only_one.group(1)
|
||||||
|
if var_name in self._available_vars:
|
||||||
|
resolved_val = self._available_vars[var_name]
|
||||||
|
if isinstance(resolved_val, NON_TEMPLATED_TYPES):
|
||||||
|
return resolved_val
|
||||||
|
|
||||||
result = self._do_template(variable, preserve_trailing_newlines=preserve_trailing_newlines)
|
result = self._do_template(variable, preserve_trailing_newlines=preserve_trailing_newlines)
|
||||||
|
|
||||||
# if this looks like a dictionary or list, convert it to such using the safe_eval method
|
# if this looks like a dictionary or list, convert it to such using the safe_eval method
|
||||||
|
|
Loading…
Reference in a new issue