diff --git a/awx/main/models/notifications.py b/awx/main/models/notifications.py index 11d97c7690..33562e7fca 100644 --- a/awx/main/models/notifications.py +++ b/awx/main/models/notifications.py @@ -12,7 +12,7 @@ from django.core.mail.message import EmailMessage from django.db import connection from django.utils.translation import ugettext_lazy as _ from django.utils.encoding import smart_str, force_text -from jinja2 import sandbox +from jinja2 import sandbox, ChainableUndefined from jinja2.exceptions import TemplateSyntaxError, UndefinedError, SecurityError # AWX @@ -429,7 +429,7 @@ class JobNotificationMixin(object): raise RuntimeError("Define me") def build_notification_message(self, nt, status): - env = sandbox.ImmutableSandboxedEnvironment() + env = sandbox.ImmutableSandboxedEnvironment(undefined=ChainableUndefined) from awx.api.serializers import UnifiedJobSerializer job_serialization = UnifiedJobSerializer(self).to_representation(self) diff --git a/awx_collection/test/awx/test_notification_template.py b/awx_collection/test/awx/test_notification_template.py index 28f7c4ecee..96fbd5e56c 100644 --- a/awx_collection/test/awx/test_notification_template.py +++ b/awx_collection/test/awx/test_notification_template.py @@ -3,7 +3,7 @@ __metaclass__ = type import pytest -from awx.main.models import NotificationTemplate +from awx.main.models import NotificationTemplate, Job def compare_with_encrypted(model_config, param_config): @@ -109,3 +109,32 @@ def test_deprecated_to_modern_no_op(run_module, admin_user, organization): ), admin_user) assert not result.get('failed', False), result.get('msg', result) assert not result.pop('changed', None), result + + +@pytest.mark.django_db +def test_build_notification_message_undefined(run_module, admin_user, organization): + """Job notification templates may encounter undefined values in the context when they are + rendered. Make sure that accessing attributes or items of an undefined value returns another + instance of Undefined, rather than raising an UndefinedError. This enables the use of expressions + like "{{ job.created_by.first_name | default('unknown') }}".""" + job = Job.objects.create(name='foobar') + + nt_config = { + 'url': 'http://www.example.com/hook', + 'headers': { + 'X-Custom-Header': 'value123' + } + } + custom_start_template = {'body': '{"started_by": "{{ job.summary_fields.created_by.username | default(\'My Placeholder\') }}"}'} + messages = {'started': custom_start_template, 'success': None, 'error': None, 'workflow_approval': None} + result = run_module('tower_notification_template', dict( + name='foo-notification-template', + organization=organization.name, + notification_type='webhook', + notification_configuration=nt_config, + messages=messages, + ), admin_user) + nt = NotificationTemplate.objects.get(id=result['id']) + + _, body = job.build_notification_message(nt, 'running') + assert '{"started_by": "My Placeholder"}' in body diff --git a/requirements/requirements.in b/requirements/requirements.in index cd06a749fb..f13ccb21b3 100644 --- a/requirements/requirements.in +++ b/requirements/requirements.in @@ -27,7 +27,7 @@ djangorestframework>=3.12.1 djangorestframework-yaml GitPython>=3.1.1 # minimum to fix https://github.com/ansible/awx/issues/6119 irc -jinja2 +jinja2>=2.11.0 # required for ChainableUndefined jsonschema Markdown # used for formatting API help openshift>=0.11.0 # minimum version to pull in new pyyaml for CVE-2017-18342