Skip to content

config

Base configuration wrappers

To import...

from dynamite_nsm.services.base import config

BackupConfigManager

Manage backup and restoration process across various service configs

list_backup_configs(self)

List configuration backups

Returns:

Type Description
List

A list of dictionaries with the following keys ["name", "path", "timestamp"]

Source code in dynamite_nsm/services/base/config.py
def list_backup_configs(self) -> List:
    """List configuration backups

    Returns:
         A list of dictionaries with the following keys ["name", "path", "timestamp"]
    """
    return utilities.list_backup_configurations(self.backup_directory)

restore_backup_config(self, backup_name, restore_name)

Restore a configuration from our config store

:param backup_name: The name of the configuration file or the keyword "recent" which will restore the most recent backup. :param restore_name: The name of the configuration file to write too :return: True, if successful

Source code in dynamite_nsm/services/base/config.py
def restore_backup_config(self, backup_name: str, restore_name: str):
    """
    Restore a configuration from our config store

    :param backup_name: The name of the configuration file or the keyword "recent" which will restore the most recent backup.
    :param restore_name: The name of the configuration file to write too
    :return: True, if successful
    """
    if backup_name == "recent":
        configs = self.list_backup_configs()
        if configs:
            return utilities.restore_backup_configuration(configs[0]['filepath'], restore_name)
    return utilities.restore_backup_configuration(
        os.path.join(self.backup_directory, backup_name), restore_name)

GenericConfigManager

__init__(self, config_data, name, verbose=False, stdout=True) special

A catchall configuration manager, generic enough to work on any configuration like file

Parameters:

Name Type Description Default
config_data Dict

Configuration data dictionary

required
name str

The name of the configuration

required
verbose Optional[bool]

Include detailed debug messages

False
stdout Optional[bool]

Print output to console

True
Source code in dynamite_nsm/services/base/config.py
def __init__(self, config_data: Dict, name: str, verbose: Optional[bool] = False, stdout: Optional[bool] = True):
    """
    A catchall configuration manager, generic enough to work on any configuration like file
    Args:
        config_data: Configuration data dictionary
        name: The name of the configuration
        verbose: Include detailed debug messages
        stdout: Print output to console
    """
    if not utilities.is_setup():
        raise exceptions.DynamiteNotSetupError()
    self.config_data = config_data
    self.formatted_data = json.dumps(config_data)
    log_level = logging.INFO
    if verbose:
        log_level = logging.DEBUG
    self.stdout = stdout
    self.verbose = verbose
    self.logger = get_logger(str(name), level=log_level, stdout=stdout)

commit(self, out_file_path, backup_directory=None)

Write out an updated configuration file, and optionally backup the old one.

Parameters:

Name Type Description Default
out_file_path str

The path to the output file

required
backup_directory Optional[str]

The path to the backup directory

None

Returns:

Type Description
None

None

Source code in dynamite_nsm/services/base/config.py
def commit(self, out_file_path: str, backup_directory: Optional[str] = None) -> None:
    """Write out an updated configuration file, and optionally backup the old one.
    Args:
        out_file_path: The path to the output file
        backup_directory: The path to the backup directory
    Returns:
        None
    """

    # Backup old configuration first
    out_file_name = os.path.basename(out_file_path)
    backup_file_name = out_file_name + '.backup'
    if backup_directory:
        utilities.backup_configuration_file(out_file_path, backup_directory,
                                            destination_file_prefix=backup_file_name)
    try:
        with open(out_file_path, 'w') as config_raw_f:
            config_raw_f.write(self.formatted_data)
        if utilities.is_root():
            utilities.set_ownership_of_file(out_file_path)
    except IOError as e:
        raise exceptions.WriteConfigError(f'An error occurred while writing the configuration file to disk. {e}')
    self.logger.warning('Configuration updated. Restart this service to apply.')

get_printable_config(self)

Get the configuration as a dictionary object

Returns:

Type Description
Dict

A dictionary of config keys and values

Source code in dynamite_nsm/services/base/config.py
def get_printable_config(self) -> Dict:
    """
    Get the configuration as a dictionary object
    Returns:
        A dictionary of config keys and values
    """
    variables = {}
    for var in vars(self):
        if var.startswith('_'):
            continue
        variables[var] = str(getattr(self, var))
    return variables

reset(self, out_file_path, default_config_path)

Reset a configuration file back to its default

!!! out_file_path "The path to the output file" default_config_path: The path to the default configuration

Returns:

Type Description

None

Source code in dynamite_nsm/services/base/config.py
def reset(self, out_file_path: Optional[str], default_config_path: Optional[str]):
    """Reset a configuration file back to its default
    Args:
    out_file_path: The path to the output file
        default_config_path: The path to the default configuration

    Returns:
        None
    """
    self.logger.info(f'Restoring {out_file_path} to default state.')
    with open(default_config_path, 'r') as default_conf_f_in:
        with open(out_file_path, 'w') as conf_f_out:
            conf_f_out.write(default_conf_f_in.read())
    if utilities.is_root():
        utilities.set_ownership_of_file(out_file_path)

