def _do_template(self, data, preserve_trailing_newlines=True, escape_backslashes=True, fail_on_undefined=None, overrides=None): # For preserving the number of input newlines in the output (used # later in this method) data_newlines = _count_newlines_from_end(data) if fail_on_undefined is None: fail_on_undefined = self._fail_on_undefined_errors try: # allows template header overrides to change jinja2 options. if overrides is None: myenv = self.environment.overlay() else: myenv = self.environment.overlay(overrides) # Get jinja env overrides from template if data.startswith(JINJA2_OVERRIDE): eol = data.find('\n') line = data[len(JINJA2_OVERRIDE):eol] data = data[eol+1:] for pair in line.split(','): (key,val) = pair.split(':') key = key.strip() setattr(myenv, key, ast.literal_eval(val.strip())) #FIXME: add tests myenv.filters.update(self._get_filters()) myenv.tests.update(self._get_tests()) if escape_backslashes: # Allow users to specify backslashes in playbooks as "\\" # instead of as "\\\\". data = _escape_backslashes(data, myenv) try: t = myenv.from_string(data) except TemplateSyntaxError as e: raise AnsibleError("template error while templating string: %s. String: %s" % (to_native(e), to_native(data))) except Exception as e: if 'recursion' in to_native(e): raise AnsibleError("recursive loop detected in template string: %s" % to_native(data)) else: return data t.globals['lookup'] = self._lookup t.globals['finalize'] = self._finalize jvars = AnsibleJ2Vars(self, t.globals) new_context = t.new_context(jvars, shared=True) rf = t.root_render_func(new_context) try: res = j2_concat(rf) except TypeError as te: if 'StrictUndefined' in to_native(te): errmsg = "Unable to look up a name or access an attribute in template string (%s).\n" % to_native(data) errmsg += "Make sure your variable name does not contain invalid characters like '-': %s" % to_native(te) raise AnsibleUndefinedVariable(errmsg) else: display.debug("failing because of a type error, template data is: %s" % to_native(data)) raise AnsibleError("Unexpected templating type error occurred on (%s): %s" % (to_native(data),to_native(te))) if preserve_trailing_newlines: # The low level calls above do not preserve the newline # characters at the end of the input data, so we use the # calculate the difference in newlines and append them # to the resulting output for parity # # jinja2 added a keep_trailing_newline option in 2.7 when # creating an Environment. That would let us make this code # better (remove a single newline if # preserve_trailing_newlines is False). Once we can depend on # that version being present, modify our code to set that when # initializing self.environment and remove a single trailing # newline here if preserve_newlines is False. res_newlines = _count_newlines_from_end(res) if data_newlines > res_newlines: res += '\n' * (data_newlines - res_newlines) return res except (UndefinedError, AnsibleUndefinedVariable) as e: if fail_on_undefined: raise AnsibleUndefinedVariable(e) else: #TODO: return warning about undefined var return data
def do_template(self, data, preserve_trailing_newlines=True, escape_backslashes=True, fail_on_undefined=None, overrides=None, disable_lookups=False): # For preserving the number of input newlines in the output (used # later in this method) data_newlines = _count_newlines_from_end(data) if fail_on_undefined is None: fail_on_undefined = self._fail_on_undefined_errors try: # allows template header overrides to change jinja2 options. if overrides is None: myenv = self.environment.overlay() else: myenv = self.environment.overlay(overrides) # Get jinja env overrides from template if data.startswith(JINJA2_OVERRIDE): eol = data.find('\n') line = data[len(JINJA2_OVERRIDE):eol] data = data[eol + 1:] for pair in line.split(','): (key, val) = pair.split(':') key = key.strip() setattr(myenv, key, ast.literal_eval(val.strip())) # Adds Ansible custom filters and tests myenv.filters.update(self._get_filters(myenv.filters)) myenv.tests.update(self._get_tests()) if escape_backslashes: # Allow users to specify backslashes in playbooks as "\\" instead of as "\\\\". data = _escape_backslashes(data, myenv) try: t = myenv.from_string(data) except TemplateSyntaxError as e: raise AnsibleError( "template error while templating string: %s. String: %s" % (to_native(e), to_native(data))) except Exception as e: if 'recursion' in to_native(e): raise AnsibleError( "recursive loop detected in template string: %s" % to_native(data)) else: return data if disable_lookups: t.globals['query'] = t.globals['q'] = t.globals[ 'lookup'] = self._fail_lookup else: t.globals['lookup'] = self._lookup t.globals['query'] = t.globals['q'] = self._query_lookup t.globals['finalize'] = self._finalize jvars = AnsibleJ2Vars(self, t.globals) self.cur_context = new_context = t.new_context(jvars, shared=True) rf = t.root_render_func(new_context) try: res = j2_concat(rf) if new_context.unsafe: res = wrap_var(res) except TypeError as te: if 'StrictUndefined' in to_native(te): errmsg = "Unable to look up a name or access an attribute in template string (%s).\n" % to_native( data) errmsg += "Make sure your variable name does not contain invalid characters like '-': %s" % to_native( te) raise AnsibleUndefinedVariable(errmsg) else: display.debug( "failing because of a type error, template data is: %s" % to_native(data)) raise AnsibleError( "Unexpected templating type error occurred on (%s): %s" % (to_native(data), to_native(te))) if preserve_trailing_newlines: # The low level calls above do not preserve the newline # characters at the end of the input data, so we use the # calculate the difference in newlines and append them # to the resulting output for parity # # jinja2 added a keep_trailing_newline option in 2.7 when # creating an Environment. That would let us make this code # better (remove a single newline if # preserve_trailing_newlines is False). Once we can depend on # that version being present, modify our code to set that when # initializing self.environment and remove a single trailing # newline here if preserve_newlines is False. res_newlines = _count_newlines_from_end(res) if data_newlines > res_newlines: res += self.environment.newline_sequence * (data_newlines - res_newlines) return res except (UndefinedError, AnsibleUndefinedVariable) as e: if fail_on_undefined: raise AnsibleUndefinedVariable(e) else: display.debug("Ignoring undefined failure: %s" % to_text(e)) return data
except Exception, e: if 'recursion' in str(e): raise AnsibleError("recursive loop detected in template string: %s" % data) else: return data t.globals['lookup'] = self._lookup t.globals['finalize'] = self._finalize jvars = AnsibleJ2Vars(self, t.globals) new_context = t.new_context(jvars, shared=True) rf = t.root_render_func(new_context) try: res = j2_concat(rf) except TypeError, te: if 'StrictUndefined' in str(te): raise AnsibleUndefinedVariable( "Unable to look up a name or access an attribute in template string. " + \ "Make sure your variable name does not contain invalid characters like '-'." ) else: debug("failing because of a type error, template data is: %s" % data) raise AnsibleError("an unexpected type error occurred. Error was %s" % te) if preserve_trailing_newlines: # The low level calls above do not preserve the newline # characters at the end of the input data, so we use the # calculate the difference in newlines and append them # to the resulting output for parity
def _do_template(self, data, preserve_trailing_newlines=False, fail_on_undefined=None, overrides=None): if fail_on_undefined is None: fail_on_undefined = self._fail_on_undefined_errors try: # allows template header overrides to change jinja2 options. if overrides is None: myenv = self.environment.overlay() else: myenv = self.environment.overlay(overrides) # Get jinja env overrides from template if data.startswith(JINJA2_OVERRIDE): eol = data.find('\n') line = data[len(JINJA2_OVERRIDE):eol] data = data[eol + 1:] for pair in line.split(','): (key, val) = pair.split(':') key = key.strip() setattr(myenv, key, ast.literal_eval(val.strip())) #FIXME: add tests myenv.filters.update(self._get_filters()) myenv.tests.update(self._get_tests()) data = _preserve_backslashes(data, myenv) try: t = myenv.from_string(data) except TemplateSyntaxError as e: raise AnsibleError( "template error while templating string: %s" % str(e)) except Exception as e: if 'recursion' in str(e): raise AnsibleError( "recursive loop detected in template string: %s" % data) else: return data t.globals['lookup'] = self._lookup t.globals['finalize'] = self._finalize jvars = AnsibleJ2Vars(self, t.globals) new_context = t.new_context(jvars, shared=True) rf = t.root_render_func(new_context) try: res = j2_concat(rf) except TypeError as te: if 'StrictUndefined' in str(te): raise AnsibleUndefinedVariable( "Unable to look up a name or access an attribute in template string. " + \ "Make sure your variable name does not contain invalid characters like '-'." ) else: debug( "failing because of a type error, template data is: %s" % data) raise AnsibleError( "an unexpected type error occurred. Error was %s" % te) if preserve_trailing_newlines: # The low level calls above do not preserve the newline # characters at the end of the input data, so we use the # calculate the difference in newlines and append them # to the resulting output for parity res_newlines = self._count_newlines_from_end(res) data_newlines = self._count_newlines_from_end(data) if data_newlines > res_newlines: res += '\n' * (data_newlines - res_newlines) return res except (UndefinedError, AnsibleUndefinedVariable) as e: if fail_on_undefined: raise AnsibleUndefinedVariable(e) else: #TODO: return warning about undefined var return data