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

migrate config models to models module

This commit is contained in:
checktheroads
2020-10-11 13:14:07 -07:00
parent f0ca060744
commit 6841cb65f5
21 changed files with 574 additions and 548 deletions

View File

@@ -1,506 +1,14 @@
"""Import configuration files and returns default values if undefined.""" """hyperglass Configuration."""
# Standard Library # Local
import os from .main import (
import copy URL_DEV,
import json URL_PROD,
from typing import Dict, List, Union, Callable CONFIG_PATH,
from pathlib import Path STATIC_PATH,
REDIS_CONFIG,
# Third Party params,
import yaml devices,
from pydantic import ValidationError commands,
frontend_params,
# Project
from hyperglass.log import (
log,
set_log_level,
enable_file_logging,
enable_syslog_logging,
) )
from hyperglass.util import check_path, set_app_path, set_cache_env, current_log_level
from hyperglass.models import HyperglassModel
from hyperglass.constants import (
TRANSPORT_REST,
SUPPORTED_QUERY_TYPES,
PARSED_RESPONSE_FIELDS,
SUPPORTED_STRUCTURED_OUTPUT,
__version__,
)
from hyperglass.exceptions import ConfigError, ConfigInvalid, ConfigMissing
from hyperglass.models.commands import Commands
from hyperglass.configuration.defaults import (
CREDIT,
DEFAULT_HELP,
DEFAULT_TERMS,
DEFAULT_DETAILS,
)
from hyperglass.configuration.markdown import get_markdown
from hyperglass.configuration.models.params import Params
from hyperglass.configuration.models.devices import Devices
set_app_path(required=True)
CONFIG_PATH = Path(os.environ["hyperglass_directory"])
log.info("Configuration directory: {d}", d=str(CONFIG_PATH))
# Project Directories
WORKING_DIR = Path(__file__).resolve().parent
CONFIG_FILES = (
("hyperglass.yaml", False),
("devices.yaml", True),
("commands.yaml", False),
)
def _check_config_files(directory):
"""Verify config files exist and are readable.
Arguments:
directory {Path} -- Config directory Path object
Raises:
ConfigMissing: Raised if a required config file does not pass checks.
Returns:
{tuple} -- main config, devices config, commands config
"""
files = ()
for file in CONFIG_FILES:
file_name, required = file
file_path = directory / file_name
checked = check_path(file_path)
if checked is None and required:
raise ConfigMissing(missing_item=str(file_path))
if checked is None and not required:
log.warning(
"'{f}' was not found, but is not required to run hyperglass. "
+ "Defaults will be used.",
f=str(file_path),
)
files += (file_path,)
return files
STATIC_PATH = CONFIG_PATH / "static"
CONFIG_MAIN, CONFIG_DEVICES, CONFIG_COMMANDS = _check_config_files(CONFIG_PATH)
def _config_required(config_path: Path) -> Dict:
try:
with config_path.open("r") as cf:
config = yaml.safe_load(cf)
except (yaml.YAMLError, yaml.MarkedYAMLError) as yaml_error:
raise ConfigError(str(yaml_error))
if config is None:
log.critical("{} appears to be empty", str(config_path))
raise ConfigMissing(missing_item=config_path.name)
return config
def _config_optional(config_path: Path) -> Dict:
if config_path is None:
config = {}
else:
try:
with config_path.open("r") as cf:
config = yaml.safe_load(cf) or {}
except (yaml.YAMLError, yaml.MarkedYAMLError) as yaml_error:
raise ConfigError(error_msg=str(yaml_error))
return config
def _validate_nos_commands(all_nos, commands):
nos_with_commands = commands.dict().keys()
for nos in all_nos:
valid = False
if nos in SUPPORTED_STRUCTURED_OUTPUT:
valid = True
elif nos in TRANSPORT_REST:
valid = True
elif nos in nos_with_commands:
valid = True
if not valid:
raise ConfigError(
'"{nos}" is used on a device, '
+ 'but no command profile for "{nos}" is defined.',
nos=nos,
)
return True
def _validate_config(config: Union[Dict, List], importer: Callable) -> HyperglassModel:
validated = None
try:
if isinstance(config, Dict):
validated = importer(**config)
elif isinstance(config, List):
validated = importer(config)
except ValidationError as err:
log.error(str(err))
raise ConfigInvalid(err.errors()) from None
return validated
user_config = _config_optional(CONFIG_MAIN)
# Read raw debug value from config to enable debugging quickly.
set_log_level(logger=log, debug=user_config.get("debug", True))
# Map imported user configuration to expected schema.
log.debug("Unvalidated configuration from {}: {}", CONFIG_MAIN, user_config)
params = _validate_config(config=user_config, importer=Params)
# Re-evaluate debug state after config is validated
log_level = current_log_level(log)
if params.debug and log_level != "debug":
set_log_level(logger=log, debug=True)
elif not params.debug and log_level == "debug":
set_log_level(logger=log, debug=False)
# Map imported user commands to expected schema.
_user_commands = _config_optional(CONFIG_COMMANDS)
log.debug("Unvalidated commands from {}: {}", CONFIG_COMMANDS, _user_commands)
commands = _validate_config(config=_user_commands, importer=Commands.import_params)
# Map imported user devices to expected schema.
_user_devices = _config_required(CONFIG_DEVICES)
log.debug("Unvalidated devices from {}: {}", CONFIG_DEVICES, _user_devices)
devices = _validate_config(config=_user_devices.get("routers", []), importer=Devices)
# Validate commands are both supported and properly mapped.
_validate_nos_commands(devices.all_nos, commands)
# Set cache configurations to environment variables, so they can be
# used without importing this module (Gunicorn, etc).
set_cache_env(db=params.cache.database, host=params.cache.host, port=params.cache.port)
# Set up file logging once configuration parameters are initialized.
enable_file_logging(
logger=log,
log_directory=params.logging.directory,
log_format=params.logging.format,
log_max_size=params.logging.max_size,
)
# Set up syslog logging if enabled.
if params.logging.syslog is not None and params.logging.syslog.enable:
enable_syslog_logging(
logger=log,
syslog_host=params.logging.syslog.host,
syslog_port=params.logging.syslog.port,
)
if params.logging.http is not None and params.logging.http.enable:
log.debug("HTTP logging is enabled")
# Perform post-config initialization string formatting or other
# functions that require access to other config levels. E.g.,
# something in 'params.web.text' needs to be formatted with a value
# from params.
try:
params.web.text.subtitle = params.web.text.subtitle.format(
**params.dict(exclude={"web", "queries", "messages"})
)
# If keywords are unmodified (default), add the org name &
# site_title.
if Params().site_keywords == params.site_keywords:
params.site_keywords = sorted(
{*params.site_keywords, params.org_name, params.site_title}
)
except KeyError:
pass
def _build_frontend_networks():
"""Build filtered JSON structure of networks for frontend.
Schema:
{
"device.network.display_name": {
"device.name": {
"display_name": "device.display_name",
"vrfs": [
"Global",
"vrf.display_name"
]
}
}
}
Raises:
ConfigError: Raised if parsing/building error occurs.
Returns:
{dict} -- Frontend networks
"""
frontend_dict = {}
for device in devices.objects:
if device.network.display_name in frontend_dict:
frontend_dict[device.network.display_name].update(
{
device.name: {
"display_name": device.network.display_name,
"vrfs": [vrf.display_name for vrf in device.vrfs],
}
}
)
elif device.network.display_name not in frontend_dict:
frontend_dict[device.network.display_name] = {
device.name: {
"display_name": device.network.display_name,
"vrfs": [vrf.display_name for vrf in device.vrfs],
}
}
frontend_dict["default_vrf"] = devices.default_vrf
if not frontend_dict:
raise ConfigError(error_msg="Unable to build network to device mapping")
return frontend_dict
def _build_frontend_devices():
"""Build filtered JSON structure of devices for frontend.
Schema:
{
"device.name": {
"display_name": "device.display_name",
"vrfs": [
"Global",
"vrf.display_name"
]
}
}
Raises:
ConfigError: Raised if parsing/building error occurs.
Returns:
{dict} -- Frontend devices
"""
frontend_dict = {}
for device in devices.objects:
if device.name in frontend_dict:
frontend_dict[device.name].update(
{
"network": device.network.display_name,
"display_name": device.display_name,
"vrfs": [
{
"id": vrf.name,
"display_name": vrf.display_name,
"ipv4": True if vrf.ipv4 else False, # noqa: IF100
"ipv6": True if vrf.ipv6 else False, # noqa: IF100
}
for vrf in device.vrfs
],
}
)
elif device.name not in frontend_dict:
frontend_dict[device.name] = {
"network": device.network.display_name,
"display_name": device.display_name,
"vrfs": [
{
"id": vrf.name,
"display_name": vrf.display_name,
"ipv4": True if vrf.ipv4 else False, # noqa: IF100
"ipv6": True if vrf.ipv6 else False, # noqa: IF100
}
for vrf in device.vrfs
],
}
if not frontend_dict:
raise ConfigError(error_msg="Unable to build network to device mapping")
return frontend_dict
def _build_networks():
"""Build filtered JSON Structure of networks & devices for Jinja templates.
Raises:
ConfigError: Raised if parsing/building error occurs.
Returns:
{dict} -- Networks & devices
"""
networks = []
_networks = list(set({device.network.display_name for device in devices.objects}))
for _network in _networks:
network_def = {"display_name": _network, "locations": []}
for device in devices.objects:
if device.network.display_name == _network:
network_def["locations"].append(
{
"name": device.name,
"display_name": device.display_name,
"network": device.network.display_name,
"vrfs": [
{"id": vrf.name, "display_name": vrf.display_name}
for vrf in device.vrfs
],
}
)
networks.append(network_def)
if not networks:
raise ConfigError(error_msg="Unable to build network to device mapping")
return networks
def _build_vrfs():
vrfs = []
for device in devices.objects:
for vrf in device.vrfs:
vrf_dict = {
"id": vrf.name,
"display_name": vrf.display_name,
}
if vrf_dict not in vrfs:
vrfs.append(vrf_dict)
return vrfs
content_params = json.loads(
params.json(include={"primary_asn", "org_name", "site_title", "site_description"})
)
def _build_vrf_help():
"""Build a dict of vrfs as keys, help content as values.
Returns:
{dict} -- Formatted VRF help
"""
all_help = {}
for vrf in devices.vrf_objects:
vrf_help = {}
for command in SUPPORTED_QUERY_TYPES:
cmd = getattr(vrf.info, command)
if cmd.enable:
help_params = {**content_params, **cmd.params.dict()}
if help_params["title"] is None:
command_params = getattr(params.queries, command)
help_params[
"title"
] = f"{vrf.display_name}: {command_params.display_name}"
md = get_markdown(
config_path=cmd,
default=DEFAULT_DETAILS[command],
params=help_params,
)
vrf_help.update(
{
command: {
"content": md,
"enable": cmd.enable,
"params": help_params,
}
}
)
all_help.update({vrf.name: vrf_help})
return all_help
content_greeting = get_markdown(
config_path=params.web.greeting,
default="",
params={"title": params.web.greeting.title},
)
content_vrf = _build_vrf_help()
content_help_params = copy.copy(content_params)
content_help_params["title"] = params.web.help_menu.title
content_help = get_markdown(
config_path=params.web.help_menu, default=DEFAULT_HELP, params=content_help_params
)
content_terms_params = copy.copy(content_params)
content_terms_params["title"] = params.web.terms.title
content_terms = get_markdown(
config_path=params.web.terms, default=DEFAULT_TERMS, params=content_terms_params
)
content_credit = CREDIT.format(version=__version__)
vrfs = _build_vrfs()
networks = _build_networks()
frontend_networks = _build_frontend_networks()
frontend_devices = _build_frontend_devices()
_include_fields = {
"cache": {"show_text", "timeout"},
"debug": ...,
"developer_mode": ...,
"primary_asn": ...,
"request_timeout": ...,
"org_name": ...,
"google_analytics": ...,
"site_title": ...,
"site_description": ...,
"site_keywords": ...,
"web": ...,
"messages": ...,
}
_frontend_params = params.dict(include=_include_fields)
_frontend_params["web"]["logo"]["light_format"] = params.web.logo.light.suffix
_frontend_params["web"]["logo"]["dark_format"] = params.web.logo.dark.suffix
_frontend_params.update(
{
"hyperglass_version": __version__,
"queries": {**params.queries.map, "list": params.queries.list},
"devices": frontend_devices,
"networks": networks,
"vrfs": vrfs,
"parsed_data_fields": PARSED_RESPONSE_FIELDS,
"content": {
"help_menu": content_help,
"terms": content_terms,
"credit": content_credit,
"vrf": content_vrf,
"greeting": content_greeting,
},
}
)
frontend_params = _frontend_params
URL_DEV = f"http://localhost:{str(params.listen_port)}/"
URL_PROD = "/api/"
REDIS_CONFIG = {
"host": str(params.cache.host),
"port": params.cache.port,
"decode_responses": True,
"password": params.cache.password,
}

