From 3c5a76ab2fd9198efcbc2df3a10ef3c237858924 Mon Sep 17 00:00:00 2001 From: Frank Brehm Date: Fri, 13 Oct 2023 14:46:08 +0200 Subject: [PATCH] Moving some methods into mixin module lib/cr_tf/handler/first.py --- lib/cr_tf/handler/__init__.py | 155 +-------------------------- lib/cr_tf/handler/first.py | 195 ++++++++++++++++++++++++++++++++++ 2 files changed, 200 insertions(+), 150 deletions(-) create mode 100644 lib/cr_tf/handler/first.py diff --git a/lib/cr_tf/handler/__init__.py b/lib/cr_tf/handler/__init__.py index af134c2..e7b13be 100644 --- a/lib/cr_tf/handler/__init__.py +++ b/lib/cr_tf/handler/__init__.py @@ -34,7 +34,7 @@ import yaml import six from fb_tools.common import pp, to_bool, to_str, RE_DOT_AT_END -from fb_tools.errors import HandlerError, ExpectedHandlerError, CommandNotFoundError +from fb_tools.errors import HandlerError, ExpectedHandlerError from fb_tools.handling_obj import HandlingObject, CalledProcessError from fb_tools.handler import BaseHandler @@ -42,26 +42,21 @@ from fb_vmware.errors import VSphereExpectedError from fb_vmware.config import VSPhereConfigInfo from fb_vmware.connect import VsphereConnection -from fb_pdnstools.server import PowerDNSServer -from fb_pdnstools.errors import PowerDNSHandlerError - # Own modules +from .first import CrTfHandlerFirstMixin + from .. import MIN_VERSION_TERRAFORM, MAX_VERSION_TERRAFORM from .. import MIN_VERSION_VSPHERE_PROVIDER from ..errors import AbortExecution -from ..config import CrTfConfiguration - from ..terraform.vm import TerraformVm -from ..terraform.disk import TerraformDisk - # from ..tools import password_input from ..xlate import XLATOR -__version__ = '3.9.1' +__version__ = '3.9.2' LOG = logging.getLogger(__name__) _ = XLATOR.gettext @@ -69,7 +64,7 @@ ngettext = XLATOR.ngettext # ============================================================================= -class CreateTerraformHandler(BaseHandler): +class CreateTerraformHandler(BaseHandler, CrTfHandlerFirstMixin): """ A handler class for creating the terraform environment """ @@ -317,108 +312,6 @@ class CreateTerraformHandler(BaseHandler): cls.tz = pytz.timezone(tz_name) cls.tz_name = tz_name - # ------------------------------------------------------------------------- - def incr_verbosity(self, diff=1): - - new_verbose = self.verbose + int(diff) - if new_verbose < 0: - new_verbose = 0 - self.verbose = new_verbose - - if self.pdns: - self.pdns.verbose = self.verbose - - for vname in self.vsphere: - self.vsphere[vname].verbose = self.verbose - - # ------------------------------------------------------------------------- - def init_handlers(self): - - if not self.config: - msg = _("No configuration given before initialisation of handlers.") - raise HandlerError(msg) - - if not isinstance(self.config, CrTfConfiguration): - raise HandlerError(_( - "{n} is not a {e}-instance, but a {w}-instance instead.").format( - n='self.config', e='CrTfConfiguration', w=self.config.__class__.__name__)) - - TerraformDisk.default_size = self.config.disk_size - TerraformDisk.min_size_gb = self.config.disk_min_size - TerraformDisk.max_size_gb = self.config.disk_max_size - - TerraformVm.min_rootdisk_size = self.config.root_min_size - TerraformVm.max_rootdisk_size = self.config.root_max_size - - LOG.info(_("Initialize some additional handlers.")) - - self.terraform_cmd = self.get_command('terraform', quiet=True) - if not self.terraform_cmd: - raise CommandNotFoundError('terraform') - self.check_terraform_version() - - self.pdns = PowerDNSServer( - appname=self.appname, verbose=self.verbose, base_dir=self.base_dir, - master_server=self.config.pdns_master_server, - port=self.config.pdns_api_port, key=self.config.pdns_api_key, - use_https=self.config.pdns_api_use_https, path_prefix=self.config.pdns_api_path_prefix, - simulate=self.simulate, force=self.force, initialized=True, - ) - - if not self.config.no_pdns: - try: - api_version = self.pdns.get_api_server_version() # noqa - except (PowerDNSHandlerError, ConnectionError) as e: - msg = "{c}: {e}".format(c=e.__class__.__name__, e=str(e)) - raise ExpectedHandlerError(msg) - - # ------------------------------------------------------------------------- - def check_terraform_version(self): - """ Checking, that the called terraform has a minimum version.""" - - tf_timeout = 10 - - got_tf_version = None - LOG.info(_("Checking the terraform version ...")) - - cmd = [str(self.terraform_cmd), 'version'] - cmd_str = ' '.join(cmd) - LOG.debug(_("Executing {!r} ...").format(cmd_str)) - result = self.run( - cmd, may_simulate=False, timeout=tf_timeout, stdout=PIPE, stderr=PIPE, check=True) - LOG.debug(_("Completed process:") + "\n" + str(result)) - - if not result.stdout: - msg = _("No output on command {!r}.").format(cmd_str) - raise ExpectedHandlerError(msg) - lines = result.stdout.splitlines() - - if self.verbose > 2: - LOG.debug(_("First line:") + '\n' + lines[0]) - match = self.re_tf_version.search(lines[0]) - if not match: - msg = _("Could not evaluate version output of terraform:") + '\n' + result.stdout - raise ExpectedHandlerError(msg) - - got_tf_version = LooseVersion(match.group(1)) - LOG.info(_("Terraform version: {!r}.").format(str(got_tf_version))) - - if self.min_version_terraform: - LOG.debug(_("Checking for {o}{m!r} ...").format( - o='>=', m=str(self.min_version_terraform))) - if got_tf_version < self.min_version_terraform: - msg = _("Invalid version {c!r} of terraform, expected {o}{m!r}.").format( - c=str(got_tf_version), o='>=', m=str(self.min_version_terraform)) - raise ExpectedHandlerError(msg) - - if self.max_version_terraform: - LOG.debug(_("Checking for {o}{m!r} ...").format( - o='<=', m=str(self.max_version_terraform))) - if got_tf_version > self.max_version_terraform: - msg = _("Invalid version {c!r} of terraform, expected {o}{m!r}.").format( - c=str(got_tf_version), o='<=', m=str(self.max_version_terraform)) - raise ExpectedHandlerError(msg) - # ------------------------------------------------------------------------- def __del__(self): """Destructor.""" @@ -431,31 +324,6 @@ class CreateTerraformHandler(BaseHandler): if self.vsphere: self.vsphere = None - # ------------------------------------------------------------------------- - def first_call(self, yaml_file): - """First steps until reading the YAML file.""" - - if not self.initialized: - raise HandlerError(_("{}-object not initialized.").format(self.__class__.__name__)) - - try: - - self.exec_init_run() - - LOG.info(_("Go ahead...")) - - self.exec_read_yaml(yaml_file) - - print() - LOG.info(_("Initialising VSPhere handlers.")) - self.init_vspheres(yaml_file) - - return True - - except AbortExecution as e: - LOG.warn(str(e)) - return False - # ------------------------------------------------------------------------- def __call__(self, yaml_file): """Executing the underlying action.""" @@ -553,19 +421,6 @@ class CreateTerraformHandler(BaseHandler): print() - # -------------------------------------------------------------------------· - def exec_init_run(self): - - if self.stop_at_step == 'init': - self.incr_verbosity() - - if self.verbose > 2: - LOG.debug(_("Current {} object:").format(self.__class__.__name__) + "\n" + str(self)) - - LOG.info(_("Finished step {!r}.").format('init')) - if self.stop_at_step == 'init': - raise AbortExecution('init') - # -------------------------------------------------------------------------· def exec_read_yaml(self, yaml_file): diff --git a/lib/cr_tf/handler/first.py b/lib/cr_tf/handler/first.py new file mode 100644 index 0000000..b8bc161 --- /dev/null +++ b/lib/cr_tf/handler/first.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +@author: Frank Brehm +@contact: frank.brehm@pixelpark.com +@copyright: © 2023 by Frank Brehm, Berlin +@summary: A mixin for the handler module for early used methods. +""" +from __future__ import absolute_import, print_function + +# Standard module +import logging + +from distutils.version import LooseVersion + +from subprocess import PIPE + +# Third party modules +from fb_tools.errors import HandlerError, ExpectedHandlerError, CommandNotFoundError + +from fb_pdnstools.server import PowerDNSServer +from fb_pdnstools.errors import PowerDNSHandlerError + +# Own modules +from ..config import CrTfConfiguration + +from ..errors import AbortExecution + +from ..terraform.vm import TerraformVm + +from ..terraform.disk import TerraformDisk + +from ..xlate import XLATOR + +__version__ = '0.1.0' +LOG = logging.getLogger(__name__) + +_ = XLATOR.gettext +ngettext = XLATOR.ngettext + + +# ============================================================================= +class CrTfHandlerFirstMixin(): + """A Mixin module for the handler module for early used methods.""" + + # ------------------------------------------------------------------------- + def incr_verbosity(self, diff=1): + + new_verbose = self.verbose + int(diff) + if new_verbose < 0: + new_verbose = 0 + self.verbose = new_verbose + + if self.pdns: + self.pdns.verbose = self.verbose + + for vname in self.vsphere: + self.vsphere[vname].verbose = self.verbose + + # ------------------------------------------------------------------------- + def init_handlers(self): + + if not self.config: + msg = _("No configuration given before initialisation of handlers.") + raise HandlerError(msg) + + if not isinstance(self.config, CrTfConfiguration): + raise HandlerError(_( + "{n} is not a {e}-instance, but a {w}-instance instead.").format( + n='self.config', e='CrTfConfiguration', w=self.config.__class__.__name__)) + + TerraformDisk.default_size = self.config.disk_size + TerraformDisk.min_size_gb = self.config.disk_min_size + TerraformDisk.max_size_gb = self.config.disk_max_size + + TerraformVm.min_rootdisk_size = self.config.root_min_size + TerraformVm.max_rootdisk_size = self.config.root_max_size + + LOG.info(_("Initialize some additional handlers.")) + + self.terraform_cmd = self.get_command('terraform', quiet=True) + if not self.terraform_cmd: + raise CommandNotFoundError('terraform') + self.check_terraform_version() + + self.pdns = PowerDNSServer( + appname=self.appname, verbose=self.verbose, base_dir=self.base_dir, + master_server=self.config.pdns_master_server, + port=self.config.pdns_api_port, key=self.config.pdns_api_key, + use_https=self.config.pdns_api_use_https, path_prefix=self.config.pdns_api_path_prefix, + simulate=self.simulate, force=self.force, initialized=True, + ) + + if not self.config.no_pdns: + try: + api_version = self.pdns.get_api_server_version() # noqa + except (PowerDNSHandlerError, ConnectionError) as e: + msg = "{c}: {e}".format(c=e.__class__.__name__, e=str(e)) + raise ExpectedHandlerError(msg) + + # ------------------------------------------------------------------------- + def check_terraform_version(self): + """ Checking, that the called terraform has a minimum version.""" + + tf_timeout = 10 + + got_tf_version = None + LOG.info(_("Checking the terraform version ...")) + + cmd = [str(self.terraform_cmd), 'version'] + cmd_str = ' '.join(cmd) + LOG.debug(_("Executing {!r} ...").format(cmd_str)) + result = self.run( + cmd, may_simulate=False, timeout=tf_timeout, stdout=PIPE, stderr=PIPE, check=True) + LOG.debug(_("Completed process:") + "\n" + str(result)) + + if not result.stdout: + msg = _("No output on command {!r}.").format(cmd_str) + raise ExpectedHandlerError(msg) + lines = result.stdout.splitlines() + + if self.verbose > 2: + LOG.debug(_("First line:") + '\n' + lines[0]) + match = self.re_tf_version.search(lines[0]) + if not match: + msg = _("Could not evaluate version output of terraform:") + '\n' + result.stdout + raise ExpectedHandlerError(msg) + + got_tf_version = LooseVersion(match.group(1)) + LOG.info(_("Terraform version: {!r}.").format(str(got_tf_version))) + + if self.min_version_terraform: + LOG.debug(_("Checking for {o}{m!r} ...").format( + o='>=', m=str(self.min_version_terraform))) + if got_tf_version < self.min_version_terraform: + msg = _("Invalid version {c!r} of terraform, expected {o}{m!r}.").format( + c=str(got_tf_version), o='>=', m=str(self.min_version_terraform)) + raise ExpectedHandlerError(msg) + + if self.max_version_terraform: + LOG.debug(_("Checking for {o}{m!r} ...").format( + o='<=', m=str(self.max_version_terraform))) + if got_tf_version > self.max_version_terraform: + msg = _("Invalid version {c!r} of terraform, expected {o}{m!r}.").format( + c=str(got_tf_version), o='<=', m=str(self.max_version_terraform)) + raise ExpectedHandlerError(msg) + + # ------------------------------------------------------------------------- + def first_call(self, yaml_file): + """First steps until reading the YAML file.""" + + if not self.initialized: + raise HandlerError(_("{}-object not initialized.").format(self.__class__.__name__)) + + try: + + self.exec_init_run() + + LOG.info(_("Go ahead...")) + + self.exec_read_yaml(yaml_file) + + print() + LOG.info(_("Initialising VSPhere handlers.")) + self.init_vspheres(yaml_file) + + return True + + except AbortExecution as e: + LOG.warn(str(e)) + return False + + # -------------------------------------------------------------------------· + def exec_init_run(self): + + if self.stop_at_step == 'init': + self.incr_verbosity() + + if self.verbose > 2: + LOG.debug(_("Current {} object:").format(self.__class__.__name__) + "\n" + str(self)) + + LOG.info(_("Finished step {!r}.").format('init')) + if self.stop_at_step == 'init': + raise AbortExecution('init') + + +# ============================================================================= + +if __name__ == "__main__": + + pass + +# ============================================================================= + +# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 list -- 2.39.5