diff --git a/hyperglass/configuration/__init__.py b/hyperglass/configuration/__init__.py index 7c37e34..43b5304 100644 --- a/hyperglass/configuration/__init__.py +++ b/hyperglass/configuration/__init__.py @@ -169,7 +169,7 @@ from params. """ try: params.web.text.subtitle = params.web.text.subtitle.format( - **params.dict(exclude={"web", "features", "messages"}) + **params.dict(exclude={"web", "queries", "messages"}) ) if params.cache.timeout >= 60: _cache_timeout = math.ceil(params.cache.timeout / 60) @@ -340,7 +340,7 @@ def _build_queries(): """ queries = [] for query in SUPPORTED_QUERY_TYPES: - query_params = getattr(params.features, query) + query_params = getattr(params.queries, query) queries.append({"name": query, "display_name": query_params.display_name}) return queries @@ -365,7 +365,7 @@ def _build_vrf_help(): help_params = {**content_params, **cmd.params.dict()} if help_params["title"] is None: - command_params = getattr(params.features, command) + command_params = getattr(params.queries, command) help_params[ "title" ] = f"{vrf.display_name}: {command_params.display_name}" @@ -421,7 +421,7 @@ _frontend_fields = { "google_analytics": ..., "site_description": ..., "web": ..., - "features": { + "queries": { "bgp_route": {"enable", "display_name"}, "bgp_community": {"enable", "display_name"}, "bgp_aspath": {"enable", "display_name"}, diff --git a/hyperglass/configuration/models/features.py b/hyperglass/configuration/models/features.py deleted file mode 100644 index 6aa43be..0000000 --- a/hyperglass/configuration/models/features.py +++ /dev/null @@ -1,81 +0,0 @@ -"""Validate feature configuration variables.""" - -# Third Party Imports -from pydantic import StrictBool -from pydantic import StrictInt -from pydantic import StrictStr -from pydantic import constr - -# Project Imports -from hyperglass.configuration.models._utils import HyperglassModel - - -class Features(HyperglassModel): - """Validation model for params.features.""" - - class BgpRoute(HyperglassModel): - """Validation model for params.features.bgp_route.""" - - enable: StrictBool = True - display_name: StrictStr = "BGP Route" - - class BgpCommunity(HyperglassModel): - """Validation model for params.features.bgp_community.""" - - enable: StrictBool = True - display_name: StrictStr = "BGP Community" - - class Regex(HyperglassModel): - """Validation model for params.features.bgp_community.regex.""" - - decimal: StrictStr = r"^[0-9]{1,10}$" - extended_as: StrictStr = r"^([0-9]{0,5})\:([0-9]{1,5})$" - large: StrictStr = r"^([0-9]{1,10})\:([0-9]{1,10})\:[0-9]{1,10}$" - - regex: Regex = Regex() - - class BgpAsPath(HyperglassModel): - """Validation model for params.features.bgp_aspath.""" - - enable: StrictBool = True - display_name: StrictStr = "BGP AS Path" - - class Regex(HyperglassModel): - """Validation model for params.bgp_aspath.regex.""" - - mode: constr(regex="asplain|asdot") = "asplain" - asplain: StrictStr = r"^(\^|^\_)(\d+\_|\d+\$|\d+\(\_\.\+\_\))+$" - asdot: StrictStr = ( - r"^(\^|^\_)((\d+\.\d+)\_|(\d+\.\d+)\$|(\d+\.\d+)\(\_\.\+\_\))+$" - ) - - regex: Regex = Regex() - - class Ping(HyperglassModel): - """Validation model for params.features.ping.""" - - enable: StrictBool = True - display_name: StrictStr = "Ping" - - class Traceroute(HyperglassModel): - """Validation model for params.features.traceroute.""" - - enable: StrictBool = True - display_name: StrictStr = "Traceroute" - - class MaxPrefix(HyperglassModel): - """Validation model for params.features.max_prefix.""" - - enable: StrictBool = False - ipv4: StrictInt = 24 - ipv6: StrictInt = 64 - message: StrictStr = ( - "Prefix length must be smaller than /{m}. {i} is too specific." - ) - - bgp_route: BgpRoute = BgpRoute() - bgp_community: BgpCommunity = BgpCommunity() - bgp_aspath: BgpAsPath = BgpAsPath() - ping: Ping = Ping() - traceroute: Traceroute = Traceroute() - max_prefix: MaxPrefix = MaxPrefix() diff --git a/hyperglass/configuration/models/params.py b/hyperglass/configuration/models/params.py index e5f4c2f..c04d9e6 100644 --- a/hyperglass/configuration/models/params.py +++ b/hyperglass/configuration/models/params.py @@ -20,8 +20,8 @@ from pydantic import validator from hyperglass.configuration.models._utils import HyperglassModel from hyperglass.configuration.models.cache import Cache from hyperglass.configuration.models.docs import Docs -from hyperglass.configuration.models.features import Features from hyperglass.configuration.models.messages import Messages +from hyperglass.configuration.models.queries import Queries from hyperglass.configuration.models.web import Web @@ -61,8 +61,8 @@ class Params(HyperglassModel): # Sub Level Params cache: Cache = Cache() docs: Docs = Docs() - features: Features = Features() messages: Messages = Messages() + queries: Queries = Queries() web: Web = Web() @validator("listen_address", pre=True, always=True) diff --git a/hyperglass/configuration/models/queries.py b/hyperglass/configuration/models/queries.py new file mode 100644 index 0000000..9d8e012 --- /dev/null +++ b/hyperglass/configuration/models/queries.py @@ -0,0 +1,85 @@ +"""Validate query configuration parameters.""" + +# Third Party Imports +from pydantic import StrictBool +from pydantic import StrictInt +from pydantic import StrictStr +from pydantic import constr + +# Project Imports +from hyperglass.configuration.models._utils import HyperglassModel + + +class BgpCommunity(HyperglassModel): + """Validation model for bgp_community configuration.""" + + class Pattern(HyperglassModel): + """Validation model for bgp_community regex patterns.""" + + decimal: StrictStr = r"^[0-9]{1,10}$" + extended_as: StrictStr = r"^([0-9]{0,5})\:([0-9]{1,5})$" + large: StrictStr = r"^([0-9]{1,10})\:([0-9]{1,10})\:[0-9]{1,10}$" + + enable: StrictBool = True + display_name: StrictStr = "BGP Community" + pattern: Pattern = Pattern() + + +class BgpRoute(HyperglassModel): + """Validation model for bgp_route configuration.""" + + enable: StrictBool = True + display_name: StrictStr = "BGP Route" + + +class BgpAsPath(HyperglassModel): + """Validation model for bgp_aspath configuration.""" + + enable: StrictBool = True + display_name: StrictStr = "BGP AS Path" + + class Pattern(HyperglassModel): + """Validation model for bgp_aspath regex patterns.""" + + mode: constr(regex="asplain|asdot") = "asplain" + asplain: StrictStr = r"^(\^|^\_)(\d+\_|\d+\$|\d+\(\_\.\+\_\))+$" + asdot: StrictStr = ( + r"^(\^|^\_)((\d+\.\d+)\_|(\d+\.\d+)\$|(\d+\.\d+)\(\_\.\+\_\))+$" + ) + + pattern: Pattern = Pattern() + + +class Ping(HyperglassModel): + """Validation model for ping configuration.""" + + enable: StrictBool = True + display_name: StrictStr = "Ping" + + +class Traceroute(HyperglassModel): + """Validation model for traceroute configuration.""" + + enable: StrictBool = True + display_name: StrictStr = "Traceroute" + + +class Queries(HyperglassModel): + """Validation model for all query types.""" + + class MaxPrefix(HyperglassModel): + """Validation model for params.features.max_prefix.""" + + enable: StrictBool = False + ipv4: StrictInt = 24 + ipv6: StrictInt = 64 + message: StrictStr = ( + "Prefix length must be smaller than /{m}. {i} is too specific." + ) + + bgp_route: BgpRoute = BgpRoute() + bgp_community: BgpCommunity = BgpCommunity() + bgp_aspath: BgpAsPath = BgpAsPath() + ping: Ping = Ping() + traceroute: Traceroute = Traceroute() + max_prefix: MaxPrefix = MaxPrefix() diff --git a/hyperglass/execution/validate.py b/hyperglass/execution/validate.py index 466d173..6dbcbab 100644 --- a/hyperglass/execution/validate.py +++ b/hyperglass/execution/validate.py @@ -219,8 +219,8 @@ def ip_type_check(query_type, target, device): # If enable_max_prefix feature enabled, require that BGP Route # queries be smaller than configured size limit. - if query_type == "bgp_route" and params.features.max_prefix.enable: - max_length = getattr(params.features.max_prefix, prefix_attr["afi"]) + if query_type == "bgp_route" and params.queries.max_prefix.enable: + max_length = getattr(params.queries.max_prefix, prefix_attr["afi"]) if prefix_attr["length"] > max_length: log.debug("Failed max prefix length check") _exception = ValueError(params.messages.max_prefix) @@ -245,7 +245,7 @@ def ip_type_check(query_type, target, device): if query_type in ("ping", "traceroute") and IPType().is_cidr(target): log.debug("Failed CIDR format for ping/traceroute check") _exception = ValueError(params.messages.directed_cidr) - query_type_params = getattr(params.features, query_type) + query_type_params = getattr(params.queries, query_type) _exception.details = {"query_type": query_type_params.display_name} raise _exception return target diff --git a/hyperglass/models/validators.py b/hyperglass/models/validators.py index 53804de..a7f806c 100644 --- a/hyperglass/models/validators.py +++ b/hyperglass/models/validators.py @@ -18,7 +18,7 @@ def validate_ip(value, query_type): Returns: Union[IPv4Address, IPv6Address] -- Validated IP address object """ - query_type_params = getattr(params.features, query_type) + query_type_params = getattr(params.queries, query_type) try: # Attempt to use IP object factory to create an IP address object @@ -60,22 +60,22 @@ def validate_community(value, query_type): """Validate input communities against configured or default regex pattern.""" # RFC4360: Extended Communities (New Format) - if re.match(params.features.bgp_community.regex.extended_as, value): + if re.match(params.queries.bgp_community.regex.extended_as, value): pass # RFC4360: Extended Communities (32 Bit Format) - elif re.match(params.features.bgp_community.regex.decimal, value): + elif re.match(params.queries.bgp_community.regex.decimal, value): pass # RFC8092: Large Communities - elif re.match(params.features.bgp_community.regex.large, value): + elif re.match(params.queries.bgp_community.regex.large, value): pass else: raise InputInvalid( params.messages.invalid_input, target=value, - query_type=params.features.bgp_community.display_name, + query_type=params.queries.bgp_community.display_name, ) return value @@ -83,14 +83,14 @@ def validate_community(value, query_type): def validate_aspath(value, query_type): """Validate input AS_PATH against configured or default regext pattern.""" - mode = params.features.bgp_aspath.regex.mode - pattern = getattr(params.features.bgp_aspath.regex, mode) + mode = params.queries.bgp_aspath.regex.mode + pattern = getattr(params.queries.bgp_aspath.regex, mode) if not re.match(pattern, value): raise InputInvalid( params.messages.invalid_input, target=value, - query_type=params.features.bgp_aspath.display_name, + query_type=params.queries.bgp_aspath.display_name, ) return value diff --git a/ui/components/Results.js b/ui/components/Results.js index 62f4877..a885957 100644 --- a/ui/components/Results.js +++ b/ui/components/Results.js @@ -76,7 +76,7 @@ const Results = ({ queryLocation, queryType, queryVrf, queryTarget, setSubmittin transition={{ duration: 0.3, delay: 0.3 }} exit={{ opacity: 0, x: -100 }} label={config.web.text.query_type} - value={config.features[queryType].display_name} + value={config.queries[queryType].display_name} valueBg={theme.colors.cyan[500]} fontSize={["xs", "sm", "sm", "sm"]} />