View File

@@ -0,0 +1,508 @@
"""Import configuration files and returns default values if undefined."""
# Standard Library
import os
import copy
import json
from typing import Dict, List, Union, Callable
from pathlib import Path
# Third Party
import yaml
from pydantic import ValidationError
# Project
from hyperglass.log import (
log,
set_log_level,
enable_file_logging,
enable_syslog_logging,
)
from hyperglass.util import check_path, set_app_path, set_cache_env, current_log_level
from hyperglass.models import HyperglassModel
from hyperglass.constants import (
TRANSPORT_REST,
SUPPORTED_QUERY_TYPES,
PARSED_RESPONSE_FIELDS,
SUPPORTED_STRUCTURED_OUTPUT,
__version__,
)
from hyperglass.exceptions import ConfigError, ConfigInvalid, ConfigMissing
from hyperglass.models.commands import Commands
from hyperglass.models.config.params import Params
from hyperglass.models.config.devices import Devices
from hyperglass.configuration.defaults import (
CREDIT,
DEFAULT_HELP,
DEFAULT_TERMS,
DEFAULT_DETAILS,
)
# Local
from .markdown import get_markdown
set_app_path(required=True)
CONFIG_PATH = Path(os.environ["hyperglass_directory"])
log.info("Configuration directory: {d}", d=str(CONFIG_PATH))
# Project Directories
WORKING_DIR = Path(__file__).resolve().parent
CONFIG_FILES = (
("hyperglass.yaml", False),
("devices.yaml", True),
("commands.yaml", False),
)
def _check_config_files(directory):
"""Verify config files exist and are readable.
Arguments:
directory {Path} -- Config directory Path object
Raises:
ConfigMissing: Raised if a required config file does not pass checks.
Returns:
{tuple} -- main config, devices config, commands config
"""
files = ()
for file in CONFIG_FILES:
file_name, required = file
file_path = directory / file_name
checked = check_path(file_path)
if checked is None and required:
raise ConfigMissing(missing_item=str(file_path))
if checked is None and not required:
log.warning(
"'{f}' was not found, but is not required to run hyperglass. "
+ "Defaults will be used.",
f=str(file_path),
)
files += (file_path,)
return files
STATIC_PATH = CONFIG_PATH / "static"
CONFIG_MAIN, CONFIG_DEVICES, CONFIG_COMMANDS = _check_config_files(CONFIG_PATH)
def _config_required(config_path: Path) -> Dict:
try:
with config_path.open("r") as cf:
config = yaml.safe_load(cf)
except (yaml.YAMLError, yaml.MarkedYAMLError) as yaml_error:
raise ConfigError(str(yaml_error))
if config is None:
log.critical("{} appears to be empty", str(config_path))
raise ConfigMissing(missing_item=config_path.name)
return config
def _config_optional(config_path: Path) -> Dict:
if config_path is None:
config = {}
else:
try:
with config_path.open("r") as cf:
config = yaml.safe_load(cf) or {}
except (yaml.YAMLError, yaml.MarkedYAMLError) as yaml_error:
raise ConfigError(error_msg=str(yaml_error))
return config
def _validate_nos_commands(all_nos, commands):
nos_with_commands = commands.dict().keys()
for nos in all_nos:
valid = False
if nos in SUPPORTED_STRUCTURED_OUTPUT:
valid = True
elif nos in TRANSPORT_REST:
valid = True
elif nos in nos_with_commands:
valid = True
if not valid:
raise ConfigError(
'"{nos}" is used on a device, '
+ 'but no command profile for "{nos}" is defined.',
nos=nos,
)
return True
def _validate_config(config: Union[Dict, List], importer: Callable) -> HyperglassModel:
validated = None
try:
if isinstance(config, Dict):
validated = importer(**config)
elif isinstance(config, List):
validated = importer(config)
except ValidationError as err:
log.error(str(err))
raise ConfigInvalid(err.errors()) from None
return validated
user_config = _config_optional(CONFIG_MAIN)
# Read raw debug value from config to enable debugging quickly.
set_log_level(logger=log, debug=user_config.get("debug", True))
# Map imported user configuration to expected schema.
log.debug("Unvalidated configuration from {}: {}", CONFIG_MAIN, user_config)
params = _validate_config(config=user_config, importer=Params)
# Re-evaluate debug state after config is validated
log_level = current_log_level(log)
if params.debug and log_level != "debug":
set_log_level(logger=log, debug=True)
elif not params.debug and log_level == "debug":
set_log_level(logger=log, debug=False)
# Map imported user commands to expected schema.
_user_commands = _config_optional(CONFIG_COMMANDS)
log.debug("Unvalidated commands from {}: {}", CONFIG_COMMANDS, _user_commands)
commands = _validate_config(config=_user_commands, importer=Commands.import_params)
# Map imported user devices to expected schema.
_user_devices = _config_required(CONFIG_DEVICES)
log.debug("Unvalidated devices from {}: {}", CONFIG_DEVICES, _user_devices)
devices = _validate_config(config=_user_devices.get("routers", []), importer=Devices)
# Validate commands are both supported and properly mapped.
_validate_nos_commands(devices.all_nos, commands)
# Set cache configurations to environment variables, so they can be
# used without importing this module (Gunicorn, etc).
set_cache_env(db=params.cache.database, host=params.cache.host, port=params.cache.port)
# Set up file logging once configuration parameters are initialized.
enable_file_logging(
logger=log,
log_directory=params.logging.directory,
log_format=params.logging.format,
log_max_size=params.logging.max_size,
)
# Set up syslog logging if enabled.
if params.logging.syslog is not None and params.logging.syslog.enable:
enable_syslog_logging(
logger=log,
syslog_host=params.logging.syslog.host,
syslog_port=params.logging.syslog.port,
)
if params.logging.http is not None and params.logging.http.enable:
log.debug("HTTP logging is enabled")
# Perform post-config initialization string formatting or other
# functions that require access to other config levels. E.g.,
# something in 'params.web.text' needs to be formatted with a value
# from params.
try:
params.web.text.subtitle = params.web.text.subtitle.format(
**params.dict(exclude={"web", "queries", "messages"})
)
# If keywords are unmodified (default), add the org name &
# site_title.
if Params().site_keywords == params.site_keywords:
params.site_keywords = sorted(
{*params.site_keywords, params.org_name, params.site_title}
)
except KeyError:
pass
def _build_frontend_networks():
"""Build filtered JSON structure of networks for frontend.
Schema:
{
"device.network.display_name": {
"device.name": {
"display_name": "device.display_name",
"vrfs": [
"Global",
"vrf.display_name"
]
}
}
}
Raises:
ConfigError: Raised if parsing/building error occurs.
Returns:
{dict} -- Frontend networks
"""
frontend_dict = {}
for device in devices.objects:
if device.network.display_name in frontend_dict:
frontend_dict[device.network.display_name].update(
{
device.name: {
"display_name": device.network.display_name,
"vrfs": [vrf.display_name for vrf in device.vrfs],
}
}
)
elif device.network.display_name not in frontend_dict:
frontend_dict[device.network.display_name] = {
device.name: {
"display_name": device.network.display_name,
"vrfs": [vrf.display_name for vrf in device.vrfs],
}
}
frontend_dict["default_vrf"] = devices.default_vrf
if not frontend_dict:
raise ConfigError(error_msg="Unable to build network to device mapping")
return frontend_dict
def _build_frontend_devices():
"""Build filtered JSON structure of devices for frontend.
Schema:
{
"device.name": {
"display_name": "device.display_name",
"vrfs": [
"Global",
"vrf.display_name"
]
}
}
Raises:
ConfigError: Raised if parsing/building error occurs.
Returns:
{dict} -- Frontend devices
"""
frontend_dict = {}
for device in devices.objects:
if device.name in frontend_dict:
frontend_dict[device.name].update(
{
"network": device.network.display_name,
"display_name": device.display_name,
"vrfs": [
{
"id": vrf.name,
"display_name": vrf.display_name,
"ipv4": True if vrf.ipv4 else False, # noqa: IF100
"ipv6": True if vrf.ipv6 else False, # noqa: IF100
}
for vrf in device.vrfs
],
}
)
elif device.name not in frontend_dict:
frontend_dict[device.name] = {
"network": device.network.display_name,
"display_name": device.display_name,
"vrfs": [
{
"id": vrf.name,
"display_name": vrf.display_name,
"ipv4": True if vrf.ipv4 else False, # noqa: IF100
"ipv6": True if vrf.ipv6 else False, # noqa: IF100
}
for vrf in device.vrfs
],
}
if not frontend_dict:
raise ConfigError(error_msg="Unable to build network to device mapping")
return frontend_dict
def _build_networks():
"""Build filtered JSON Structure of networks & devices for Jinja templates.
Raises:
ConfigError: Raised if parsing/building error occurs.
Returns:
{dict} -- Networks & devices
"""
networks = []
_networks = list(set({device.network.display_name for device in devices.objects}))
for _network in _networks:
network_def = {"display_name": _network, "locations": []}
for device in devices.objects:
if device.network.display_name == _network:
network_def["locations"].append(
{
"name": device.name,
"display_name": device.display_name,
"network": device.network.display_name,
"vrfs": [
{"id": vrf.name, "display_name": vrf.display_name}
for vrf in device.vrfs
],
}
)
networks.append(network_def)
if not networks:
raise ConfigError(error_msg="Unable to build network to device mapping")
return networks
def _build_vrfs():
vrfs = []
for device in devices.objects:
for vrf in device.vrfs:
vrf_dict = {
"id": vrf.name,
"display_name": vrf.display_name,
}
if vrf_dict not in vrfs:
vrfs.append(vrf_dict)
return vrfs
content_params = json.loads(
params.json(include={"primary_asn", "org_name", "site_title", "site_description"})
)
def _build_vrf_help():
"""Build a dict of vrfs as keys, help content as values.
Returns:
{dict} -- Formatted VRF help
"""
all_help = {}
for vrf in devices.vrf_objects:
vrf_help = {}
for command in SUPPORTED_QUERY_TYPES:
cmd = getattr(vrf.info, command)
if cmd.enable:
help_params = {**content_params, **cmd.params.dict()}
if help_params["title"] is None:
command_params = getattr(params.queries, command)
help_params[
"title"
] = f"{vrf.display_name}: {command_params.display_name}"
md = get_markdown(
config_path=cmd,
default=DEFAULT_DETAILS[command],
params=help_params,
)
vrf_help.update(
{
command: {
"content": md,
"enable": cmd.enable,
"params": help_params,
}
}
)
all_help.update({vrf.name: vrf_help})
return all_help
content_greeting = get_markdown(
config_path=params.web.greeting,
default="",
params={"title": params.web.greeting.title},
)
content_vrf = _build_vrf_help()
content_help_params = copy.copy(content_params)
content_help_params["title"] = params.web.help_menu.title
content_help = get_markdown(
config_path=params.web.help_menu, default=DEFAULT_HELP, params=content_help_params
)
content_terms_params = copy.copy(content_params)
content_terms_params["title"] = params.web.terms.title
content_terms = get_markdown(
config_path=params.web.terms, default=DEFAULT_TERMS, params=content_terms_params
)
content_credit = CREDIT.format(version=__version__)
vrfs = _build_vrfs()
networks = _build_networks()
frontend_networks = _build_frontend_networks()
frontend_devices = _build_frontend_devices()
_include_fields = {
"cache": {"show_text", "timeout"},
"debug": ...,
"developer_mode": ...,
"primary_asn": ...,
"request_timeout": ...,
"org_name": ...,
"google_analytics": ...,
"site_title": ...,
"site_description": ...,
"site_keywords": ...,
"web": ...,
"messages": ...,
}
_frontend_params = params.dict(include=_include_fields)
_frontend_params["web"]["logo"]["light_format"] = params.web.logo.light.suffix
_frontend_params["web"]["logo"]["dark_format"] = params.web.logo.dark.suffix
_frontend_params.update(
{
"hyperglass_version": __version__,
"queries": {**params.queries.map, "list": params.queries.list},
"devices": frontend_devices,
"networks": networks,
"vrfs": vrfs,
"parsed_data_fields": PARSED_RESPONSE_FIELDS,
"content": {
"help_menu": content_help,
"terms": content_terms,
"credit": content_credit,
"vrf": content_vrf,
"greeting": content_greeting,
},
}
)
frontend_params = _frontend_params
URL_DEV = f"http://localhost:{str(params.listen_port)}/"
URL_PROD = "/api/"
REDIS_CONFIG = {
"host": str(params.cache.host),
"port": params.cache.port,
"decode_responses": True,
"password": params.cache.password,
}

