From 0927a2b4051ae2067e5f855e34c84b83560bd629 Mon Sep 17 00:00:00 2001 From: Frank Brehm Date: Fri, 3 Sep 2021 17:30:35 +0200 Subject: [PATCH] Input of failing information * New functions password_input_getch() and password_input() * Asking for VSphere user and password and for PowerDNS API key, if not configured * Don't write those information into terraform variables, if they are not configured --- lib/cr_tf/handler.py | 148 +++++++++++++++++++++++++++++++++---------- 1 file changed, 113 insertions(+), 35 deletions(-) diff --git a/lib/cr_tf/handler.py b/lib/cr_tf/handler.py index d656820..8f465b7 100644 --- a/lib/cr_tf/handler.py +++ b/lib/cr_tf/handler.py @@ -28,6 +28,13 @@ from distutils.version import LooseVersion from operator import attrgetter +HAS_GETCH = False +try: + import getch + HAS_GETCH = True +except ImportError: + pass + # Third party modules import pytz import yaml @@ -60,13 +67,54 @@ from .terraform.disk import TerraformDisk from .xlate import XLATOR -__version__ = '3.4.8' +__version__ = '3.5.0' LOG = logging.getLogger(__name__) _ = XLATOR.gettext ngettext = XLATOR.ngettext +# ============================================================================= +def password_input_getch(prompt='', fill_char='*', max_len=64): + p_s = '' + proxy_string = ' ' * 64 + + fch = ' ' + if len(fill_char) >= 1: + fch = fill_char[0] + + while True: + + print('\r' + proxy_string, end='', flush=True) + print('\r' + prompt, end='', flush=True) + + c = getch.getch() + if c == b'\r' or c == b'\n': + break + elif c == b'\x08': + if len(p_s): + p_s = p_s[:-1] + continue + + p_s += to_str(c) + if len(p_s) >= max_len: + break + + print('', flush=True) + return p_s + + +# ============================================================================= +def password_input(prompt='', fill_char='*', max_len=64): + + if HAS_GETCH: + return password_input_getch(prompt=prompt, fill_char=fill_char, max_len=max_len) + + import getpass + + return getpass.getpass(prompt=prompt) + + # ============================================================================= class AbortExecution(ExpectedHandlerError): """Indicating an abort of the execution.""" @@ -367,10 +415,20 @@ class CreateTerraformHandler(BaseHandler): raise CommandNotFoundError('terraform') self.check_terraform_version() + pdns_api_key = self.config.pdns_api_key + if not pdns_api_key: + msg = '\n' + _("Please input the {}:").format(self.colored( + 'PowerDNS API key', 'AQUA')) + print(msg) + pdns_api_key = password_input(prompt='Key: ') + if pdns_api_key == '': + msg = _("No {} given.").format('PowerDNS API key') + raise ExpectedHandlerError(msg) + 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, + port=self.config.pdns_api_port, key=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, ) @@ -689,6 +747,27 @@ class CreateTerraformHandler(BaseHandler): msg = _("VSPhere {!r} not defined in configuration.").format(vname) raise ExpectedHandlerError(msg) + vsphere_user = self.config.vsphere[vname].user + vsphere_password = self.config.vsphere[vname].password + + if not vsphere_user: + msg = '\n' + _("Please input the {}:").format(self.colored( + _('vSphere user name'), 'AQUA')) + print(msg) + vsphere_user = input(_('vSphere user name') + ': ') + if vsphere_user == '': + msg = _("No {} given.").format(_('vSphere user name')) + raise ExpectedHandlerError(msg) + + if not vsphere_password: + msg = '\n' + _("Please input the {}:").format(self.colored( + _('vSphere user password'), 'AQUA')) + print(msg) + vsphere_password = password_input(prompt=(_('vSphere user name') + ': ')) + if vsphere_password == '': + msg = _("No {} given.").format(_('vSphere user password')) + raise ExpectedHandlerError(msg) + try: params = { 'appname': self.appname, @@ -696,8 +775,8 @@ class CreateTerraformHandler(BaseHandler): 'base_dir': self.base_dir, 'host': self.config.vsphere[vname].host, 'port': self.config.vsphere[vname].port, - 'user': self.config.vsphere[vname].user, - 'password': self.config.vsphere[vname].password, + 'user': vsphere_user, + 'password': vsphere_password, 'dc': self.config.vsphere[vname].dc, 'simulate': self.simulate, 'force': self.force, @@ -2150,26 +2229,25 @@ class CreateTerraformHandler(BaseHandler): fh.write(content) os.chmod('terraform.tfvars', self.std_file_permissions) - tpl = textwrap.dedent('''\ - # Private sensible information. Please keep this file secret. - - vsphere_user = "{u}" - vsphere_password = "{p}" - pdns_api_key = "{a}" - - ''') - - content = tpl.format(u=vs_user, p=vs_pwd, a=self.config.pdns_api_key) + # Sensible stuff + if vs_user or vs_pwd: + content = '# Private sensible information. Please keep this file secret.\n\n' + if vs_user: + content += 'vsphere_user = "{}"\n.'.format(vs_user) + if vs_pwd: + content += 'vsphere_password = "{}""\n.'.format(vs_pwd) + content += '\n' - LOG.debug(_("Creating {!r} ...").format('private.auto.tfvars')) - if self.simulate: - if self.verbose: - print(content) - else: - with open('private.auto.tfvars', 'w', **self.open_opts) as fh: - fh.write(content) - os.chmod('private.auto.tfvars', self.std_secure_file_permissions) + LOG.debug(_("Creating {!r} ...").format('private.auto.tfvars')) + if self.simulate: + if self.verbose: + print(content) + else: + with open('private.auto.tfvars', 'w', **self.open_opts) as fh: + fh.write(content) + os.chmod('private.auto.tfvars', self.std_secure_file_permissions) + # File with variable declarations content = textwrap.dedent('''\ # filename: variables.tf # definition of the variables to be used in the play @@ -2854,19 +2932,19 @@ class CreateTerraformHandler(BaseHandler): LOG.debug(_("Completed process:") + "\n" + str(result)) - print() - LOG.info(_("Executing {!r} ...").format('terraform plan')) - cmd = [str(self.terraform_cmd), 'plan'] - try: - result = self.run( - cmd, may_simulate=True, timeout=tf_timeout, stdout=PIPE, stderr=PIPE, check=True) - except CalledProcessError as e: - if e.stdout: - print(self.colored("Output", 'AQUA') + ':\n' + to_str(e.stdout)) - if e.stderr: - print(self.colored("Error message", ('BOLD', 'RED')) + ':\n' + to_str(e.stderr)) - raise ExpectedHandlerError(str(e)) - LOG.debug(_("Completed process:") + "\n" + str(result)) +# print() +# LOG.info(_("Executing {!r} ...").format('terraform plan')) +# cmd = [str(self.terraform_cmd), 'plan'] +# try: +# result = self.run( +# cmd, may_simulate=True, timeout=tf_timeout, stdout=PIPE, stderr=PIPE, check=True) +# except CalledProcessError as e: +# if e.stdout: +# print(self.colored("Output", 'AQUA') + ':\n' + to_str(e.stdout)) +# if e.stderr: +# print(self.colored("Error message", ('BOLD', 'RED')) + ':\n' + to_str(e.stderr)) +# raise ExpectedHandlerError(str(e)) +# LOG.debug(_("Completed process:") + "\n" + str(result)) goto = Path(os.path.relpath(self.project_dir, self.start_dir)) -- 2.39.5