mirror of
https://github.com/checktheroads/hyperglass
synced 2024-05-11 05:55:08 +00:00
refactor response model
This commit is contained in:
@@ -1,29 +1,30 @@
|
||||
"""Custom exceptions for hyperglass."""
|
||||
|
||||
# Standard Library Imports
|
||||
# Third Party Imports
|
||||
import ujson as _json
|
||||
|
||||
# Project Imports
|
||||
from hyperglass.constants import STATUS_CODE_MAP
|
||||
from hyperglass.util import log
|
||||
|
||||
|
||||
class HyperglassError(Exception):
|
||||
"""hyperglass base exception."""
|
||||
|
||||
def __init__(self, message="", alert="warning", keywords=None):
|
||||
def __init__(self, message="", level="warning", keywords=None):
|
||||
"""Initialize the hyperglass base exception class.
|
||||
|
||||
Keyword Arguments:
|
||||
message {str} -- Error message (default: {""})
|
||||
alert {str} -- Error severity (default: {"warning"})
|
||||
level {str} -- Error severity (default: {"warning"})
|
||||
keywords {list} -- 'Important' keywords (default: {None})
|
||||
"""
|
||||
self._message = message
|
||||
self._alert = alert
|
||||
self._level = level
|
||||
self._keywords = keywords or []
|
||||
if self._alert == "warning":
|
||||
if self._level == "warning":
|
||||
log.error(repr(self))
|
||||
elif self._alert == "danger":
|
||||
elif self._level == "danger":
|
||||
log.critical(repr(self))
|
||||
else:
|
||||
log.info(repr(self))
|
||||
@@ -42,7 +43,7 @@ class HyperglassError(Exception):
|
||||
Returns:
|
||||
{str} -- Error message with code
|
||||
"""
|
||||
return f"[{self.alert.upper()}] {self._message}"
|
||||
return f"[{self.level.upper()}] {self._message}"
|
||||
|
||||
def dict(self):
|
||||
"""Return the instance's attributes as a dictionary.
|
||||
@@ -52,7 +53,7 @@ class HyperglassError(Exception):
|
||||
"""
|
||||
return {
|
||||
"message": self._message,
|
||||
"alert": self._alert,
|
||||
"level": self._level,
|
||||
"keywords": self._keywords,
|
||||
}
|
||||
|
||||
@@ -74,13 +75,13 @@ class HyperglassError(Exception):
|
||||
return self._message
|
||||
|
||||
@property
|
||||
def alert(self):
|
||||
"""Return the instance's `alert` attribute.
|
||||
def level(self):
|
||||
"""Return the instance's `level` attribute.
|
||||
|
||||
Returns:
|
||||
{str} -- Alert name
|
||||
"""
|
||||
return self._alert
|
||||
return self._level
|
||||
|
||||
@property
|
||||
def keywords(self):
|
||||
@@ -91,38 +92,47 @@ class HyperglassError(Exception):
|
||||
"""
|
||||
return self._keywords
|
||||
|
||||
@property
|
||||
def status_code(self):
|
||||
"""Return HTTP status code based on level level.
|
||||
|
||||
Returns:
|
||||
{int} -- HTTP Status Code
|
||||
"""
|
||||
return STATUS_CODE_MAP.get(self._level, 500)
|
||||
|
||||
|
||||
class _UnformattedHyperglassError(HyperglassError):
|
||||
"""Base exception class for freeform error messages."""
|
||||
|
||||
_alert = "warning"
|
||||
_level = "warning"
|
||||
|
||||
def __init__(self, unformatted_msg="", alert=None, **kwargs):
|
||||
def __init__(self, unformatted_msg="", level=None, **kwargs):
|
||||
"""Format error message with keyword arguments.
|
||||
|
||||
Keyword Arguments:
|
||||
message {str} -- Error message (default: {""})
|
||||
alert {str} -- Error severity (default: {"warning"})
|
||||
level {str} -- Error severity (default: {"warning"})
|
||||
keywords {list} -- 'Important' keywords (default: {None})
|
||||
"""
|
||||
self._message = unformatted_msg.format(**kwargs)
|
||||
self._alert = alert or self._alert
|
||||
self._level = level or self._level
|
||||
self._keywords = list(kwargs.values())
|
||||
super().__init__(
|
||||
message=self._message, alert=self._alert, keywords=self._keywords
|
||||
message=self._message, level=self._level, keywords=self._keywords
|
||||
)
|
||||
|
||||
|
||||
class _PredefinedHyperglassError(HyperglassError):
|
||||
_message = "undefined"
|
||||
_alert = "warning"
|
||||
_level = "warning"
|
||||
|
||||
def __init__(self, alert=None, **kwargs):
|
||||
def __init__(self, level=None, **kwargs):
|
||||
self._fmt_msg = self._message.format(**kwargs)
|
||||
self._alert = alert or self._alert
|
||||
self._level = level or self._level
|
||||
self._keywords = list(kwargs.values())
|
||||
super().__init__(
|
||||
message=self._fmt_msg, alert=self._alert, keywords=self._keywords
|
||||
message=self._fmt_msg, level=self._level, keywords=self._keywords
|
||||
)
|
||||
|
||||
|
||||
@@ -148,25 +158,25 @@ class ConfigMissing(_PredefinedHyperglassError):
|
||||
class ScrapeError(_UnformattedHyperglassError):
|
||||
"""Raised when a scrape/netmiko error occurs."""
|
||||
|
||||
_alert = "danger"
|
||||
_level = "danger"
|
||||
|
||||
|
||||
class AuthError(_UnformattedHyperglassError):
|
||||
"""Raised when authentication to a device fails."""
|
||||
|
||||
_alert = "danger"
|
||||
_level = "danger"
|
||||
|
||||
|
||||
class RestError(_UnformattedHyperglassError):
|
||||
"""Raised upon a rest API client error."""
|
||||
|
||||
_alert = "danger"
|
||||
_level = "danger"
|
||||
|
||||
|
||||
class DeviceTimeout(_UnformattedHyperglassError):
|
||||
"""Raised when the connection to a device times out."""
|
||||
|
||||
_alert = "danger"
|
||||
_level = "danger"
|
||||
|
||||
|
||||
class InputInvalid(_UnformattedHyperglassError):
|
||||
|
@@ -37,7 +37,7 @@ class Construct:
|
||||
if not _device_vrf:
|
||||
raise HyperglassError(
|
||||
message="Unable to match query VRF to any configured VRFs",
|
||||
alert="danger",
|
||||
level="danger",
|
||||
keywords=[self.query_vrf],
|
||||
)
|
||||
return _device_vrf
|
||||
|
@@ -169,7 +169,7 @@ def ip_access_list(query_data, device):
|
||||
if not vrf_acl:
|
||||
raise HyperglassError(
|
||||
message="Unable to match query VRF to any configured VRFs",
|
||||
alert="danger",
|
||||
level="danger",
|
||||
keywords=[query_data.query_vrf],
|
||||
)
|
||||
|
||||
|
@@ -8,9 +8,17 @@ from pydantic import StrictStr
|
||||
from pydantic import constr
|
||||
|
||||
|
||||
class QueryError(BaseModel):
|
||||
"""Query response model."""
|
||||
|
||||
output: StrictStr
|
||||
level: constr(regex=r"(success|warning|error|danger)")
|
||||
keywords: List[StrictStr]
|
||||
|
||||
|
||||
class QueryResponse(BaseModel):
|
||||
"""Query response model."""
|
||||
|
||||
output: StrictStr
|
||||
alert: constr(regex=r"(warning|error|danger)")
|
||||
keywords: List[StrictStr]
|
||||
level: constr(regex=r"(success|warning|error|danger)")
|
||||
keywords: List[StrictStr] = []
|
||||
|
@@ -51,7 +51,7 @@ const Result = React.forwardRef(
|
||||
const selectionBg = { dark: theme.colors.white, light: theme.colors.black };
|
||||
const selectionColor = { dark: theme.colors.black, light: theme.colors.white };
|
||||
const [{ data, loading, error }, refetch] = useAxios({
|
||||
url: "/api/query",
|
||||
url: "/api/query/",
|
||||
method: "post",
|
||||
data: {
|
||||
query_location: queryLocation,
|
||||
@@ -73,6 +73,7 @@ const Result = React.forwardRef(
|
||||
(error && error.response?.data?.output) ||
|
||||
(error && error.message) ||
|
||||
config.messages.general;
|
||||
error && console.log("ERROR", errorMsg);
|
||||
return (
|
||||
<AccordionItem
|
||||
isDisabled={loading}
|
||||
@@ -127,7 +128,7 @@ const Result = React.forwardRef(
|
||||
rounded="lg"
|
||||
my={2}
|
||||
py={4}
|
||||
status={error.response?.data?.alert || "error"}
|
||||
status={error.response?.data?.level || "error"}
|
||||
>
|
||||
<FormattedError keywords={errorKw} message={errorMsg} />
|
||||
</Alert>
|
||||
|
@@ -36,7 +36,7 @@ export default React.forwardRef(({ title, loading, error }, ref) => {
|
||||
name="warning"
|
||||
color={
|
||||
error.response
|
||||
? theme.colors[error.response?.data?.alert][warningColor[colorMode]]
|
||||
? theme.colors[error.response?.data?.level][warningColor[colorMode]]
|
||||
: defaultWarningColor[colorMode]
|
||||
}
|
||||
mr={4}
|
||||
|
Reference in New Issue
Block a user