View File

@@ -8,7 +8,7 @@ from hyperglass.log import log
from hyperglass.models.api import Query from hyperglass.models.api import Query
from hyperglass.parsing.nos import scrape_parsers, structured_parsers from hyperglass.parsing.nos import scrape_parsers, structured_parsers
from hyperglass.parsing.common import parsers from hyperglass.parsing.common import parsers
from hyperglass.configuration.models.devices import Device from hyperglass.models.config.devices import Device
from ._construct import Construct from ._construct import Construct

View File

@@ -6,8 +6,8 @@ from typing import Union, Optional
# Third Party # Third Party
from pydantic import SecretStr, StrictInt, StrictStr, StrictBool, IPvAnyAddress from pydantic import SecretStr, StrictInt, StrictStr, StrictBool, IPvAnyAddress
# Project # Local
from hyperglass.models import HyperglassModel from ..main import HyperglassModel
class Cache(HyperglassModel): class Cache(HyperglassModel):

View File

@@ -3,8 +3,8 @@
# Third Party # Third Party
from pydantic import SecretStr, StrictStr from pydantic import SecretStr, StrictStr
# Project # Local
from hyperglass.models import HyperglassModel from ..main import HyperglassModel
class Credential(HyperglassModel): class Credential(HyperglassModel):

