Jinja2 raise extension

Extend Jinja2 envrionment with a raise method so that
we can add logic in Jinja2 and raise errors.

In jinja2 template the raise method can be used like this:

 {%- if condition %}
   {{ raise('MESSAGE') }}
 {%- endif %}

Change-Id: Idaa1d570b129aa6c8c117b8087d1aad7ae987a47
This commit is contained in:
Harald Jensås 2020-05-11 10:21:53 +02:00
parent 0157539464
commit 675f8bc64f
3 changed files with 37 additions and 2 deletions

View File

@ -0,0 +1,12 @@
---
other:
- |
The jinja2 template rendering function is extensended with a ``raise``
method. This can be used to raise errors conditionally in the Jinja2
templated tripleo-heat-tempaltes, for example in case some required property
is not defined in roles_data or network_data. The following example
demonstrates how to raise an error conditionally in a template::
{%- if condition %}
{{ raise('MESSAGE') }}
{%- endif %}

View File

@ -37,6 +37,11 @@ JINJA_SNIPPET = r"""
DefaultPasswords: {get_attr: [DefaultPasswords, passwords]}
{% endfor %}"""
JINJA_RAISE_CONFIG = r"""
# Jinja raise extension
{{ raise('MESSAGE') }}
"""
ROLE_DATA_YAML = r"""
-
name: CustomRole
@ -390,6 +395,20 @@ class ProcessTemplatesTest(base.TestCase):
self.assertTrue(
{'name': []} == template_utils.get_j2_excludes_file(swift))
def test_j2_render_and_put_raise_in_template(self):
# setup swift
swift = mock.MagicMock()
swift.get_object = mock.MagicMock()
swift.get_container = mock.MagicMock()
# Test
args = (swift, JINJA_RAISE_CONFIG, {'role': 'CustomRole'},
'customrole-config.yaml', constants.DEFAULT_CONTAINER_NAME)
self.assertRaises(RuntimeError,
template_utils.j2_render_and_put,
*args)
def test_heat_resource_exists(self):
heat_client = mock.MagicMock()
stack = mock.MagicMock(stack_name='overcloud')

View File

@ -64,14 +64,18 @@ class J2SwiftLoader(jinja2.BaseLoader):
def j2_render_and_put(swift, j2_template, j2_data, yaml_f,
container=constants.DEFAULT_CONTAINER_NAME):
def raise_helper(msg):
raise jinja2.exceptions.TemplateError(msg)
# Search for templates relative to the current template path first
template_base = os.path.dirname(yaml_f)
j2_loader = J2SwiftLoader(swift, container, template_base)
try:
# Render the j2 template
template = jinja2.Environment(loader=j2_loader).from_string(
j2_template)
jinja2_env = jinja2.Environment(loader=j2_loader)
jinja2_env.globals['raise'] = raise_helper
template = jinja2_env.from_string(j2_template)
r_template = template.render(**j2_data)
except jinja2.exceptions.TemplateError as ex:
error_msg = ("Error rendering template %s : %s"