From 80073dd8c88f4b1417c3ca793e4506fea9a5747c Mon Sep 17 00:00:00 2001 From: Blake Harnden <32446120+bharnden@users.noreply.github.com> Date: Fri, 24 Jan 2020 22:15:21 -0800 Subject: [PATCH] adding documentation to config service base class --- daemon/core/configservice/base.py | 121 ++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/daemon/core/configservice/base.py b/daemon/core/configservice/base.py index b0033a0c..47cd6f62 100644 --- a/daemon/core/configservice/base.py +++ b/daemon/core/configservice/base.py @@ -28,6 +28,10 @@ class ConfigServiceBootError(Exception): class ConfigService(abc.ABC): + """ + Base class for creating configurable services. + """ + # validation period in seconds, how frequent validation is attempted validation_period = 0.5 @@ -35,6 +39,11 @@ class ConfigService(abc.ABC): validation_timer = 5 def __init__(self, node: CoreNode) -> None: + """ + Create ConfigService instance. + + :param node: node this service is assigned to + """ self.node = node class_file = inspect.getfile(self.__class__) templates_path = pathlib.Path(class_file).parent.joinpath(TEMPLATES_DIR) @@ -47,6 +56,13 @@ class ConfigService(abc.ABC): @staticmethod def clean_text(text: str) -> str: + """ + Returns space stripped text for string literals, while keeping space + indentations. + + :param text: text to clean + :return: cleaned text + """ return inspect.cleandoc(text) @property @@ -110,6 +126,13 @@ class ConfigService(abc.ABC): raise NotImplementedError def start(self) -> None: + """ + Creates services files/directories, runs startup, and validates based on + validation mode. + + :return: nothing + :raises ConfigServiceBootError: when there is an error starting service + """ logging.info("node(%s) service(%s) starting...", self.node.name, self.name) self.create_dirs() self.create_files() @@ -122,6 +145,11 @@ class ConfigService(abc.ABC): self.run_validation() def stop(self) -> None: + """ + Stop service using shutdown commands. + + :return: nothing + """ for cmd in self.shutdown: try: self.node.cmd(cmd) @@ -132,10 +160,21 @@ class ConfigService(abc.ABC): ) def restart(self) -> None: + """ + Restarts service by running stop and then start. + + :return: nothing + """ self.stop() self.start() def create_dirs(self) -> None: + """ + Creates directories for service. + + :return: nothing + :raises CoreError: when there is a failure creating a directory + """ for directory in self.directories: try: self.node.privatedir(directory) @@ -146,15 +185,39 @@ class ConfigService(abc.ABC): ) def data(self) -> Dict[str, Any]: + """ + Returns key/value data, used when rendering file templates. + + :return: key/value template data + """ return {} def set_template(self, name: str, template: str) -> None: + """ + Store custom template to render for a given file. + + :param name: file to store custom template for + :param template: custom template to render + :return: nothing + """ self.custom_templates[name] = template def get_text_template(self, name: str) -> str: + """ + Retrieves text based template for files that do not have a file based template. + + :param name: name of file to get template for + :return: template to render + """ raise CoreError(f"service({self.name}) unknown template({name})") def get_templates(self) -> Dict[str, str]: + """ + Retrieves mapping of file names to templates for all cases, which + includes custom templates, file templates, and text templates. + + :return: mapping of files to templates + """ templates = {} for name in self.files: basename = pathlib.Path(name).name @@ -170,6 +233,11 @@ class ConfigService(abc.ABC): return templates def create_files(self) -> None: + """ + Creates service files inside associated node. + + :return: nothing + """ data = self.data() for name in self.files: basename = pathlib.Path(name).name @@ -191,6 +259,14 @@ class ConfigService(abc.ABC): self.node.nodefile(name, rendered) def run_startup(self, wait: bool) -> None: + """ + Run startup commands for service on node. + + :param wait: wait successful command exit status when True, ignore status + otherwise + :return: nothing + :raises ConfigServiceBootError: when a command that waits fails + """ for cmd in self.startup: try: self.node.cmd(cmd, wait=wait) @@ -200,6 +276,12 @@ class ConfigService(abc.ABC): ) def run_validation(self) -> None: + """ + Runs validation commands for service on node. + + :return: nothing + :raises ConfigServiceBootError: if there is a validation failure + """ start = time.monotonic() cmds = self.validate[:] index = 0 @@ -222,6 +304,13 @@ class ConfigService(abc.ABC): ) def _render(self, template: Template, data: Dict[str, Any] = None) -> str: + """ + Renders template providing all associated data to template. + + :param template: template to render + :param data: service specific defined data for template + :return: rendered template + """ if data is None: data = {} return template.render_unicode( @@ -229,6 +318,13 @@ class ConfigService(abc.ABC): ) def render_text(self, text: str, data: Dict[str, Any] = None) -> str: + """ + Renders text based template providing all associated data to template. + + :param text: text to render + :param data: service specific defined data for template + :return: rendered template + """ text = self.clean_text(text) try: template = Template(text) @@ -240,6 +336,13 @@ class ConfigService(abc.ABC): ) def render_template(self, basename: str, data: Dict[str, Any] = None) -> str: + """ + Renders file based template providing all associated data to template. + + :param basename: base name for file to render + :param data: service specific defined data for template + :return: rendered template + """ try: template = self.templates.get_template(basename) return self._render(template, data) @@ -250,16 +353,34 @@ class ConfigService(abc.ABC): ) def _define_config(self, configs: List[Configuration]) -> None: + """ + Initializes default configuration data. + + :param configs: configs to initialize + :return: nothing + """ for config in configs: self.config[config.id] = config def render_config(self) -> Dict[str, str]: + """ + Returns configuration data key/value pairs for rendering a template. + + :return: nothing + """ if self.custom_config: return self.custom_config else: return {k: v.default for k, v in self.config.items()} def set_config(self, data: Dict[str, str]) -> None: + """ + Set configuration data from key/value pairs. + + :param data: configuration key/values to set + :return: nothing + :raise CoreError: when an unknown configuration value is given + """ for key, value in data.items(): if key not in self.config: raise CoreError(f"unknown config: {key}")