View File

@@ -13,14 +13,16 @@ from pydantic import StrictInt, StrictStr, StrictBool, validator
# Project # Project
from hyperglass.log import log from hyperglass.log import log
from hyperglass.util import validate_nos, resolve_hostname from hyperglass.util import validate_nos, resolve_hostname
from hyperglass.models import HyperglassModel, HyperglassModelExtra
from hyperglass.constants import SCRAPE_HELPERS, SUPPORTED_STRUCTURED_OUTPUT from hyperglass.constants import SCRAPE_HELPERS, SUPPORTED_STRUCTURED_OUTPUT
from hyperglass.exceptions import ConfigError, UnsupportedDevice from hyperglass.exceptions import ConfigError, UnsupportedDevice
from hyperglass.configuration.models.ssl import Ssl
from hyperglass.configuration.models.vrf import Vrf, Info # Local
from hyperglass.configuration.models.proxy import Proxy from .ssl import Ssl
from hyperglass.configuration.models.network import Network from .vrf import Vrf, Info
from hyperglass.configuration.models.credential import Credential from ..main import HyperglassModel, HyperglassModelExtra
from .proxy import Proxy
from .network import Network
from .credential import Credential
_default_vrf = { _default_vrf = {
"name": "default", "name": "default",

View File

@@ -2,9 +2,9 @@
# Third Party # Third Party
from pydantic import Field, HttpUrl, StrictStr, StrictBool, constr from pydantic import Field, HttpUrl, StrictStr, StrictBool, constr
# Project # Local
from hyperglass.models import HyperglassModel from ..main import HyperglassModel
from hyperglass.models.fields import AnyUri from ..fields import AnyUri
DocsMode = constr(regex=r"(swagger|redoc)") DocsMode = constr(regex=r"(swagger|redoc)")

View File

@@ -21,9 +21,11 @@ from pydantic import (
) )
# Project # Project
from hyperglass.models import HyperglassModel, HyperglassModelExtra
from hyperglass.constants import __version__ from hyperglass.constants import __version__
# Local
from ..main import HyperglassModel, HyperglassModelExtra
HttpAuthMode = constr(regex=r"(basic|api_key)") HttpAuthMode = constr(regex=r"(basic|api_key)")
HttpProvider = constr(regex=r"(msteams|slack|generic)") HttpProvider = constr(regex=r"(msteams|slack|generic)")
LogFormat = constr(regex=r"(text|json)") LogFormat = constr(regex=r"(text|json)")

View File

@@ -3,8 +3,8 @@
# Third Party # Third Party
from pydantic import Field, StrictStr from pydantic import Field, StrictStr
# Project # Local
from hyperglass.models import HyperglassModel from ..main import HyperglassModel
class Messages(HyperglassModel): class Messages(HyperglassModel):

View File

@@ -3,8 +3,8 @@
# Third Party # Third Party
from pydantic import Field, StrictStr from pydantic import Field, StrictStr
# Project # Local
from hyperglass.models import HyperglassModel from ..main import HyperglassModel
class Network(HyperglassModel): class Network(HyperglassModel):

View File

@@ -7,8 +7,8 @@ from pathlib import Path
# Third Party # Third Party
from pydantic import FilePath, validator from pydantic import FilePath, validator
# Project # Local
from hyperglass.models import HyperglassModel from ..main import HyperglassModel
CONFIG_PATH = Path(os.environ["hyperglass_directory"]) CONFIG_PATH = Path(os.environ["hyperglass_directory"])
DEFAULT_IMAGES = Path(__file__).parent.parent.parent / "images" DEFAULT_IMAGES = Path(__file__).parent.parent.parent / "images"

View File

@@ -15,16 +15,16 @@ from pydantic import (
validator, validator,
) )
# Project # Local
from hyperglass.models import HyperglassModel from .web import Web
from hyperglass.models.fields import IntFloat from .docs import Docs
from hyperglass.configuration.models.web import Web from ..main import HyperglassModel
from hyperglass.configuration.models.docs import Docs from .cache import Cache
from hyperglass.configuration.models.cache import Cache from ..fields import IntFloat
from hyperglass.configuration.models.logging import Logging from .logging import Logging
from hyperglass.configuration.models.queries import Queries from .queries import Queries
from hyperglass.configuration.models.messages import Messages from .messages import Messages
from hyperglass.configuration.models.structured import Structured from .structured import Structured
Localhost = constr(regex=r"localhost") Localhost = constr(regex=r"localhost")

