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

add structured output support in configuration models

This commit is contained in:
checktheroads
2020-05-02 23:05:17 -07:00
parent 1867154ed2
commit 6858536d29
15 changed files with 420 additions and 390 deletions

View File

@@ -62,6 +62,7 @@ class QueryResponse(BaseModel):
runtime: StrictInt
keywords: List[StrictStr] = []
timestamp: StrictStr
_format: constr(regex=r"(application\/json|text\/plain)") = "text/plain"
class Config:
"""Pydantic model configuration."""
@@ -89,6 +90,12 @@ class QueryResponse(BaseModel):
"description": "UTC Time at which the backend application received the query.",
"example": "2020-04-18 14:45:37",
},
"format": {
"alias": "format",
"title": "Format",
"description": "Response [MIME Type](http://www.iana.org/assignments/media-types/media-types.xhtml). Supported values: `text/plain` and `application/json`.",
"example": "text/plain",
},
"keywords": {
"title": "Keywords",
"description": "Relevant keyword values contained in the `output` field, which can be used for formatting.",

View File

@@ -1,373 +0,0 @@
"""Validate command configuration variables."""
# Third Party
from pydantic import StrictStr
# Project
from hyperglass.models import HyperglassModel, HyperglassModelExtra
class Command(HyperglassModel):
"""Validation model for non-default commands."""
class IPv4(HyperglassModel):
"""Validation model for non-default dual afi commands."""
bgp_route: StrictStr
bgp_aspath: StrictStr
bgp_community: StrictStr
ping: StrictStr
traceroute: StrictStr
class IPv6(HyperglassModel):
"""Validation model for non-default ipv4 commands."""
bgp_route: StrictStr
bgp_aspath: StrictStr
bgp_community: StrictStr
ping: StrictStr
traceroute: StrictStr
class VPNIPv4(HyperglassModel):
"""Validation model for non-default ipv6 commands."""
bgp_route: StrictStr
bgp_aspath: StrictStr
bgp_community: StrictStr
ping: StrictStr
traceroute: StrictStr
class VPNIPv6(HyperglassModel):
"""Validation model for non-default ipv6 commands."""
bgp_route: StrictStr
bgp_aspath: StrictStr
bgp_community: StrictStr
ping: StrictStr
traceroute: StrictStr
ipv4_default: IPv4
ipv6_default: IPv6
ipv4_vpn: VPNIPv4
ipv6_vpn: VPNIPv6
class CiscoIOS(Command):
"""Validation model for default cisco_ios commands."""
class VPNIPv4(Command.VPNIPv4):
"""Default commands for dual afi commands."""
bgp_community: StrictStr = "show bgp vpnv4 unicast vrf {vrf} community {target}"
bgp_aspath: StrictStr = 'show bgp vpnv4 unicast vrf {vrf} quote-regexp "{target}"'
bgp_route: StrictStr = "show bgp vpnv4 unicast vrf {vrf} {target}"
ping: StrictStr = "ping vrf {vrf} {target} repeat 5 source {source}"
traceroute: StrictStr = (
"traceroute vrf {vrf} {target} timeout 1 probe 2 source {source}"
)
class VPNIPv6(Command.VPNIPv6):
"""Default commands for dual afi commands."""
bgp_community: StrictStr = "show bgp vpnv6 unicast vrf {vrf} community {target}"
bgp_aspath: StrictStr = 'show bgp vpnv6 unicast vrf {vrf} quote-regexp "{target}"'
bgp_route: StrictStr = "show bgp vpnv6 unicast vrf {vrf} {target}"
ping: StrictStr = "ping vrf {vrf} {target} repeat 5 source {source}"
traceroute: StrictStr = (
"traceroute vrf {vrf} {target} timeout 1 probe 2 source {source}"
)
class IPv4(Command.IPv4):
"""Default commands for ipv4 commands."""
bgp_community: StrictStr = "show bgp ipv4 unicast community {target}"
bgp_aspath: StrictStr = 'show bgp ipv4 unicast quote-regexp "{target}"'
bgp_route: StrictStr = "show bgp ipv4 unicast {target} | exclude pathid:|Epoch"
ping: StrictStr = "ping {target} repeat 5 source {source}"
traceroute: StrictStr = "traceroute {target} timeout 1 probe 2 source {source}"
class IPv6(Command.IPv6):
"""Default commands for ipv6 commands."""
bgp_community: StrictStr = "show bgp ipv6 unicast community {target}"
bgp_aspath: StrictStr = 'show bgp ipv6 unicast quote-regexp "{target}"'
bgp_route: StrictStr = "show bgp ipv6 unicast {target} | exclude pathid:|Epoch"
ping: StrictStr = ("ping ipv6 {target} repeat 5 source {source}")
traceroute: StrictStr = (
"traceroute ipv6 {target} timeout 1 probe 2 source {source}"
)
ipv4_default: IPv4 = IPv4()
ipv6_default: IPv6 = IPv6()
ipv4_vpn: VPNIPv4 = VPNIPv4()
ipv6_vpn: VPNIPv6 = VPNIPv6()
class CiscoXR(Command):
"""Validation model for default cisco_xr commands."""
class IPv4(Command.IPv4):
"""Validation model for non-default dual afi commands."""
bgp_route: StrictStr = "show bgp ipv4 unicast {target}"
bgp_aspath: StrictStr = "show bgp ipv4 unicast regexp {target}"
bgp_community: StrictStr = "show bgp ipv4 unicast community {target}"
ping: StrictStr = "ping ipv4 {target} count 5 source {source}"
traceroute: StrictStr = "traceroute ipv4 {target} timeout 1 probe 2 source {source}"
class IPv6(Command.IPv6):
"""Validation model for non-default ipv4 commands."""
bgp_route: StrictStr = "show bgp ipv6 unicast {target}"
bgp_aspath: StrictStr = "show bgp ipv6 unicast regexp {target}"
bgp_community: StrictStr = "show bgp ipv6 unicast community {target}"
ping: StrictStr = "ping ipv6 {target} count 5 source {source}"
traceroute: StrictStr = "traceroute ipv6 {target} timeout 1 probe 2 source {source}"
class VPNIPv4(Command.VPNIPv4):
"""Validation model for non-default ipv6 commands."""
bgp_route: StrictStr = "show bgp vpnv4 unicast vrf {vrf} {target}"
bgp_aspath: StrictStr = "show bgp vpnv4 unicast vrf {vrf} regexp {target}"
bgp_community: StrictStr = "show bgp vpnv4 unicast vrf {vrf} community {target}"
ping: StrictStr = "ping vrf {vrf} {target} count 5 source {source}"
traceroute: StrictStr = "traceroute vrf {vrf} {target} timeout 1 probe 2 source {source}"
class VPNIPv6(Command.VPNIPv6):
"""Validation model for non-default ipv6 commands."""
bgp_route: StrictStr = "show bgp vpnv6 unicast vrf {vrf} {target}"
bgp_aspath: StrictStr = "show bgp vpnv6 unicast vrf {vrf} regexp {target}"
bgp_community: StrictStr = "show bgp vpnv6 unicast vrf {vrf} community {target}"
ping: StrictStr = "ping vrf {vrf} {target} count 5 source {source}"
traceroute: StrictStr = "traceroute vrf {vrf} {target} timeout 1 probe 2 source {source}"
ipv4_default: IPv4 = IPv4()
ipv6_default: IPv6 = IPv6()
ipv4_vpn: VPNIPv4 = VPNIPv4()
ipv6_vpn: VPNIPv6 = VPNIPv6()
class Juniper(Command):
"""Validation model for default juniper commands."""
class IPv4(Command.IPv4):
"""Validation model for non-default dual afi commands."""
bgp_route: StrictStr = 'show route protocol bgp table inet.0 {target} detail | except Label | except Label | except "Next hop type" | except Task | except Address | except "Session Id" | except State | except "Next-hop reference" | except destinations | except "Announcement bits"'
bgp_aspath: StrictStr = 'show route protocol bgp table inet.0 aspath-regex "{target}"'
bgp_community: StrictStr = "show route protocol bgp table inet.0 community {target}"
ping: StrictStr = "ping inet {target} count 5 source {source}"
traceroute: StrictStr = "traceroute inet {target} wait 1 source {source}"
class IPv6(Command.IPv6):
"""Validation model for non-default ipv4 commands."""
bgp_route: StrictStr = 'show route protocol bgp table inet6.0 {target} detail | except Label | except Label | except "Next hop type" | except Task | except Address | except "Session Id" | except State | except "Next-hop reference" | except destinations | except "Announcement bits"'
bgp_aspath: StrictStr = 'show route protocol bgp table inet6.0 aspath-regex "{target}"'
bgp_community: StrictStr = "show route protocol bgp table inet6.0 community {target}"
ping: StrictStr = "ping inet6 {target} count 5 source {source}"
traceroute: StrictStr = "traceroute inet6 {target} wait 2 source {source}"
class VPNIPv4(Command.VPNIPv4):
"""Validation model for non-default ipv6 commands."""
bgp_route: StrictStr = 'show route protocol bgp table {vrf}.inet.0 {target} detail | except Label | except Label | except "Next hop type" | except Task | except Address | except "Session Id" | except State | except "Next-hop reference" | except destinations | except "Announcement bits"'
bgp_aspath: StrictStr = 'show route protocol bgp table {vrf}.inet.0 aspath-regex "{target}"'
bgp_community: StrictStr = "show route protocol bgp table {vrf}.inet.0 community {target}"
ping: StrictStr = "ping inet routing-instance {vrf} {target} count 5 source {source}"
traceroute: StrictStr = "traceroute inet routing-instance {vrf} {target} wait 1 source {source}"
class VPNIPv6(Command.VPNIPv6):
"""Validation model for non-default ipv6 commands."""
bgp_route: StrictStr = 'show route protocol bgp table {vrf}.inet6.0 {target} detail | except Label | except Label | except "Next hop type" | except Task | except Address | except "Session Id" | except State | except "Next-hop reference" | except destinations | except "Announcement bits"'
bgp_aspath: StrictStr = 'show route protocol bgp table {vrf}.inet6.0 aspath-regex "{target}"'
bgp_community: StrictStr = "show route protocol bgp table {vrf}.inet6.0 community {target}"
ping: StrictStr = "ping inet6 routing-instance {vrf} {target} count 5 source {source}"
traceroute: StrictStr = "traceroute inet6 routing-instance {vrf} {target} wait 2 source {source}"
ipv4_default: IPv4 = IPv4()
ipv6_default: IPv6 = IPv6()
ipv4_vpn: VPNIPv4 = VPNIPv4()
ipv6_vpn: VPNIPv6 = VPNIPv6()
class Huawei(Command):
"""Validation model for default huawei commands."""
class IPv4(Command.IPv4):
"""Default commands for ipv4 commands."""
bgp_community: StrictStr = "display bgp routing-table regular-expression {target}"
bgp_aspath: StrictStr = "display bgp routing-table regular-expression {target}"
bgp_route: StrictStr = "display bgp routing-table {target}"
ping: StrictStr = "ping -c 5 -a {source} {target}"
traceroute: StrictStr = "tracert -q 2 -f 1 -a {source} {target}"
class IPv6(Command.IPv6):
"""Default commands for ipv6 commands."""
bgp_community: StrictStr = "display bgp ipv6 routing-table community {target}"
bgp_aspath: StrictStr = "display bgp ipv6 routing-table regular-expression {target}"
bgp_route: StrictStr = "display bgp ipv6 routing-table {target}"
ping: StrictStr = "ping ipv6 -c 5 -a {source} {target}"
traceroute: StrictStr = "tracert ipv6 -q 2 -f 1 -a {source} {target}"
class VPNIPv4(Command.VPNIPv4):
"""Default commands for dual afi commands."""
bgp_community: StrictStr = "display bgp vpnv4 vpn-instance {vrf} routing-table regular-expression {target}"
bgp_aspath: StrictStr = "display bgp vpnv4 vpn-instance {vrf} routing-table regular-expression {target}"
bgp_route: StrictStr = "display bgp vpnv4 vpn-instance {vrf} routing-table {target}"
ping: StrictStr = "ping -vpn-instance {vrf} -c 5 -a {source} {target}"
traceroute: StrictStr = "tracert -q 2 -f 1 -vpn-instance {vrf} -a {source} {target}"
class VPNIPv6(Command.VPNIPv6):
"""Default commands for dual afi commands."""
bgp_community: StrictStr = "display bgp vpnv6 vpn-instance {vrf} routing-table regular-expression {target}"
bgp_aspath: StrictStr = "display bgp vpnv6 vpn-instance {vrf} routing-table regular-expression {target}"
bgp_route: StrictStr = "display bgp vpnv6 vpn-instance {vrf} routing-table {target}"
ping: StrictStr = "ping vpnv6 vpn-instance {vrf} -c 5 -a {source} {target}"
traceroute: StrictStr = "tracert -q 2 -f 1 vpn-instance {vrf} -a {source} {target}"
ipv4_default: IPv4 = IPv4()
ipv6_default: IPv6 = IPv6()
ipv4_vpn: VPNIPv4 = VPNIPv4()
ipv6_vpn: VPNIPv6 = VPNIPv6()
class Arista(Command):
"""Validation model for non-default commands."""
class IPv4(Command.IPv4):
"""Validation model for non-default dual afi commands."""
bgp_route: StrictStr = "show ip bgp {target}"
bgp_aspath: StrictStr = "show ip bgp regexp {target}"
bgp_community: StrictStr = "show ip bgp community {target}"
ping: StrictStr = "ping ip {target} source {source}"
traceroute: StrictStr = "traceroute ip {target} source {source}"
class IPv6(Command.IPv6):
"""Validation model for non-default ipv4 commands."""
bgp_route: StrictStr = "show ipv6 bgp {target}"
bgp_aspath: StrictStr = "show ipv6 bgp regexp {target}"
bgp_community: StrictStr = "show ipv6 bgp community {target}"
ping: StrictStr = "ping ipv6 {target} source {source}"
traceroute: StrictStr = "traceroute ipv6 {target} source {source}"
class VPNIPv4(Command.VPNIPv4):
"""Validation model for non-default ipv6 commands."""
bgp_route: StrictStr = "show ip bgp {target} vrf {vrf}"
bgp_aspath: StrictStr = "show ip bgp regexp {target} vrf {vrf}"
bgp_community: StrictStr = "show ip bgp community {target} vrf {vrf}"
ping: StrictStr = "ping vrf {vrf} ip {target} source {source}"
traceroute: StrictStr = "traceroute vrf {vrf} ip {target} source {source}"
class VPNIPv6(Command.VPNIPv6):
"""Validation model for non-default ipv6 commands."""
bgp_route: StrictStr = "show ipv6 bgp {target} vrf {vrf}"
bgp_aspath: StrictStr = "show ipv6 bgp regexp {target} vrf {vrf}"
bgp_community: StrictStr = "show ipv6 bgp community {target} vrf {vrf}"
ping: StrictStr = "ping vrf {vrf} ipv6 {target} source {source}"
traceroute: StrictStr = "traceroute vrf {vrf} ipv6 {target} source {source}"
ipv4_default: IPv4 = IPv4()
ipv6_default: IPv6 = IPv6()
ipv4_vpn: VPNIPv4 = VPNIPv4()
ipv6_vpn: VPNIPv6 = VPNIPv6()
class CiscoNXOS(Command):
"""Validation model for non-default commands."""
class IPv4(Command.IPv4):
"""Validation model for non-default dual afi commands."""
bgp_route: StrictStr = "show bgp ipv4 unicast {target}"
bgp_aspath: StrictStr = 'show bgp ipv4 unicast regexp "{target}"'
bgp_community: StrictStr = "show bgp ipv4 unicast community {target}"
ping: StrictStr = "ping {target} source {source}"
traceroute: StrictStr = "traceroute {target} source {source}"
class IPv6(Command.IPv6):
"""Validation model for non-default ipv4 commands."""
bgp_route: StrictStr = "show bgp ipv6 unicast {target}"
bgp_aspath: StrictStr = 'show bgp ipv6 unicast regexp "{target}"'
bgp_community: StrictStr = "show bgp ipv6 unicast community {target}"
ping: StrictStr = "ping6 {target} source {source}"
traceroute: StrictStr = "traceroute6 {target} source {source}"
class VPNIPv4(Command.VPNIPv4):
"""Validation model for non-default ipv6 commands."""
bgp_route: StrictStr = "show bgp ipv4 unicast {target} vrf {vrf}"
bgp_aspath: StrictStr = 'show bgp ipv4 unicast regexp "{target}" vrf {vrf}'
bgp_community: StrictStr = "show bgp ipv4 unicast community {target} vrf {vrf}"
ping: StrictStr = "ping {target} source {source} vrf {vrf}"
traceroute: StrictStr = "traceroute {target} source {source} vrf {vrf}"
class VPNIPv6(Command.VPNIPv6):
"""Validation model for non-default ipv6 commands."""
bgp_route: StrictStr = "show bgp ipv6 unicast {target} vrf {vrf}"
bgp_aspath: StrictStr = 'show bgp ipv6 unicast regexp "{target}" vrf {vrf}'
bgp_community: StrictStr = "show bgp ipv6 unicast community {target} vrf {vrf}"
ping: StrictStr = "ping6 {target} source {source} vrf {vrf}"
traceroute: StrictStr = "traceroute6 {target} source {source} vrf {vrf}"
ipv4_default: IPv4 = IPv4()
ipv6_default: IPv6 = IPv6()
ipv4_vpn: VPNIPv4 = VPNIPv4()
ipv6_vpn: VPNIPv6 = VPNIPv6()
_NOS_MAP = {
"arista": Arista,
"huawei": Huawei,
"juniper": Juniper,
"cisco_ios": CiscoIOS,
"cisco_nxos": CiscoNXOS,
"cisco_xr": CiscoXR,
}
class Commands(HyperglassModelExtra):
"""Base class for command definitions."""
arista: Command = Arista()
cisco_ios: Command = CiscoIOS()
cisco_nxos: Command = CiscoNXOS()
cisco_xr: Command = CiscoXR()
huawei: Command = Huawei()
juniper: Command = Juniper()
@classmethod
def import_params(cls, input_params):
"""Import loaded YAML, initialize per-command definitions.
Dynamically set attributes for the command class.
Arguments:
input_params {dict} -- Unvalidated command definitions
Returns:
{object} -- Validated commands object
"""
obj = Commands()
for nos, cmds in input_params.items():
nos_cmd_set = _NOS_MAP.get(nos, Command)
nos_cmds = nos_cmd_set(**cmds)
setattr(obj, nos, nos_cmds)
return obj
class Config:
"""Override pydantic config."""
validate_all = False

View File

@@ -0,0 +1,55 @@
"""Validate command configuration variables."""
# Project
from hyperglass.models import HyperglassModelExtra
from hyperglass.configuration.models.commands.arista import AristaCommands
from hyperglass.configuration.models.commands.common import CommandGroup
from hyperglass.configuration.models.commands.huawei import HuaweiCommands
from hyperglass.configuration.models.commands.juniper import JuniperCommands
from hyperglass.configuration.models.commands.cisco_xr import CiscoXRCommands
from hyperglass.configuration.models.commands.cisco_ios import CiscoIOSCommands
from hyperglass.configuration.models.commands.cisco_nxos import CiscoNXOSCommands
_NOS_MAP = {
"juniper": JuniperCommands,
"cisco_ios": CiscoIOSCommands,
"cisco_xr": CiscoXRCommands,
"cisco_nxos": CiscoNXOSCommands,
"arista": AristaCommands,
"huawei": HuaweiCommands,
}
class Commands(HyperglassModelExtra):
"""Base class for command definitions."""
juniper: CommandGroup = JuniperCommands()
arista: CommandGroup = AristaCommands()
cisco_ios: CommandGroup = CiscoIOSCommands()
cisco_xr: CommandGroup = CiscoXRCommands()
cisco_nxos: CommandGroup = CiscoNXOSCommands()
huawei: CommandGroup = HuaweiCommands()
@classmethod
def import_params(cls, input_params):
"""Import loaded YAML, initialize per-command definitions.
Dynamically set attributes for the command class.
Arguments:
input_params {dict} -- Unvalidated command definitions
Returns:
{object} -- Validated commands object
"""
obj = Commands()
for nos, cmds in input_params.items():
nos_cmd_set = _NOS_MAP.get(nos, CommandGroup)
nos_cmds = nos_cmd_set(**cmds)
setattr(obj, nos, nos_cmds)
return obj
class Config:
"""Override pydantic config."""
validate_all = False

View File

@@ -0,0 +1,42 @@
"""Arista Command Model."""
# Project
from hyperglass.configuration.models.commands.common import CommandSet, CommandGroup
_ipv4_default = {
"bgp_route": "show ip bgp {target}",
"bgp_aspath": "show ip bgp regexp {target}",
"bgp_community": "show ip bgp community {target}",
"ping": "ping ip {target} source {source}",
"traceroute": "traceroute ip {target} source {source}",
}
_ipv6_default = {
"bgp_route": "show ipv6 bgp {target}",
"bgp_aspath": "show ipv6 bgp regexp {target}",
"bgp_community": "show ipv6 bgp community {target}",
"ping": "ping ipv6 {target} source {source}",
"traceroute": "traceroute ipv6 {target} source {source}",
}
_ipv4_vpn = {
"bgp_route": "show ip bgp {target} vrf {vrf}",
"bgp_aspath": "show ip bgp regexp {target} vrf {vrf}",
"bgp_community": "show ip bgp community {target} vrf {vrf}",
"ping": "ping vrf {vrf} ip {target} source {source}",
"traceroute": "traceroute vrf {vrf} ip {target} source {source}",
}
_ipv6_vpn = {
"bgp_route": "show ipv6 bgp {target} vrf {vrf}",
"bgp_aspath": "show ipv6 bgp regexp {target} vrf {vrf}",
"bgp_community": "show ipv6 bgp community {target} vrf {vrf}",
"ping": "ping vrf {vrf} ipv6 {target} source {source}",
"traceroute": "traceroute vrf {vrf} ipv6 {target} source {source}",
}
class AristaCommands(CommandGroup):
"""Validation model for default arista commands."""
ipv4_default: CommandSet = CommandSet(**_ipv4_default)
ipv6_default: CommandSet = CommandSet(**_ipv6_default)
ipv4_vpn: CommandSet = CommandSet(**_ipv4_vpn)
ipv6_vpn: CommandSet = CommandSet(**_ipv6_vpn)

View File

@@ -0,0 +1,42 @@
"""Cisco IOS Command Model."""
# Project
from hyperglass.configuration.models.commands.common import CommandSet, CommandGroup
_ipv4_default = {
"bgp_route": "show bgp ipv4 unicast {target} | exclude pathid:|Epoch",
"bgp_aspath": 'show bgp ipv4 unicast quote-regexp "{target}"',
"bgp_community": "show bgp ipv4 unicast community {target}",
"ping": "ping {target} repeat 5 source {source}",
"traceroute": "traceroute {target} timeout 1 probe 2 source {source}",
}
_ipv6_default = {
"bgp_route": "show bgp ipv6 unicast {target} | exclude pathid:|Epoch",
"bgp_aspath": 'show bgp ipv6 unicast quote-regexp "{target}"',
"bgp_community": "show bgp ipv6 unicast community {target}",
"ping": "ping ipv6 {target} repeat 5 source {source}",
"traceroute": "traceroute ipv6 {target} timeout 1 probe 2 source {source}",
}
_ipv4_vpn = {
"bgp_route": "show bgp vpnv4 unicast vrf {vrf} {target}",
"bgp_aspath": 'show bgp vpnv4 unicast vrf {vrf} quote-regexp "{target}"',
"bgp_community": "show bgp vpnv4 unicast vrf {vrf} community {target}",
"ping": "ping vrf {vrf} {target} repeat 5 source {source}",
"traceroute": "traceroute vrf {vrf} {target} timeout 1 probe 2 source {source}",
}
_ipv6_vpn = {
"bgp_route": "show bgp vpnv6 unicast vrf {vrf} {target}",
"bgp_aspath": 'show bgp vpnv6 unicast vrf {vrf} quote-regexp "{target}"',
"bgp_community": "show bgp vpnv6 unicast vrf {vrf} community {target}",
"ping": "ping vrf {vrf} {target} repeat 5 source {source}",
"traceroute": "traceroute vrf {vrf} {target} timeout 1 probe 2 source {source}",
}
class CiscoIOSCommands(CommandGroup):
"""Validation model for default cisco_ios commands."""
ipv4_default: CommandSet = CommandSet(**_ipv4_default)
ipv6_default: CommandSet = CommandSet(**_ipv6_default)
ipv4_vpn: CommandSet = CommandSet(**_ipv4_vpn)
ipv6_vpn: CommandSet = CommandSet(**_ipv6_vpn)

View File

@@ -0,0 +1,42 @@
"""Cisco NX-OS Command Model."""
# Project
from hyperglass.configuration.models.commands.common import CommandSet, CommandGroup
_ipv4_default = {
"bgp_route": "show bgp ipv4 unicast {target}",
"bgp_aspath": 'show bgp ipv4 unicast regexp "{target}"',
"bgp_community": "show bgp ipv4 unicast community {target}",
"ping": "ping {target} source {source}",
"traceroute": "traceroute {target} source {source}",
}
_ipv6_default = {
"bgp_route": "show bgp ipv6 unicast {target}",
"bgp_aspath": 'show bgp ipv6 unicast regexp "{target}"',
"bgp_community": "show bgp ipv6 unicast community {target}",
"ping": "ping6 {target} source {source}",
"traceroute": "traceroute6 {target} source {source}",
}
_ipv4_vpn = {
"bgp_route": "show bgp ipv4 unicast {target} vrf {vrf}",
"bgp_aspath": 'show bgp ipv4 unicast regexp "{target}" vrf {vrf}',
"bgp_community": "show bgp ipv4 unicast community {target} vrf {vrf}",
"ping": "ping {target} source {source} vrf {vrf}",
"traceroute": "traceroute {target} source {source} vrf {vrf}",
}
_ipv6_vpn = {
"bgp_route": "show bgp ipv6 unicast {target} vrf {vrf}",
"bgp_aspath": 'show bgp ipv6 unicast regexp "{target}" vrf {vrf}',
"bgp_community": "show bgp ipv6 unicast community {target} vrf {vrf}",
"ping": "ping6 {target} source {source} vrf {vrf}",
"traceroute": "traceroute6 {target} source {source} vrf {vrf}",
}
class CiscoNXOSCommands(CommandGroup):
"""Validation model for default cisco_nxos commands."""
ipv4_default: CommandSet = CommandSet(**_ipv4_default)
ipv6_default: CommandSet = CommandSet(**_ipv6_default)
ipv4_vpn: CommandSet = CommandSet(**_ipv4_vpn)
ipv6_vpn: CommandSet = CommandSet(**_ipv6_vpn)

View File

@@ -0,0 +1,42 @@
"""Cisco IOS XR Command Model."""
# Project
from hyperglass.configuration.models.commands.common import CommandSet, CommandGroup
_ipv4_default = {
"bgp_route": "show bgp ipv4 unicast {target}",
"bgp_aspath": "show bgp ipv4 unicast regexp {target}",
"bgp_community": "show bgp ipv4 unicast community {target}",
"ping": "ping ipv4 {target} count 5 source {source}",
"traceroute": "traceroute ipv4 {target} timeout 1 probe 2 source {source}",
}
_ipv6_default = {
"bgp_route": "show bgp ipv6 unicast {target}",
"bgp_aspath": "show bgp ipv6 unicast regexp {target}",
"bgp_community": "show bgp ipv6 unicast community {target}",
"ping": "ping ipv6 {target} count 5 source {source}",
"traceroute": "traceroute ipv6 {target} timeout 1 probe 2 source {source}",
}
_ipv4_vpn = {
"bgp_route": "show bgp vpnv4 unicast vrf {vrf} {target}",
"bgp_aspath": "show bgp vpnv4 unicast vrf {vrf} regexp {target}",
"bgp_community": "show bgp vpnv4 unicast vrf {vrf} community {target}",
"ping": "ping vrf {vrf} {target} count 5 source {source}",
"traceroute": "traceroute vrf {vrf} {target} timeout 1 probe 2 source {source}",
}
_ipv6_vpn = {
"bgp_route": "show bgp vpnv6 unicast vrf {vrf} {target}",
"bgp_aspath": "show bgp vpnv6 unicast vrf {vrf} regexp {target}",
"bgp_community": "show bgp vpnv6 unicast vrf {vrf} community {target}",
"ping": "ping vrf {vrf} {target} count 5 source {source}",
"traceroute": "traceroute vrf {vrf} {target} timeout 1 probe 2 source {source}",
}
class CiscoXRCommands(CommandGroup):
"""Validation model for default cisco_xr commands."""
ipv4_default: CommandSet = CommandSet(**_ipv4_default)
ipv6_default: CommandSet = CommandSet(**_ipv6_default)
ipv4_vpn: CommandSet = CommandSet(**_ipv4_vpn)
ipv6_vpn: CommandSet = CommandSet(**_ipv6_vpn)

View File

@@ -0,0 +1,32 @@
"""Models common to entire commands module."""
from typing import Optional
# Third Party
from pydantic import StrictStr
# Project
from hyperglass.models import HyperglassModel
class CommandSet(HyperglassModel):
"""Command set, defined per-AFI."""
bgp_route: StrictStr
bgp_aspath: StrictStr
bgp_community: StrictStr
ping: StrictStr
traceroute: StrictStr
class CommandGroup(HyperglassModel):
"""Validation model for all commands."""
ipv4_default: CommandSet
ipv6_default: CommandSet
ipv4_vpn: CommandSet
ipv6_vpn: CommandSet
structured: Optional["CommandGroup"]
CommandGroup.update_forward_refs()

View File

@@ -0,0 +1,42 @@
"""Huawei Command Model."""
# Project
from hyperglass.configuration.models.commands.common import CommandSet, CommandGroup
_ipv4_default = {
"bgp_route": "display bgp routing-table {target}",
"bgp_aspath": "display bgp routing-table regular-expression {target}",
"bgp_community": "display bgp routing-table regular-expression {target}",
"ping": "ping -c 5 -a {source} {target}",
"traceroute": "tracert -q 2 -f 1 -a {source} {target}",
}
_ipv6_default = {
"bgp_route": "display bgp ipv6 routing-table {target}",
"bgp_aspath": "display bgp ipv6 routing-table regular-expression {target}",
"bgp_community": "display bgp ipv6 routing-table community {target}",
"ping": "ping ipv6 -c 5 -a {source} {target}",
"traceroute": "tracert ipv6 -q 2 -f 1 -a {source} {target}",
}
_ipv4_vpn = {
"bgp_route": "display bgp vpnv4 vpn-instance {vrf} routing-table {target}",
"bgp_aspath": "display bgp vpnv4 vpn-instance {vrf} routing-table regular-expression {target}",
"bgp_community": "display bgp vpnv4 vpn-instance {vrf} routing-table regular-expression {target}",
"ping": "ping -vpn-instance {vrf} -c 5 -a {source} {target}",
"traceroute": "tracert -q 2 -f 1 -vpn-instance {vrf} -a {source} {target}",
}
_ipv6_vpn = {
"bgp_route": "display bgp vpnv6 vpn-instance {vrf} routing-table {target}",
"bgp_aspath": "display bgp vpnv6 vpn-instance {vrf} routing-table regular-expression {target}",
"bgp_community": "display bgp vpnv6 vpn-instance {vrf} routing-table regular-expression {target}",
"ping": "ping vpnv6 vpn-instance {vrf} -c 5 -a {source} {target}",
"traceroute": "tracert -q 2 -f 1 vpn-instance {vrf} -a {source} {target}",
}
class HuaweiCommands(CommandGroup):
"""Validation model for default huawei commands."""
ipv4_default: CommandSet = CommandSet(**_ipv4_default)
ipv6_default: CommandSet = CommandSet(**_ipv6_default)
ipv4_vpn: CommandSet = CommandSet(**_ipv4_vpn)
ipv6_vpn: CommandSet = CommandSet(**_ipv6_vpn)

View File

@@ -0,0 +1,74 @@
"""Juniper Command Model."""
# Project
from hyperglass.configuration.models.commands.common import CommandSet, CommandGroup
_ipv4_default = {
"bgp_route": 'show route protocol bgp table inet.0 {target} detail | except Label | except Label | except "Next hop type" | except Task | except Address | except "Session Id" | except State | except "Next-hop reference" | except destinations | except "Announcement bits"',
"bgp_aspath": 'show route protocol bgp table inet.0 aspath-regex "{target}"',
"bgp_community": "show route protocol bgp table inet.0 community {target}",
"ping": "ping inet {target} count 5 source {source}",
"traceroute": "traceroute inet {target} wait 1 source {source}",
}
_ipv6_default = {
"bgp_route": 'show route protocol bgp table inet6.0 {target} detail | except Label | except Label | except "Next hop type" | except Task | except Address | except "Session Id" | except State | except "Next-hop reference" | except destinations | except "Announcement bits"',
"bgp_aspath": 'show route protocol bgp table inet6.0 aspath-regex "{target}"',
"bgp_community": "show route protocol bgp table inet6.0 community {target}",
"ping": "ping inet6 {target} count 5 source {source}",
"traceroute": "traceroute inet6 {target} wait 2 source {source}",
}
_ipv4_vpn = {
"bgp_route": 'show route protocol bgp table {vrf}.inet.0 {target} detail | except Label | except Label | except "Next hop type" | except Task | except Address | except "Session Id" | except State | except "Next-hop reference" | except destinations | except "Announcement bits"',
"bgp_aspath": 'show route protocol bgp table {vrf}.inet.0 aspath-regex "{target}"',
"bgp_community": "show route protocol bgp table {vrf}.inet.0 community {target}",
"ping": "ping inet routing-instance {vrf} {target} count 5 source {source}",
"traceroute": "traceroute inet routing-instance {vrf} {target} wait 1 source {source}",
}
_ipv6_vpn = {
"bgp_route": 'show route protocol bgp table {vrf}.inet6.0 {target} detail | except Label | except Label | except "Next hop type" | except Task | except Address | except "Session Id" | except State | except "Next-hop reference" | except destinations | except "Announcement bits"',
"bgp_aspath": 'show route protocol bgp table {vrf}.inet6.0 aspath-regex "{target}"',
"bgp_community": "show route protocol bgp table {vrf}.inet6.0 community {target}",
"ping": "ping inet6 routing-instance {vrf} {target} count 5 source {source}",
"traceroute": "traceroute inet6 routing-instance {vrf} {target} wait 2 source {source}",
}
_structured = CommandGroup(
ipv4_default=CommandSet(
bgp_route="show route protocol bgp table inet.0 {target} detail | display json",
bgp_aspath='show route protocol bgp table inet.0 aspath-regex "{target}" | display json',
bgp_community="show route protocol bgp table inet.0 community {target} | display json",
ping="ping inet {target} count 5 source {source}",
traceroute="traceroute inet {target} wait 1 source {source}",
),
ipv6_default=CommandSet(
bgp_route="show route protocol bgp table inet6.0 {target} detail | display json",
bgp_aspath='show route protocol bgp table inet6.0 aspath-regex "{target}" | display json',
bgp_community="show route protocol bgp table inet6.0 community {target} | display json",
ping="ping inet6 {target} count 5 source {source}",
traceroute="traceroute inet6 {target} wait 2 source {source}",
),
ipv4_vpn=CommandSet(
bgp_route="show route protocol bgp table {vrf}.inet.0 {target} detail | display json",
bgp_aspath='show route protocol bgp table {vrf}.inet.0 aspath-regex "{target}" | display json',
bgp_community="show route protocol bgp table {vrf}.inet.0 community {target} | display json",
ping="ping inet routing-instance {vrf} {target} count 5 source {source}",
traceroute="traceroute inet routing-instance {vrf} {target} wait 1 source {source}",
),
ipv6_vpn=CommandSet(
bgp_route="show route protocol bgp table {vrf}.inet6.0 {target} detail | display json",
bgp_aspath='show route protocol bgp table {vrf}.inet6.0 aspath-regex "{target}" | display json',
bgp_community="show route protocol bgp table {vrf}.inet6.0 community {target} | display json",
ping="ping inet6 routing-instance {vrf} {target} count 5 source {source}",
traceroute="traceroute inet6 routing-instance {vrf} {target} wait 1 source {source}",
),
)
class JuniperCommands(CommandGroup):
"""Validation model for default juniper commands."""
ipv4_default: CommandSet = CommandSet(**_ipv4_default)
ipv6_default: CommandSet = CommandSet(**_ipv6_default)
ipv4_vpn: CommandSet = CommandSet(**_ipv4_vpn)
ipv6_vpn: CommandSet = CommandSet(**_ipv6_vpn)
structured: CommandGroup = _structured

View File

@@ -7,20 +7,25 @@ from typing import List, Optional
from pathlib import Path
# Third Party
from pydantic import StrictInt, StrictStr, validator
from pydantic import StrictInt, StrictStr, StrictBool, validator
# Project
from hyperglass.log import log
from hyperglass.util import clean_name
from hyperglass.models import HyperglassModel, HyperglassModelExtra
from hyperglass.constants import SCRAPE_HELPERS, TRANSPORT_REST, TRANSPORT_SCRAPE
from hyperglass.constants import (
SCRAPE_HELPERS,
TRANSPORT_REST,
TRANSPORT_SCRAPE,
SUPPORTED_STRUCTURED_OUTPUT,
)
from hyperglass.exceptions import ConfigError, UnsupportedDevice
from hyperglass.configuration.models.ssl import Ssl
from hyperglass.configuration.models.vrfs import Vrf, Info
from hyperglass.configuration.models.proxies import Proxy
from hyperglass.configuration.models.commands import Command
from hyperglass.configuration.models.networks import Network
from hyperglass.configuration.models.credentials import Credential
from hyperglass.configuration.models.commands.common import CommandGroup
_default_vrf = {
"name": "default",
@@ -51,10 +56,36 @@ class Router(HyperglassModel):
port: StrictInt
ssl: Optional[Ssl]
nos: StrictStr
commands: Optional[Command]
commands: Optional[CommandGroup]
vrfs: List[Vrf] = [_default_vrf]
display_vrfs: List[StrictStr] = []
vrf_names: List[StrictStr] = []
structured_output: Optional[StrictBool]
@validator("structured_output", pre=True, always=True)
def validate_structured_output(cls, value, values):
"""Validate structured output is supported on the device & set a default.
Raises:
ConfigError: Raised if true on a device that doesn't support structured output.
Returns:
{bool} -- True if hyperglass should return structured output for this device.
"""
if value is True and values["nos"] not in SUPPORTED_STRUCTURED_OUTPUT:
raise ConfigError(
"The 'structured_output' field is set to 'true' on device '{d}' with "
+ "NOS '{n}', which does not support structured output",
d=values["name"],
n=values["nos"],
)
elif value is None and values["nos"] in SUPPORTED_STRUCTURED_OUTPUT:
value = True
else:
value = False
return value
@validator("nos")
def supported_nos(cls, value):

View File

@@ -13,12 +13,12 @@ METADATA = (__name__, __version__, __author__, __copyright__, __license__)
MIN_PYTHON_VERSION = (3, 6)
protocol_map = {80: "http", 8080: "http", 443: "https", 8443: "https"}
TARGET_FORMAT_SPACE = ("huawei", "huawei_vrpv8")
TARGET_JUNIPER_ASPATH = ("juniper", "juniper_junos")
SUPPORTED_STRUCTURED_OUTPUT = ("juniper",)
STATUS_CODE_MAP = {"warning": 400, "error": 400, "danger": 500}
DNS_OVER_HTTPS = {

View File

@@ -1,6 +1,6 @@
import * as React from "react";
import { Box } from "@chakra-ui/core";
import css from "@styled-system/css";
/** @jsx jsx */
import { jsx } from "@emotion/core";
import { Box, css } from "@chakra-ui/core";
const TableBody = ({ children, ...props }) => {
return (
@@ -9,7 +9,7 @@ const TableBody = ({ children, ...props }) => {
overflowY="scroll"
css={css({
"&::-webkit-scrollbar": { display: "none" },
"&": { "-ms-overflow-style": "none" }
"&": { msOverflowStyle: "none" }
})}
overflowX="hidden"
{...props}

View File

@@ -77,12 +77,6 @@ const Table = ({
usePagination
);
// tableColumns.map(col => {
// if (col.hidden === true) {
// setHiddenColumns(old => [...old, col.id]);
// }
// });
return (
<CardBody>
{!!tableHeading && <CardHeader>{tableHeading}</CardHeader>}

View File

@@ -324,7 +324,7 @@ const Structured = () => {
return (
<Layout>
<Flex my={8} w="80%">
<Flex my={8} maxW={["100%", "100%", "75%", "50%"]} w="100%">
<Table
columns={columns}
data={data.routes}