Source code for freckles.exceptions

# -*- coding: utf-8 -*-
from collections import OrderedDict

from colorama import Style
from jinja2.exceptions import TemplateSyntaxError
from six import string_types

from frutils import readable, reindent, readable_yaml
from frutils.exceptions import FrklException, FrklParseException
from ting.exceptions import TingException


[docs]class FrecklesConfigException(FrklException): def __init__( self, keys=None, msg=None, solution=None, reason=None, references=None ): if keys and isinstance(keys, string_types): keys = [keys] if not msg: if not keys: message = "Configuration error." else: message = "Error with configuration option(s): {}.".format( ", ".join(keys) ) else: message = msg if solution is None: if not keys: solution = "Check documentation for configuration key." else: solution = "Check documentation for configuration key(s): {}.".format( ", ".join(keys) ) references_default = { "freckles configuration documentation": "https://freckles.io/doc/configuration" } if references: references.update(references_default) super(FrecklesConfigException, self).__init__( msg=message, solution=solution, references=references, reason=reason ) self.keys = keys self.msg = msg
[docs]class FrecklesVarException(FrklException): def __init__( self, frecklet=None, frecklet_name=None, var_name=None, errors=None, task_path=None, vars=None, task=None, msg=None, solution=None, references=None, ): self.var_name = var_name self.frecklet = frecklet self.frecklet_name = frecklet_name if self.frecklet is not None and self.frecklet_name is None: self.frecklet_name = self.frecklet.id self.errors = errors self.task_path = task_path self.vars = vars self.task = task if msg is None: msg = "Error validating input for frecklet '{}'.".format(self.frecklet_name) # if len(self.errors) == 1: # reason = Style.BRIGHT + "Var" + Style.RESET_ALL # else: # reason = Style.BRIGHT + "Vars:" + Style.RESET_ALL + "\n" reason = "" for var, error in self.errors.items(): if isinstance(error, string_types): error = [error] reason = reason + Style.DIM + "{}: ".format(var) + Style.RESET_ALL reason = reason + " - ".join(error) reason = reason + "\n" super(FrecklesVarException, self).__init__( msg=msg, reason=reason, solution=solution, references=references ) def __str__(self): msg = "Error processing variables:\n" msg = msg + " frecklet: {}\n".format(self.frecklet_name) if self.task_path is not None: msg = msg + " task path: {}\n".format(self.task_path) msg = msg + " vars:\n " msg = msg + readable(self.vars, out="yaml", indent=4).strip() if self.task is not None: msg = msg + "\n frecklet:\n " msg = msg + readable(self.task["frecklet"], out="yaml", indent=4).strip() msg = msg + "\n error: {}".format(str(self.errors)) return msg
[docs]class FreckletBuildException(FrklException): def __init__(self, frecklet, msg, solution=None, reason=None, references=None): self.frecklet = frecklet super(FreckletBuildException, self).__init__( msg, solution=solution, reason=reason, references=references )
[docs]class InvalidFreckletException(FrklException): def __init__(self, frecklet=None, parent_exception=None, frecklet_name=None): self.frecklet = frecklet self.parent_exception = parent_exception if frecklet_name is None: if self.frecklet is not None: self.frecklet_name = self.frecklet.id else: self.frecklet_name = None else: self.frecklet_name = frecklet_name if self.frecklet_name is None: msg = "Invalid or missing frecklet" else: msg = "Invalid or missing frecklet: '{}'.".format(self.frecklet_name) reason = None if self.frecklet_name is not None: solution = "Check '{}' is a frecklet in any of the repositories of this context, or is a local file. In case you provided a yaml/json/toml string, check its syntax.\n\nIf the frecklet was created dynamically, check the upstream adapter whether there was an error.".format( frecklet_name ) else: solution = "Check frecklet is in any of the repositories of this context, or is a local file. In case you provided a yaml/json/toml string, check its syntax.\n\nIf the frecklet was created dynamically, check the upstream adapter whether there was an error.".format( frecklet_name ) references = {"frecklet documentation": "https://freckles.io/doc/frecklets"} super(InvalidFreckletException, self).__init__( msg, solution=solution, reason=reason, references=references )
[docs]class FreckletException(FrklException): def __init__(self, frecklet, parent_exception, frecklet_name): """ Args: frecklet: parent_exception: frecklet_name: optional frecklet name a command was called with """ self.frecklet = frecklet self.parent_exception = parent_exception if frecklet_name is not None: self.frecklet_name = frecklet_name elif frecklet is not None: self.frecklet_name = frecklet.id else: self.frecklet_name = "n/a" msg = "Can't process frecklet: '{}'".format(self.frecklet_name) # print(parent_exception.__dict__.keys()) # print(parent_exception.root_exc) if isinstance(parent_exception, TingException): root_exc = parent_exception.root_exc if root_exc is not None and isinstance(root_exc, FrklParseException): problem_frecklet = root_exc.content_origin else: problem_frecklet = None if len(parent_exception.attribute_chain) == 1: if problem_frecklet is not None: reason = "Error when processing property of frecklet '{}':\n".format( problem_frecklet.id ) else: reason = "Error when processing frecklet property:\n" else: if ( root_exc is not None and hasattr(root_exc, "reason") and root_exc.reason ): reason = root_exc.reason else: if problem_frecklet is not None: reason = "Error when processing properties of frecklet '{}':\n".format( problem_frecklet.id ) else: reason = "Error when processing frecklet properties:\n" for index, attr in enumerate(parent_exception.attribute_chain): padding = " " * (index + 1) reason = reason + "\n{}-> {}".format(padding, attr) reason = reason + ": {}".format(parent_exception.root_exc) extra_reason = OrderedDict() if hasattr(parent_exception.root_exc, "exception_map"): for k, v in parent_exception.root_exc.exception_map.items(): potential_attrs = ["problem", "problem_mark", "msg"] for a in potential_attrs: if hasattr(v, a): extra_reason.setdefault(k, OrderedDict())[a] = str( getattr(v, a) ) if extra_reason: text = "" for t, details in extra_reason.items(): text = ( text + "if type: {}{}{}".format(Style.BRIGHT, t, Style.RESET_ALL) + "\n\n" ) text = ( text + Style.DIM + readable_yaml( details, ignore_aliases=True, safe=False, indent=2 ) + Style.RESET_ALL + "\n" ) reason = reason + "\n\n" + reindent(text, 2) if hasattr(parent_exception.root_exc, "solution"): solution = parent_exception.root_exc.solution else: solution = "Check format of frecklet '{}'.".format( parent_exception.ting.id ) if hasattr(parent_exception.root_exc, "references"): references = parent_exception.root_exc.references else: references = { "frecklet documentation": "https://freckles.io/doc/frecklets" } elif isinstance(parent_exception, TemplateSyntaxError): reason = "Template syntax error: {}".format(str(parent_exception)) solution = "Check format of frecklet '{}' (probably line {}):\n\n".format( frecklet.id, parent_exception.lineno ) solution = solution + reindent(parent_exception.source, 4, line_nrs=1) references = { "frecklet documentation": "https://freckles.io/doc/frecklets", "jinja2 documentation": "http://jinja.pocoo.org/docs", } else: if self.frecklet_name == "n/a": solution = "Check format of frecklets. Can't say which ones, too little information." else: solution = "Check format of frecklet '{}' and all of its childs.".format( self.frecklet_name ) references = {"frecklet documentation": "https://freckles.io/doc/frecklets"} reason = None super(FreckletException, self).__init__( msg, solution=solution, reason=reason, references=references )
[docs]class FrecklesPermissionException(FrklException): def __init__( self, key=None, msg=None, solution=None, reason=None, addition_references=None ): if not msg: if not key: message = "Access to context config key denied." else: message = "Access to context config key '{}' denied.".format(key) else: message = msg if solution is None: solution = "Adjust configuration to allow permissions to this key" references = { "freckles configuration documentation": "https://freckles.io/doc/configuration" } if addition_references: references.update(addition_references) super(FrecklesPermissionException, self).__init__( message, solution=solution, reason=reason, references=references ) self.key = key self.msg = msg
[docs]class FrecklesUnlockException(FrklException): def __init__(self, message): if not message: message = "Access to context config denied." solution = "Unlock freckles configuration with: 'freckles config unlock'" references = { "freckles configuration documentation": "https://freckles.io/doc/configuration" } super(FrecklesUnlockException, self).__init__( message, solution=solution, references=references, reason="freckles config not unlocked.", )
[docs]class FrecklesRunException(FrklException): def __init__(self, msg=None, run_info=None): self._run_info = run_info reason = None if msg is None: if run_info is None: msg = "n/a" else: e = run_info.exception if e: if isinstance(e, FrklException): msg = e.message else: msg = str(e) self._failed_tasks = None if self._run_info: self._failed_tasks = self._run_info.root_task._tasks.get_failed_tasks() if self._failed_tasks: reason = "failed tasks:\n" for t in self._failed_tasks: reason = reason + "\n {}\n".format(t._task_name) t_msg = t.get_messages() if t_msg: reason = reason + " {}\n".format(t_msg) err = t.get_error_messages() if err: reason = reason + " {}\n".format(err) super(FrecklesRunException, self).__init__(msg, reason=reason)