View File

@@ -9,9 +9,11 @@ from pydantic import StrictInt, StrictStr, validator
# Project # Project
from hyperglass.util import resolve_hostname from hyperglass.util import resolve_hostname
from hyperglass.models import HyperglassModel
from hyperglass.exceptions import ConfigError, UnsupportedDevice from hyperglass.exceptions import ConfigError, UnsupportedDevice
from hyperglass.configuration.models.credential import Credential
# Local
from ..main import HyperglassModel
from .credential import Credential
class Proxy(HyperglassModel): class Proxy(HyperglassModel):

View File

@@ -7,9 +7,11 @@ from typing import List
from pydantic import Field, StrictStr, StrictBool, constr from pydantic import Field, StrictStr, StrictBool, constr
# Project # Project
from hyperglass.models import HyperglassModel
from hyperglass.constants import SUPPORTED_QUERY_TYPES from hyperglass.constants import SUPPORTED_QUERY_TYPES
# Local
from ..main import HyperglassModel
ASPathMode = constr(regex=r"asplain|asdot") ASPathMode = constr(regex=r"asplain|asdot")
CommunityInput = constr(regex=r"(input|select)") CommunityInput = constr(regex=r"(input|select)")

View File

@@ -6,8 +6,8 @@ from typing import Optional
# Third Party # Third Party
from pydantic import Field, FilePath, StrictBool from pydantic import Field, FilePath, StrictBool
# Project # Local
from hyperglass.models import HyperglassModel from ..main import HyperglassModel
class Ssl(HyperglassModel): class Ssl(HyperglassModel):

