Skip to content

Commit

Permalink
Refactor Jinja error handling and add stack trace
Browse files Browse the repository at this point in the history
  • Loading branch information
jmpettit authored and Justin Pettit committed Mar 21, 2024
1 parent bab83ce commit 7927d2f
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 24 deletions.
41 changes: 17 additions & 24 deletions nornir_nautobot/plugins/tasks/dispatcher/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from nornir_netmiko.tasks import netmiko_send_command

from nornir_nautobot.exceptions import NornirNautobotException
from nornir_nautobot.utils.helpers import make_folder
from nornir_nautobot.utils.helpers import make_folder, format_jinja_stack_trace

_logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -174,29 +174,22 @@ def generate_config(
jinja_env=jinja_env,
)[0].result
except NornirSubTaskError as exc:
if isinstance(exc.result.exception, jinja2.exceptions.UndefinedError): # pylint: disable=no-else-raise
error_msg = (
f"`E1010:` There was a jinja2.exceptions.UndefinedError error: ``{str(exc.result.exception)}``"
)
logger.error(error_msg, extra={"object": obj})
raise NornirNautobotException(error_msg)

elif isinstance(exc.result.exception, jinja2.TemplateSyntaxError):
error_msg = (f"`E1011:` There was a jinja2.TemplateSyntaxError error: ``{str(exc.result.exception)}``",)
logger.error(error_msg, extra={"object": obj})
raise NornirNautobotException(error_msg)

elif isinstance(exc.result.exception, jinja2.TemplateNotFound):
error_msg = f"`E1012:` There was an issue finding the template and a jinja2.TemplateNotFound error was raised: ``{str(exc.result.exception)}``"
logger.error(error_msg, extra={"object": obj})
raise NornirNautobotException(error_msg)

elif isinstance(exc.result.exception, jinja2.TemplateError):
error_msg = f"`E1013:` There was an issue general Jinja error: ``{str(exc.result.exception)}``"
logger.error(error_msg, extra={"object": obj})
raise NornirNautobotException(error_msg)

error_msg = f"`E1014:` Failed with an unknown issue. `{exc.result.exception}`"
stack_trace = format_jinja_stack_trace(exc.result.exception)

error_mapping = {
jinja2.exceptions.UndefinedError: ("E1010", "Undefined variable in Jinja2 template"),
jinja2.TemplateSyntaxError: ("E1011", "Syntax error in Jinja2 template"),
jinja2.TemplateNotFound: ("E1012", "Jinja2 template not found"),
jinja2.TemplateError: ("E1013", "General Jinja2 template error"),
}

for error, (code, message) in error_mapping.items():
if isinstance(exc.result.exception, error):
error_msg = f"`{code}:` {message} - ``{str(exc.result.exception)}``\n```\n{stack_trace}\n```"
logger.error(error_msg, extra={"object": obj})
raise NornirNautobotException(error_msg)

error_msg = f"`E1014:` Unknown error - {exc.result.exception}\n```\n{stack_trace}\n```"
logger.error(error_msg, extra={"object": obj})
raise NornirNautobotException(error_msg)

Expand Down
7 changes: 7 additions & 0 deletions nornir_nautobot/utils/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import os
import logging
import importlib
import traceback

LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -31,3 +32,9 @@ def import_string(dotted_path):
return getattr(importlib.import_module(module_name), class_name)
except (ModuleNotFoundError, AttributeError):
return None

def format_jinja_stack_trace(exc: Exception) -> str:
"""Generate and format a stack trace string for a given Jinja exception."""
stack_trace_lines = traceback.format_exception(type(exc), exc, exc.__traceback__)
stack_trace_lines = [line for line in stack_trace_lines if '.j2' in line or '{{' in line]
return "\n".join(stack_trace_lines)

0 comments on commit 7927d2f

Please sign in to comment.