This is an automated email from the ASF dual-hosted git repository. ephraimanierobi pushed a commit to branch v2-3-test in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 146d5109b45afe7e2feaf467dbd97a3955ad8996 Author: ecodina <[email protected]> AuthorDate: Mon Jul 18 20:22:03 2022 +0200 Added exception catching to send default email if template file raises any exception (#24943) (cherry picked from commit fd6f537eab7430cb10ea057194bfc9519ff0bb38) --- airflow/models/taskinstance.py | 9 +++++++-- tests/models/test_taskinstance.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/airflow/models/taskinstance.py b/airflow/models/taskinstance.py index afcc469feb..c369e84e47 100644 --- a/airflow/models/taskinstance.py +++ b/airflow/models/taskinstance.py @@ -2337,8 +2337,13 @@ class TaskInstance(Base, LoggingMixin): def render(key: str, content: str) -> str: if conf.has_option('email', key): path = conf.get_mandatory_value('email', key) - with open(path) as f: - content = f.read() + try: + with open(path) as f: + content = f.read() + except FileNotFoundError: + self.log.warning(f"Could not find email template file '{path!r}'. Using defaults...") + except OSError: + self.log.exception(f"Error while using email template '{path!r}'. Using defaults...") return render_template_to_string(jinja_env.from_string(content), jinja_context) subject = render('subject_template', default_subject) diff --git a/tests/models/test_taskinstance.py b/tests/models/test_taskinstance.py index 3990c3cbf5..1db5542904 100644 --- a/tests/models/test_taskinstance.py +++ b/tests/models/test_taskinstance.py @@ -1392,6 +1392,40 @@ class TestTaskInstance: assert 'template: test_email_alert_with_config' == title assert 'template: test_email_alert_with_config' == body + @patch('airflow.models.taskinstance.send_email') + def test_email_alert_with_filenotfound_config(self, mock_send_email, dag_maker): + with dag_maker(dag_id='test_failure_email'): + task = BashOperator( + task_id='test_email_alert_with_config', + bash_command='exit 1', + email='to', + ) + ti = dag_maker.create_dagrun(execution_date=timezone.utcnow()).task_instances[0] + ti.task = task + + # Run test when the template file is not found + opener = mock_open(read_data='template: {{ti.task_id}}') + opener.side_effect = FileNotFoundError + with patch('airflow.models.taskinstance.open', opener, create=True): + try: + ti.run() + except AirflowException: + pass + + (email_error, title_error, body_error), _ = mock_send_email.call_args + + # Rerun task without any error and no template file + try: + ti.run() + except AirflowException: + pass + + (email_default, title_default, body_default), _ = mock_send_email.call_args + + assert email_error == email_default == 'to' + assert title_default == title_error + assert body_default == body_error + @pytest.mark.parametrize("task_id", ["test_email_alert", "test_email_alert__1"]) @patch('airflow.models.taskinstance.send_email') def test_failure_mapped_taskflow(self, mock_send_email, dag_maker, session, task_id):
