Source code for certdeploy.client.config
"""Public CertDeploy Client Config."""
import os
import re
from typing import Any
# fmt: off
from ... import (
CERTDEPLOY_CLIENT_LOGGER_NAME,
set_log_properties,
set_paramiko_log_properties,
)
# fmt: on
from ...errors import ConfigError, ConfigInvalid, ConfigInvalidPath
from .client import Config, Permissions, SFTPDConfig
from .service import DockerContainer, RCService, Script, Service, SystemdUnit
_DURATION_FACTORS = {
'w': 60 * 60 * 24 * 7,
'd': 60 * 60 * 24,
'h': 60 * 60,
'm': 60,
's': 1,
}
_DURATION_RE = re.compile(
r'\s*(?:\s*(\d+(?:\.\d+)?)([{0}]))\s*'.format(
''.join(_DURATION_FACTORS.keys()),
)
)
[docs]
class ClientConfig(Config):
"""CertDeploy client configuration.
See `certdeploy.client.config.client.Config` for details about
arguments.
"""
# This is meant to validate as much of the config as possible so that
# errors are more likely to occur while a human is looking and before
# the system is cluttered with possible causes.
def __init__(self, *args: Any, **kwargs: Any):
try:
super().__init__(*args, **kwargs)
except TypeError as err:
if 'got an unexpected keyword argument' in str(err):
raise ConfigError(f'Invalid config option: {err}') from err
raise
# Set the log files right away so that the errors produced here go to
# the right place
set_log_properties(
logger_name=CERTDEPLOY_CLIENT_LOGGER_NAME,
log_filename=self.log_filename,
log_level=self.log_level,
)
if not os.path.isdir(self.source):
raise ConfigInvalidPath('source', self.source, is_type='directory')
if not os.path.isdir(self.destination):
raise ConfigInvalidPath(
'destination',
self.destination,
is_type='directory',
)
if isinstance(self.docker_timeout, (float, int)):
DockerContainer.timeout = self.docker_timeout
if isinstance(self.init_timeout, (float, int)):
RCService.timeout = self.init_timeout
SystemdUnit.timeout = self.init_timeout
if isinstance(self.script_timeout, (float, int)):
Script.timeout = self.script_timeout
self.services = [Service.load(s) for s in self.update_services]
try:
self.sftpd_config = SFTPDConfig(**self.sftpd)
except TypeError as err:
if 'got an unexpected keyword argument' in str(err):
raise ConfigError(
f'Invalid SFTPD config option: {err}',
) from err
raise
set_paramiko_log_properties(
log_filename=self.sftpd_config.log_filename,
log_level=self.sftpd_config.log_level,
)
seconds = 0
# `null` in the config is eqivalent to 0s
if self.update_delay is not None:
matches = _DURATION_RE.findall(self.update_delay)
# something to match against but no matches is bad
if not matches:
raise ConfigInvalid('update_delay', self.update_delay)
try:
for match in matches:
seconds += float(match[0]) * _DURATION_FACTORS[match[1]]
except TypeError as err:
raise ConfigInvalid('update_delay', self.update_delay) from err
self.update_delay_seconds = int(seconds)
try:
self.permissions = Permissions(**self.file_permissions)
except TypeError as err:
if 'got an unexpected keyword argument' in str(err):
raise ConfigError(
f'Invalid Permissions config option: {err}',
) from err
raise