View File

@@ -6,8 +6,8 @@ from typing import List
# Third Party # Third Party
from pydantic import StrictStr, constr from pydantic import StrictStr, constr
# Project # Local
from hyperglass.models import HyperglassModel from ..main import HyperglassModel
StructuredCommunityMode = constr(regex=r"(permit|deny)") StructuredCommunityMode = constr(regex=r"(permit|deny)")
StructuredRPKIMode = constr(regex=r"(router|external)") StructuredRPKIMode = constr(regex=r"(router|external)")

View File

@@ -16,8 +16,8 @@ from pydantic import (
root_validator, root_validator,
) )
# Project # Local
from hyperglass.models import HyperglassModel, HyperglassModelExtra from ..main import HyperglassModel, HyperglassModelExtra
ACLAction = constr(regex=r"permit|deny") ACLAction = constr(regex=r"permit|deny")

View File

@@ -18,9 +18,11 @@ from pydantic import (
from pydantic.color import Color from pydantic.color import Color
# Project # Project
from hyperglass.models import HyperglassModel
from hyperglass.constants import DNS_OVER_HTTPS, FUNC_COLOR_MAP from hyperglass.constants import DNS_OVER_HTTPS, FUNC_COLOR_MAP
from hyperglass.configuration.models.opengraph import OpenGraph
# Local
from ..main import HyperglassModel
from .opengraph import OpenGraph
DEFAULT_IMAGES = Path(__file__).parent.parent.parent / "images" DEFAULT_IMAGES = Path(__file__).parent.parent.parent / "images"

View File

@@ -51,7 +51,7 @@ def _comment_optional_files():
def _validate_devices(): def _validate_devices():
# Project # Project
from hyperglass.configuration.models.devices import Devices from hyperglass.models.config.devices import Devices
with DEVICES.open() as raw: with DEVICES.open() as raw:
devices_dict = yaml.safe_load(raw.read()) or {} devices_dict = yaml.safe_load(raw.read()) or {}
@@ -77,7 +77,7 @@ def _validate_commands():
def _validate_main(): def _validate_main():
# Project # Project
from hyperglass.configuration.models.params import Params from hyperglass.models.config.params import Params
with MAIN.open() as raw: with MAIN.open() as raw:
main_dict = yaml.safe_load(raw.read()) or {} main_dict = yaml.safe_load(raw.read()) or {}