mirror of
https://github.com/checktheroads/hyperglass
synced 2024-05-11 05:55:08 +00:00
remove requirement for default VRF to be named default, closes #29
This commit is contained in:
@@ -21,33 +21,24 @@ from .validators import (
|
||||
validate_community_input,
|
||||
validate_community_select,
|
||||
)
|
||||
from ..config.vrf import Vrf
|
||||
|
||||
|
||||
def get_vrf_object(vrf_name):
|
||||
"""Match VRF object from VRF name.
|
||||
def get_vrf_object(vrf_name: str) -> Vrf:
|
||||
"""Match VRF object from VRF name."""
|
||||
|
||||
Arguments:
|
||||
vrf_name {str} -- VRF name
|
||||
|
||||
Raises:
|
||||
InputInvalid: Raised if no VRF is matched.
|
||||
|
||||
Returns:
|
||||
{object} -- Valid VRF object
|
||||
"""
|
||||
matched = None
|
||||
for vrf_obj in devices.vrf_objects:
|
||||
if vrf_name is not None:
|
||||
if vrf_name == vrf_obj.name or vrf_name == vrf_obj.display_name:
|
||||
matched = vrf_obj
|
||||
break
|
||||
if vrf_name == vrf_obj._id or vrf_name == vrf_obj.display_name:
|
||||
return vrf_obj
|
||||
|
||||
elif vrf_name == "__hyperglass_default" and vrf_obj.default:
|
||||
return vrf_obj
|
||||
elif vrf_name is None:
|
||||
if vrf_obj.name == "default":
|
||||
matched = vrf_obj
|
||||
break
|
||||
if matched is None:
|
||||
raise InputInvalid(params.messages.vrf_not_found, vrf_name=vrf_name)
|
||||
return matched
|
||||
if vrf_obj.default:
|
||||
return vrf_obj
|
||||
|
||||
raise InputInvalid(params.messages.vrf_not_found, vrf_name=vrf_name)
|
||||
|
||||
|
||||
class Query(BaseModel):
|
||||
@@ -145,7 +136,7 @@ class Query(BaseModel):
|
||||
items = {
|
||||
"query_location": self.query_location,
|
||||
"query_type": self.query_type,
|
||||
"query_vrf": self.query_vrf.name,
|
||||
"query_vrf": self.query_vrf._id,
|
||||
"query_target": str(self.query_target),
|
||||
}
|
||||
return items
|
||||
@@ -156,17 +147,7 @@ class Query(BaseModel):
|
||||
|
||||
@validator("query_type")
|
||||
def validate_query_type(cls, value):
|
||||
"""Ensure query_type is enabled.
|
||||
|
||||
Arguments:
|
||||
value {str} -- Query Type
|
||||
|
||||
Raises:
|
||||
InputInvalid: Raised if query_type is disabled.
|
||||
|
||||
Returns:
|
||||
{str} -- Valid query_type
|
||||
"""
|
||||
"""Ensure query_type is enabled."""
|
||||
query = params.queries[value]
|
||||
if not query.enable:
|
||||
raise InputInvalid(
|
||||
@@ -178,17 +159,7 @@ class Query(BaseModel):
|
||||
|
||||
@validator("query_location")
|
||||
def validate_query_location(cls, value):
|
||||
"""Ensure query_location is defined.
|
||||
|
||||
Arguments:
|
||||
value {str} -- Unvalidated query_location
|
||||
|
||||
Raises:
|
||||
InputInvalid: Raised if query_location is not defined.
|
||||
|
||||
Returns:
|
||||
{str} -- Valid query_location
|
||||
"""
|
||||
"""Ensure query_location is defined."""
|
||||
if value not in devices._ids:
|
||||
raise InputInvalid(
|
||||
params.messages.invalid_field,
|
||||
@@ -200,17 +171,7 @@ class Query(BaseModel):
|
||||
|
||||
@validator("query_vrf")
|
||||
def validate_query_vrf(cls, value, values):
|
||||
"""Ensure query_vrf is defined.
|
||||
|
||||
Arguments:
|
||||
value {str} -- Unvalidated query_vrf
|
||||
|
||||
Raises:
|
||||
InputInvalid: Raised if query_vrf is not defined.
|
||||
|
||||
Returns:
|
||||
{str} -- Valid query_vrf
|
||||
"""
|
||||
"""Ensure query_vrf is defined."""
|
||||
vrf_object = get_vrf_object(value)
|
||||
device = devices[values["query_location"]]
|
||||
device_vrf = None
|
||||
|
@@ -237,7 +237,7 @@ class Device(HyperglassModel):
|
||||
"""
|
||||
vrfs = []
|
||||
for vrf in value:
|
||||
vrf_name = vrf.get("name")
|
||||
vrf_default = vrf.get("default", False)
|
||||
|
||||
for afi in ("ipv4", "ipv6"):
|
||||
vrf_afi = vrf.get(afi)
|
||||
@@ -259,9 +259,7 @@ class Device(HyperglassModel):
|
||||
# to make one by replacing non-alphanumeric characters
|
||||
# with whitespaces and using str.title() to make each
|
||||
# word look "pretty".
|
||||
if vrf_name != "default" and not isinstance(
|
||||
vrf.get("display_name"), StrictStr
|
||||
):
|
||||
if not vrf_default and not isinstance(vrf.get("display_name"), str):
|
||||
new_name = vrf["name"]
|
||||
new_name = re.sub(r"[^a-zA-Z0-9]", " ", new_name)
|
||||
new_name = re.split(" ", new_name)
|
||||
@@ -272,7 +270,7 @@ class Device(HyperglassModel):
|
||||
f"Generated '{vrf['display_name']}'"
|
||||
)
|
||||
|
||||
elif vrf_name == "default" and vrf.get("display_name") is None:
|
||||
elif vrf_default and vrf.get("display_name") is None:
|
||||
vrf["display_name"] = "Global"
|
||||
|
||||
# Validate the non-default VRF against the standard
|
||||
|
@@ -1,7 +1,8 @@
|
||||
"""Validate VRF configuration variables."""
|
||||
|
||||
# Standard Library
|
||||
from typing import List, Optional
|
||||
import re
|
||||
from typing import Dict, List, Optional
|
||||
from ipaddress import IPv4Address, IPv4Network, IPv6Address, IPv6Network
|
||||
|
||||
# Third Party
|
||||
@@ -10,18 +11,39 @@ from pydantic import (
|
||||
FilePath,
|
||||
StrictStr,
|
||||
StrictBool,
|
||||
PrivateAttr,
|
||||
conint,
|
||||
constr,
|
||||
validator,
|
||||
root_validator,
|
||||
)
|
||||
|
||||
# Project
|
||||
from hyperglass.log import log
|
||||
|
||||
# Local
|
||||
from ..main import HyperglassModel, HyperglassModelExtra
|
||||
|
||||
ACLAction = constr(regex=r"permit|deny")
|
||||
|
||||
|
||||
def find_vrf_id(values: Dict) -> str:
|
||||
"""Generate (private) VRF ID."""
|
||||
|
||||
def generate_id(name: str) -> str:
|
||||
scrubbed = re.sub(r"[^A-Za-z0-9\_\-\s]", "", name)
|
||||
return "_".join(scrubbed.split()).lower()
|
||||
|
||||
display_name = values.get("display_name")
|
||||
|
||||
if display_name is None:
|
||||
raise ValueError("display_name is required.")
|
||||
|
||||
vrf_id = generate_id(display_name)
|
||||
|
||||
return vrf_id
|
||||
|
||||
|
||||
class AccessList4(HyperglassModel):
|
||||
"""Validation model for IPv4 access-lists."""
|
||||
|
||||
@@ -195,23 +217,33 @@ class DeviceVrf6(HyperglassModelExtra):
|
||||
class Vrf(HyperglassModel):
|
||||
"""Validation model for per VRF/afi config in devices.yaml."""
|
||||
|
||||
_id: StrictStr = PrivateAttr()
|
||||
name: StrictStr
|
||||
display_name: StrictStr
|
||||
info: Info = Info()
|
||||
ipv4: Optional[DeviceVrf4]
|
||||
ipv6: Optional[DeviceVrf6]
|
||||
default: StrictBool = False
|
||||
|
||||
def __init__(self, **kwargs) -> None:
|
||||
"""Set the VRF ID."""
|
||||
_id = find_vrf_id(kwargs)
|
||||
super().__init__(**kwargs)
|
||||
self._id = _id
|
||||
|
||||
@root_validator
|
||||
def set_dynamic(cls, values):
|
||||
"""Set dynamic attributes before VRF initialization.
|
||||
def set_dynamic(cls, values: Dict) -> Dict:
|
||||
"""Set dynamic attributes before VRF initialization."""
|
||||
|
||||
Arguments:
|
||||
values {dict} -- Post-validation VRF attributes
|
||||
|
||||
Returns:
|
||||
{dict} -- VRF with new attributes set
|
||||
"""
|
||||
if values["name"] == "default":
|
||||
log.warning(
|
||||
"""You have set the VRF name to 'default'. This is no longer the way to
|
||||
designate a VRF as the default (or global routing table) VRF. Instead,
|
||||
add 'default: true' to the VRF definition.
|
||||
"""
|
||||
)
|
||||
|
||||
if values.get("default", False) is True:
|
||||
protocol4 = "ipv4_default"
|
||||
protocol6 = "ipv6_default"
|
||||
|
||||
@@ -227,7 +259,7 @@ class Vrf(HyperglassModel):
|
||||
values["ipv6"].protocol = protocol6
|
||||
values["ipv6"].version = 6
|
||||
|
||||
if values.get("name") == "default" and values.get("display_name") is None:
|
||||
if values.get("default", False) and values.get("display_name") is None:
|
||||
values["display_name"] = "Global"
|
||||
|
||||
return values
|
||||
@@ -245,7 +277,7 @@ class Vrf(HyperglassModel):
|
||||
{object} -- AFI object
|
||||
"""
|
||||
if i not in (4, 6):
|
||||
raise AttributeError(f"Must be 4 or 6, got '{i}")
|
||||
raise AttributeError(f"Must be 4 or 6, got '{i}'")
|
||||
|
||||
return getattr(self, f"ipv{i}")
|
||||
|
||||
|
Reference in New Issue
Block a user