From 4a645ce6e365e959c13fa516a517bfea7485795c Mon Sep 17 00:00:00 2001 From: Frank Brehm Date: Tue, 29 Mar 2022 18:47:44 +0200 Subject: [PATCH] Refactoring lib/pp_admintools/pdns_app.py --- lib/pp_admintools/pdns_app.py | 304 ++++++++++++---------------------- 1 file changed, 102 insertions(+), 202 deletions(-) diff --git a/lib/pp_admintools/pdns_app.py b/lib/pp_admintools/pdns_app.py index 61f0143..236df5b 100644 --- a/lib/pp_admintools/pdns_app.py +++ b/lib/pp_admintools/pdns_app.py @@ -27,99 +27,64 @@ from fb_pdnstools.zone import PowerDNSZone from fb_pdnstools.server import PowerDNSServer from fb_pdnstools.errors import PDNSApiNotFoundError from fb_pdnstools.errors import PDNSApiValidationError +from fb_tools.xlate import format_list -from fb_tools.errors import FbCfgAppError +from . import __version__ as GLOBAL_VERSION -from fb_tools.cfg_app import FbConfigApplication +from .argparse_actions import PortOptionAction, TimeoutOptionAction + +from .mail_app import MailAppError, BaseMailApplication + +from .pdns_config import PdnsConfigError, PdnsConfiguration, LIBRARY_NAME from .xlate import XLATOR -__version__ = '0.8.0' +__version__ = '0.9.0' LOG = logging.getLogger(__name__) -_LIBRARY_NAME = "pp-pdns-api-client" _ = XLATOR.gettext # ============================================================================= -class PpPDNSAppError(FbCfgAppError): +class PpPDNSAppError(MailAppError): """Base error class for all exceptions happened during execution this configured application""" pass # ============================================================================= -class PpPDNSApplication(FbConfigApplication): +class PpPDNSApplication(BaseMailApplication): """ Class for configured application objects related to PowerDNS. """ - api_keys = { - 'global': "6d1b08e2-59c6-49e7-9e48-039ade102016", - 'public': "cf0fb928-2a73-49ec-86c2-36e85c9672ff", - 'local': "d94b183a-c50d-47f7-b338-496090af1577" - } - - api_hosts = { - 'global': "dnsmaster.pp-dns.com", - 'public': "dnsmaster-public.pixelpark.com", - 'local': "dnsmaster-local.pixelpark.com" - } - - default_api_port = 8081 - default_api_servername = "localhost" - default_timeout = 20 - # ------------------------------------------------------------------------- def __init__( - self, appname=None, verbose=0, version=__version__, base_dir=None, - initialized=None, usage=None, description=None, + self, appname=None, verbose=0, version=GLOBAL_VERSION, base_dir=None, + cfg_class=PdnsConfiguration, initialized=False, usage=None, description=None, argparse_epilog=None, argparse_prefix_chars='-', env_prefix=None, - cfg_dir=None, cfg_stems=None, cfg_encoding='utf-8', need_config_file=False, - environment='global'): + instance=None): + + if instance: + self._instance = instance + else: + self._instance = PdnsConfiguration.default_pdns_instance - self._api_key = self.api_keys['global'] - self._api_host = self.api_hosts['global'] - self._api_port = self.default_api_port - self._api_servername = self.default_api_servername + self._api_key = None + self._api_host = None + self._api_port = None + self._api_servername = None self._api_server_version = 'unknown' - self._user_agent = '{}/{}'.format(_LIBRARY_NAME, self.version) - self._timeout = self.default_timeout self.local_addresses = [] self.pdns = None - self._environment = 'global' - if environment != 'global': - self.environment = environment - - stems = [] - if cfg_stems: - if isinstance(cfg_stems, list): - for stem in cfg_stems: - s = str(stem).strip() - if not s: - msg = _("Invalid configuration stem {!r} given.").format(stem) - raise PpPDNSAppError(msg) - stems.append(s) - else: - s = str(cfg_stems).strip() - if not s: - msg = _("Invalid configuration stem {!r} given.").format(cfg_stems) - raise PpPDNSAppError(msg) - stems.append(s) - else: - stems = [self.appname] - if 'pdns-api' not in stems: - stems.insert(0, 'pdns-api') - super(PpPDNSApplication, self).__init__( appname=appname, verbose=verbose, version=version, base_dir=base_dir, - initialized=False, usage=usage, description=description, + description=description, cfg_class=cfg_class, initialized=False, argparse_epilog=argparse_epilog, argparse_prefix_chars=argparse_prefix_chars, - env_prefix=env_prefix, cfg_dir=cfg_dir, cfg_stems=stems, - cfg_encoding=cfg_encoding, need_config_file=need_config_file, + env_prefix=env_prefix, ) for interface, snics in psutil.net_if_addrs().items(): @@ -129,7 +94,11 @@ class PpPDNSApplication(FbConfigApplication): if addr not in self.local_addresses: self.local_addresses.append(addr) - self._user_agent = '{}/{}'.format(_LIBRARY_NAME, self.version) + if not self.cfg: + msg=_("Configuration not available.") + raise PpPDNSAppError(msg) + + self.eval_instance(instance) # ----------------------------------------------------------- @property @@ -188,45 +157,38 @@ class PpPDNSApplication(FbConfigApplication): # ----------------------------------------------------------- @property - def user_agent(self): - "The name of the user agent used in API calls." - return self._user_agent + def instance(self): + "The name of the PowerDNS instance." + return self._instance - @user_agent.setter - def user_agent(self, value): - if value is None or str(value).strip() == '': - raise PpPDNSAppError(_("Invalid user agent {!r} given.").format(value)) - self._user_agent = str(value).strip() + @instance.setter + def instance(self, value): + if value is None: + raise PpPDNSAppError(_("Invalid instance {!r} given.").format(None)) + v = str(value).strip().lower() + if v not in self.api_keys.keys(): + raise PpPDNSAppError(_("Invalid instance {!r} given.").format(value)) - # ----------------------------------------------------------- - @property - def timeout(self): - "The timeout in seconds on requesting the PowerDNS API." - return self._timeout + self.eval_instance(v) - @timeout.setter - def timeout(self, value): - v = int(value) - if v < 1: - raise PpPDNSAppError(_("Invalid timeout {!r} given.").format(value)) - self._timeout = v + # ------------------------------------------------------------------------- + def eval_instance(self, inst_name): - # ----------------------------------------------------------- - @property - def environment(self): - "The name of the PowerDNS environment." - return self._environment + if not self.cfg: + msg = _("Configuration not available.") + raise PpPDNSAppError(msg) - @environment.setter - def environment(self, value): - if value is None: - raise PpPDNSAppError(_("Invalid environment {!r} given.").format(None)) - v = str(value).strip().lower() - if v not in self.api_keys.keys(): - raise PpPDNSAppError(_("Invalid environment {!r} given.").format(value)) - self._environment = v - self._api_host = self.api_hosts[v] - self._api_key = self.api_keys[v] + if inst_name not in self.cfg.pdns_api_instances: + msg = _("PDNS instance {!r} is not configured.").format(inst_name) + raise PpPDNSAppError(msg) + + inst = self.cfg.pdns_api_instances[inst_name] + + self._instance = inst_name + self.api_host = inst['host'] + self.api_port = inst['port'] + self.api_key = inst['key'] + self.api_servername = inst['servername'] # ------------------------------------------------------------------------- def as_dict(self, short=True): @@ -242,17 +204,10 @@ class PpPDNSApplication(FbConfigApplication): res = super(PpPDNSApplication, self).as_dict(short=short) res['api_host'] = self.api_host - res['api_hosts'] = copy.copy(self.api_hosts) res['api_key'] = self.api_key - res['api_keys'] = copy.copy(self.api_keys) res['api_port'] = self.api_port res['api_servername'] = self.api_servername - res['default_api_port'] = self.default_api_port - res['default_api_servername'] = self.default_api_servername - res['default_timeout'] = self.default_timeout - res['environment'] = self.environment - res['timeout'] = self.timeout - res['user_agent'] = self.user_agent + res['instance'] = self.instance res['api_server_version'] = self.api_server_version return res @@ -269,52 +224,53 @@ class PpPDNSApplication(FbConfigApplication): super(PpPDNSApplication, self).init_arg_parser() pdns_group = self.arg_parser.add_argument_group(_('PowerDNS API options')) - env_group = pdns_group.add_mutually_exclusive_group() + inst_group = pdns_group.add_mutually_exclusive_group() - envs = [] - for env in self.api_keys.keys(): - envs.append(str(env)) - envs.sort() + insts = PdnsConfiguration.valid_pdns_api_instances + inst_list = format_list(insts, do_repr=True) + default_timeout = PdnsConfiguration.default_pdns_timeout - env_group.add_argument( - '-E', '--env', '--environment', - metavar=_("ENVIRONMENT"), choices=envs, dest="env", + inst_group.add_argument( + '-I', '--inst', '--instance', + metavar=_("INSTANCE"), choices=envs, dest="inst", help=_( - "Select, which PowerDNS environment to use. " - "Valid values: {v}, default: {d!r}.").format( - v=', '.join(map(lambda x: repr(x), envs)), d='global') + "Select, which PowerDNS instance to use. Valid values: {v}, " + "default: {d!r}.").format(v=inst_list, d=self.instance), ) - env_group.add_argument( + inst_group.add_argument( '-G', '--global', - action='store_true', dest="env_global", - help=_("Using the {!r} PowerDNS environment.").format('global'), + action='store_true', dest="inst_global", + help=_("Using the {!r} PowerDNS instance.").format('global'), ) - env_group.add_argument( + inst_group.add_argument( '-L', '--local', - action='store_true', dest="env_local", - help=_("Using the {!r} PowerDNS environment.").format('local'), + action='store_true', dest="inst_local", + help=_("Using the {!r} PowerDNS instance.").format('local'), ) - env_group.add_argument( + inst_group.add_argument( '-P', '--public', - action='store_true', dest="env_public", - help=_("Using the {!r} PowerDNS environment.").format('public'), + action='store_true', dest="inst_public", + help=_("Using the {!r} PowerDNS instance.").format('public'), ) pdns_group.add_argument( '-p', '--port', - metavar=_("PORT"), type=int, dest='api_port', default=self.default_api_port, + metavar=_("PORT"), type=int, dest='api_port', + default=PdnsConfiguration.default_pdns_api_port, + what="PowerDNS API", action=PortOptionAction, help=_("Which port to connect to PowerDNS API, default: {}.").format( - self.default_api_port), + PdnsConfiguration.default_pdns_api_port), ) pdns_group.add_argument( '-t', '--timeout', - metavar=_("SECS"), type=int, dest='timeout', default=self.default_timeout, + metavar=_("SECS"), type=int, dest='timeout', default=default_timeout, + what=_("PowerDNS API access"), action=TimeoutOptionAction, help=_("The timeout in seconds to request the PowerDNS API, default: {}.").format( - self.default_timeout), + default_timeout), ) # ------------------------------------------------------------------------- @@ -324,80 +280,6 @@ class PpPDNSApplication(FbConfigApplication): the command line parameters. """ - if self.args.env: - self.environment = self.args.env - elif self.args.env_global: - self.environment = 'global' - elif self.args.env_local: - self.environment = 'local' - elif self.args.env_public: - self.environment = 'public' - - if self.args.api_port: - self.api_port = self.args.api_port - - if self.args.timeout: - self.timeout = self.args.timeout - - # ------------------------------------------------------------------------- - def perform_config(self): - - super(PpPDNSApplication, self).perform_config() - - for section_name in self.cfg.keys(): - - if self.verbose > 3: - LOG.debug(_("Checking config section {!r} ...").format(section_name)) - - section = self.cfg[section_name] - - if section_name.lower() in ( - 'powerdns-api', 'powerdns_api', 'powerdnsapi', - 'pdns-api', 'pdns_api', 'pdnsapi'): - self.set_cfg_api_options(section, section_name) - - # ------------------------------------------------------------------------- - def set_cfg_api_options(self, section, section_name): - - if self.verbose > 2: - LOG.debug( - _("Evaluating config section {!r}:").format(section_name) + '\n' + pp(section)) - - if 'environment' in section: - v = section['environment'].strip().lower() - if v not in self.api_hosts: - LOG.error(_("Wrong environment {!r} found in configuration.").format( - section['environment'])) - self.config_has_errors = True - else: - self.environment = v - - if 'host' in section: - v = section['host'] - host = v.lower().strip() - if host: - self.api_host = host - - if 'port' in section: - try: - port = int(section['port']) - if port <= 0 or port > 2**16: - raise ValueError( - _("A port must be greater than 0 and less than {}.").format(2**16)) - except (TypeError, ValueError) as e: - LOG.error(_("Wrong port number {p!r} in configuration section {s!r}: {e}").format( - p=section['port'], s=section_name, e=e)) - self.config_has_errors = True - else: - self.api_port = port - - if 'server_id' in section and section['server_id'].strip(): - self.api_servername = section['server_id'].strip().lower() - - if 'key' in section: - key = section['key'].strip() - self.api_key = key - # ------------------------------------------------------------------------- def _check_path_config(self, section, section_name, key, class_prop, absolute=True, desc=None): @@ -442,6 +324,23 @@ class PpPDNSApplication(FbConfigApplication): if self.verbose > 1: LOG.debug(_("Executing {} ...").format('post_init()')) + super(PpPDNSApplication, self).post_init() + + if self.args.inst: + self.instance = self.args.inst + elif self.args.inst_global: + self.instance = 'global' + elif self.args.inst_local: + self.instance = 'local' + elif self.args.inst_public: + self.instance = 'public' + + if self.args.api_port: + self.api_port = self.args.api_port + + if self.args.timeout: + self.cfg.pdns_timeout = self.args.timeout + self.pdns = PowerDNSServer( appname=self.appname, verbose=self.verbose, base_dir=self.base_dir, master_server=self.api_host, port=self.api_port, @@ -450,8 +349,6 @@ class PpPDNSApplication(FbConfigApplication): ) self.pdns.initialized = True - self.initialized = True - # ------------------------------------------------------------------------- def pre_run(self): """ @@ -490,6 +387,9 @@ class PpPDNSApplication(FbConfigApplication): if self.verbose > 1: LOG.debug(_("Executing {} ...").format('post_run()')) + if self.pdns: + self.pdns = None + # ------------------------------------------------------------------------- def get_api_server_version(self): -- 2.39.5