From ab097d4b06384c43385b236ba535d36bc4d70ea9 Mon Sep 17 00:00:00 2001 From: thatmattlove Date: Thu, 16 Sep 2021 22:43:53 -0700 Subject: [PATCH] Refactor `Device.commands` to `Device.directives` --- hyperglass/configuration/__init__.py | 4 +-- hyperglass/configuration/main.py | 43 ++++++++++++---------------- hyperglass/models/config/devices.py | 27 ++++++++++------- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/hyperglass/configuration/__init__.py b/hyperglass/configuration/__init__.py index 1f33d03..b9ce906 100644 --- a/hyperglass/configuration/__init__.py +++ b/hyperglass/configuration/__init__.py @@ -1,11 +1,11 @@ """hyperglass Configuration.""" # Local -from .main import params, devices, commands, ui_params +from .main import params, devices, directives, ui_params __all__ = ( "params", "devices", - "commands", + "directives", "ui_params", ) diff --git a/hyperglass/configuration/main.py b/hyperglass/configuration/main.py index 4d5a3af..3e46e84 100644 --- a/hyperglass/configuration/main.py +++ b/hyperglass/configuration/main.py @@ -10,7 +10,6 @@ from pydantic import ValidationError # Project from hyperglass.log import log, enable_file_logging, enable_syslog_logging -from hyperglass.util import set_cache_env from hyperglass.defaults import CREDIT from hyperglass.settings import Settings from hyperglass.constants import PARSED_RESPONSE_FIELDS, __version__ @@ -33,7 +32,7 @@ WORKING_DIR = Path(__file__).resolve().parent CONFIG_FILES = ( ("hyperglass.yaml", False), ("devices.yaml", True), - ("commands.yaml", False), + ("directives.yaml", False), ) @@ -62,7 +61,7 @@ def _check_config_files(directory: Path): return files -CONFIG_MAIN, CONFIG_DEVICES, CONFIG_COMMANDS = _check_config_files(CONFIG_PATH) +CONFIG_MAIN, CONFIG_DEVICES, CONFIG_DIRECTIVES = _check_config_files(CONFIG_PATH) def _config_required(config_path: Path) -> Dict: @@ -97,29 +96,30 @@ def _config_optional(config_path: Path) -> Dict: return config -def _get_commands(data: Dict) -> List[Directive]: - commands = [] - for name, command in data.items(): +def _get_directives(data: Dict) -> List[Directive]: + directives = [] + for name, directive in data.items(): try: - commands.append(Directive(id=name, **command)) + directives.append(Directive(id=name, **directive)) except ValidationError as err: raise ConfigError( - message="Validation error in command '{c}': '{e}'", c=name, e=err + message="Validation error in directive '{d}': '{e}'", d=name, e=err ) from err - return commands + return directives -def _device_commands(device: Dict, directives: List[Directive]) -> Generator[Directive, None, None]: - device_commands = device.get("commands", []) +def _device_directives( + device: Dict, directives: List[Directive] +) -> Generator[Directive, None, None]: for directive in directives: - if directive.id in device_commands: + if directive.id in device.get("directives", []): yield directive def _get_devices(data: List[Dict], directives: List[Directive]) -> Devices: for device in data: - device_commands = list(_device_commands(device, directives)) - device["commands"] = device_commands + directives = list(_device_directives(device, directives)) + device["directives"] = directives return Devices(data) @@ -131,19 +131,16 @@ user_config = _config_optional(CONFIG_MAIN) log.debug("Unvalidated configuration from {}: {}", CONFIG_MAIN, user_config) params = validate_config(config=user_config, importer=Params) -# Map imported user commands to expected schema. -_user_commands = _config_optional(CONFIG_COMMANDS) -log.debug("Unvalidated commands from {}: {}", CONFIG_COMMANDS, _user_commands) -commands = _get_commands(_user_commands) +# Map imported user directives to expected schema. +_user_directives = _config_optional(CONFIG_DIRECTIVES) +log.debug("Unvalidated directives from {!s}: {}", CONFIG_DIRECTIVES, _user_directives) +directives = _get_directives(_user_directives) # Map imported user devices to expected schema. _user_devices = _config_required(CONFIG_DEVICES) log.debug("Unvalidated devices from {}: {}", CONFIG_DEVICES, _user_devices) -devices: Devices = _get_devices(_user_devices.get("routers", []), commands) +devices = _get_devices(_user_devices.get("devices", _user_devices.get("routers", [])), directives) -# 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( @@ -198,5 +195,3 @@ ui_params = UIParameters( parsed_data_fields=PARSED_RESPONSE_FIELDS, content={"credit": content_credit, "greeting": content_greeting}, ) - -URL_PROD = "/api/" diff --git a/hyperglass/models/config/devices.py b/hyperglass/models/config/devices.py index 9913603..0210b75 100644 --- a/hyperglass/models/config/devices.py +++ b/hyperglass/models/config/devices.py @@ -46,7 +46,7 @@ class Device(HyperglassModelWithId, extra="allow"): port: StrictInt = 22 ssl: Optional[Ssl] platform: StrictStr - commands: List[Directive] + directives: List[Directive] structured_output: Optional[StrictBool] driver: Optional[SupportedDriver] attrs: Dict[str, str] = {} @@ -95,12 +95,16 @@ class Device(HyperglassModelWithId, extra="allow"): "network": self.network.display_name, } + @property + def directive_builtins(self) -> List[str]: + ... + @property def directive_commands(self) -> List[str]: """Get all commands associated with the device.""" return [ command - for directive in self.commands + for directive in self.directives for rule in directive.rules for command in rule.commands ] @@ -108,7 +112,7 @@ class Device(HyperglassModelWithId, extra="allow"): @property def directive_ids(self) -> List[str]: """Get all directive IDs associated with the device.""" - return [directive.id for directive in self.commands] + return [directive.id for directive in self.directives] def has_directives(self, *directive_ids: str) -> bool: """Determine if a directive is used on this device.""" @@ -184,8 +188,8 @@ class Device(HyperglassModelWithId, extra="allow"): return value @root_validator(pre=True) - def validate_device_commands(cls, values: Dict) -> Dict: - """Validate & rewrite device platform, set default commands.""" + def validate_device(cls, values: Dict[str, Any]) -> Dict[str, Any]: + """Validate & rewrite device platform, set default directives.""" platform = values.get("platform") if platform is None: @@ -206,10 +210,11 @@ class Device(HyperglassModelWithId, extra="allow"): values["platform"] = platform - commands = values.get("commands") + directives = values.get("directives") - if commands is None: - # If no commands are defined, set commands to the NOS. + if directives is None: + # TODO: This should be different now, and could be removed after there's a way to associate default directives + # If no directive are defined, set directive to the NOS. inferred = values["platform"] # If the _telnet prefix is added, remove it from the command @@ -218,7 +223,7 @@ class Device(HyperglassModelWithId, extra="allow"): if "_telnet" in inferred: inferred = inferred.replace("_telnet", "") - values["commands"] = [inferred] + values["directives"] = [inferred] return values @@ -293,7 +298,7 @@ class Devices(HyperglassModel, extra="allow"): "id": device.id, "name": device.name, "network": device.network.display_name, - "directives": [c.frontend(params) for c in device.commands], + "directives": [d.frontend(params) for d in device.directives], } for device in self.objects if device.network.display_name == name @@ -306,7 +311,7 @@ class Devices(HyperglassModel, extra="allow"): """Get a mapping of plugin paths to associated directive IDs.""" result: Dict[Path, Set[StrictStr]] = {} # Unique set of all directives. - directives = {directive for device in self.objects for directive in device.commands} + directives = {directive for device in self.objects for directive in device.directives} # Unique set of all plugin file names. plugin_names = {plugin for directive in directives for plugin in directive.plugins}