JavaOptionsConfigManager

A special base configuration manager for jvm.options configurations

__init__(self, config_data, name, verbose=False, stdout=True) special

Work with jvm.options configurations

Parameters:

Name Type Description Default
config_data Dict

Configuration data dictionary

required
name str

The name of the configuration

required
verbose Optional[bool]

Include detailed debug messages

False
stdout Optional[bool]

Print output to console

True
Source code in dynamite_nsm/services/base/config.py
def __init__(self, config_data: Dict, name: str, verbose: Optional[bool] = False, stdout: Optional[bool] = True):
    """Work with jvm.options configurations
    Args:
        config_data: Configuration data dictionary
        name: The name of the configuration
        verbose: Include detailed debug messages
        stdout: Print output to console
    """
    super().__init__(config_data, name=name, verbose=verbose, stdout=stdout)

    self.initial_memory = None
    self.maximum_memory = None
    self._raw_extra_params = None

    self.add_parser(
        parser=lambda data: self._parse_jvm_options(data)[0],
        attribute_name='initial_memory'
    )
    self.add_parser(
        parser=lambda data: self._parse_jvm_options(data)[1],
        attribute_name='maximum_memory'
    )

    self.add_parser(
        parser=lambda data: self._parse_jvm_options(data)[2],
        attribute_name='_raw_extra_params'
    )

commit(self, out_file_path=None, backup_directory=None)

Write out an updated configuration file, and optionally backup the old one.

Parameters:

Name Type Description Default
out_file_path Optional[str]

The path to the output file; if none given overwrites existing

None
backup_directory Optional[str]

The path to the backup directory

None

Returns:

Type Description
None

None

Source code in dynamite_nsm/services/base/config.py
def commit(self, out_file_path: Optional[str] = None, backup_directory: Optional[str] = None) -> None:
    """Write out an updated configuration file, and optionally backup the old one.
    Args:
        out_file_path: The path to the output file; if none given overwrites existing
        backup_directory: The path to the backup directory
    Returns:
        None
    """

    # Backup old configuration first
    out_file_name = os.path.basename(out_file_path)
    backup_file_name = out_file_name + '.backup'
    self.formatted_data = f'-Xms{self.initial_memory}\n-Xmx{self.maximum_memory}\n' + \
                          '\n'.join(self._raw_extra_params)
    if backup_directory:
        utilities.backup_configuration_file(out_file_path, backup_directory,
                                            destination_file_prefix=backup_file_name)
    try:
        with open(out_file_path, 'w') as config_raw_f:
            config_raw_f.write(self.formatted_data)
        if utilities.is_root():
            utilities.set_ownership_of_file(out_file_path)
            utilities.set_permissions_of_file(out_file_path, 644)
    except IOError:
        raise exceptions.WriteConfigError('An error occurred while writing the configuration file to disk.')

YamlConfigManager

A configuration manager for working with any YAML formatted configuration file

__init__(self, config_data, name, verbose=False, stdout=True, **extract_tokens) special

Work with YAML based configuration files

Parameters:

Name Type Description Default
config_data Dict

Configuration data dictionary

required
name str

The name of the configuration

required
verbose Optional[bool]

Include detailed debug messages

False
stdout Optional[bool]

Print output to console

True
**extract_tokens Dict

A dictionary object, where the keys represent the names of instance variables to create

{}
Source code in dynamite_nsm/services/base/config.py
def __init__(self, config_data: Dict, name: str, verbose: Optional[bool] = False, stdout: Optional[bool] = True,
             **extract_tokens: Dict):
    """Work with YAML based configuration files

    Args:
        config_data: Configuration data dictionary
        name: The name of the configuration
        verbose: Include detailed debug messages
        stdout: Print output to console
        **extract_tokens: A dictionary object, where the keys represent the names of instance variables to create
        if the path to that variable exists. Paths are given using dot notation or as a Tuple.
    """
    super().__init__(config_data, name, verbose, stdout)
    if not utilities.is_setup():
        raise exceptions.DynamiteNotSetupError()
    self.config_data = config_data
    self.extract_tokens = extract_tokens
    log_level = logging.INFO
    if verbose:
        log_level = logging.DEBUG
    self.stdout = stdout
    self.verbose = verbose
    self.logger = get_logger(str(name), level=log_level, stdout=stdout)

commit(self, out_file_path=None, backup_directory=None, top_text=None)

Write out an updated configuration file, and optionally backup the old one.

Parameters:

Name Type Description Default
out_file_path Optional[str]

