1
0
mirror of https://github.com/checktheroads/hyperglass synced 2024-05-11 05:55:08 +00:00

92 lines
2.7 KiB
Python

"""Parse Arista JSON Response to Structured Data."""
# Standard Library
import json
import typing as t
# Third Party
from pydantic import PrivateAttr, ValidationError
# Project
from hyperglass.log import log
from hyperglass.exceptions.private import ParsingError
from hyperglass.models.parsing.arista_eos import AristaBGPTable
# Local
from .._output import OutputPlugin
if t.TYPE_CHECKING:
# Project
from hyperglass.models.data import OutputDataModel
from hyperglass.models.api.query import Query
# Local
from .._output import OutputType
def parse_arista(output: t.Sequence[str]) -> "OutputDataModel":
"""Parse a Arista BGP JSON response."""
result = None
for response in output:
try:
parsed: t.Dict = json.loads(response)
log.debug("Pre-parsed data:\n{}", parsed)
vrf = list(parsed["vrfs"].keys())[0]
routes = parsed["vrfs"][vrf]
validated = AristaBGPTable(**routes)
bgp_table = validated.bgp_table()
if result is None:
result = bgp_table
else:
result += bgp_table
except json.JSONDecodeError as err:
log.critical("Error decoding JSON: {}", str(err))
raise ParsingError("Error parsing response data")
except KeyError as err:
log.critical("'{}' was not found in the response", str(err))
raise ParsingError("Error parsing response data")
except IndexError as err:
log.critical(str(err))
raise ParsingError("Error parsing response data")
except ValidationError as err:
log.critical(str(err))
raise ParsingError(err.errors())
return result
class BGPRoutePluginArista(OutputPlugin):
"""Coerce a Arista route table in JSON format to a standard BGP Table structure."""
__hyperglass_builtin__: bool = PrivateAttr(True)
platforms: t.Sequence[str] = ("arista_eos",)
directives: t.Sequence[str] = (
"__hyperglass_arista_eos_bgp_route_table__",
"__hyperglass_arista_eos_bgp_aspath_table__",
"__hyperglass_arista_eos_bgp_community_table__",
)
def process(self, *, output: "OutputType", query: "Query") -> "OutputType":
"""Parse Arista response if data is a string (and is therefore unparsed)."""
should_process = all(
(
isinstance(output, (list, tuple)),
query.device.platform in self.platforms,
query.device.structured_output is True,
query.device.has_directives(*self.directives),
)
)
if should_process:
return parse_arista(output)
return output