The path to the output file; if none given overwrites existing

None
backup_directory Optional[str]

The path to the backup directory

None
top_text Optional[str]

The text to be appended at the top of the config file (typically used for YAML version header)

None

Returns:

Type Description
None

None

Source code in dynamite_nsm/services/base/config.py
def commit(self, out_file_path: Optional[str] = None, backup_directory: Optional[str] = None,
           top_text: Optional[str] = None) -> None:
    """Write out an updated configuration file, and optionally backup the old one.
    Args:
        out_file_path: The path to the output file; if none given overwrites existing
        backup_directory: The path to the backup directory
        top_text: The text to be appended at the top of the config file (typically used for YAML version header)
    Returns:
        None
    """
    out_file_name = os.path.basename(out_file_path)
    backup_file_name = out_file_name + '.backup'

    def update_dict_from_path(path, value) -> None:
        """Update the internal YAML dictionary object with the new values from our config
        Args:
            path: A tuple representing each level of a nested path in the yaml document ('vars', 'address-groups', 'HOME_NET') = /vars/address-groups/HOME_NET
            value: The new value
        Returns:
             None
        """
        partial_config_data = self.config_data
        if len(path) > 1:
            for i in range(0, len(path) - 1):
                k = path[i]
                if isinstance(partial_config_data, dict):
                    partial_config_data = partial_config_data[k]
                elif isinstance(partial_config_data, list):
                    for list_entry in partial_config_data:
                        if isinstance(list_entry, dict):
                            if k in list_entry.keys():
                                partial_config_data = list_entry[k]
                else:
                    break
        if value is None:
            return
        partial_config_data.update({path[-1]: value})

    # Backup old configuration first
    if backup_directory:
        utilities.backup_configuration_file(out_file_path, backup_directory,
                                            destination_file_prefix=backup_file_name)

    for k, v in vars(self).items():
        if k not in self.extract_tokens:
            continue
        token_path = self.extract_tokens[k]
        update_dict_from_path(token_path, v)
    try:
        with open(out_file_path, 'w') as config_yaml_f:
            if top_text:
                config_yaml_f.write(f'{top_text}\n')
            try:
                dump(self.config_data, config_yaml_f, default_flow_style=False, Dumper=NoAliasDumper)
            except RecursionError:
                dump(self.config_data, config_yaml_f, default_flow_style=False)
        if utilities.is_root():
            utilities.set_ownership_of_file(out_file_path)
    except IOError:
        raise exceptions.WriteConfigError('An error occurred while writing the configuration file to disk.')
    self.logger.warning('Configuration updated. Restart this service to apply.')

get_printable_config(self, pretty_print=False)

Get the configuration as a dictionary object

Parameters:

Name Type Description Default
pretty_print Optional[bool]

Print the log entry in a nice tabular view

False

Returns:

Type Description
str

A dictionary of config keys and values

Source code in dynamite_nsm/services/base/config.py
def get_printable_config(self, pretty_print: Optional[bool] = False) -> str:
    """
    Get the configuration as a dictionary object
    Args:
        pretty_print: Print the log entry in a nice tabular view
    Returns:
        A dictionary of config keys and values
    """
    reserved_keywords = ['logger', 'config_data', 'config_data_raw', 'extract_tokens']
    variables = {}
    for var in vars(self):
        if var.startswith('_'):
            continue
        elif var in reserved_keywords:
            continue
        variables[var] = getattr(self, var)
    if pretty_print:
        table = [['Config Option', 'Value']]
        table.extend([(label, value) for label, value in variables.items()])
        return tabulate(table, tablefmt='fancy_grid')
    return json.dumps(variables, indent=1)

parse_yaml_file(self)

Parse the yaml file.

Returns:

Type Description
None

None

Source code in dynamite_nsm/services/base/config.py
def parse_yaml_file(self) -> None:
    """
    Parse the yaml file.
    Returns:
        None
    """

    def set_instance_var_from_token(variable_name: str, data: Union[Dict, List]):
        """Given a variable name, and data; create an instance variable (at parse-time) of that name
        Args:
            variable_name: The name of the instance variable to update
            data: The parsed yaml object
        Returns:
             True if successfully located
        """
        if variable_name not in self.extract_tokens.keys():
            return False
        key_path = self.extract_tokens[variable_name]
        value = data
        for k in key_path:
            if isinstance(value, dict):
                try:
                    value = value[k]
                except KeyError:
                    continue
            elif isinstance(value, list):
                for list_entry in value:
                    if isinstance(list_entry, dict):
                        if k in list_entry.keys():
                            value = list_entry[k]
            else:
                break
        setattr(self, var_name, value)
        return True

    for var_name in vars(self).keys():
        set_instance_var_from_token(variable_name=var_name, data=self.config_data)