def __init__(self, subparsers): """Create command.""" # pylint: disable=no-member CliCommand.__init__(self, self.SUBCOMMAND, self.ACTION, subparsers.add_parser(self.ACTION)) if not DOWNSTREAM: # Upstream only args self.parser.add_argument( '--offline-files', dest='offline_files', help=_(messages.CLI_INSTALL_OFFLINE_FILES_HELP), required=False) self.parser.add_argument('--version', dest='cli_version', help=_(messages.CLI_INSTALL_VERSION_HELP), required=False) self.parser.add_argument('--home-dir', dest='home_dir', help=_(messages.ALL_INSTALL_HOME_DIR_HELP), required=False) self.parser.add_argument('--server-host', dest='server_host', help=_(messages.CLI_INSTALL_SERVER_HELP), required=False) self.parser.add_argument('--server-port', dest='server_port', help=_(messages.CLI_INSTALL_PORT_HELP), required=False) self.parser.add_argument('--advanced', dest='server_advanced', nargs='+', default=[], help=SUPPRESS, required=False)
def _do_command(self): """Install the CLI.""" # Can't use subprocess.run cause python > 3.5 cwd_abs_path = os.path.abspath(os.path.dirname(__file__)) playbook_abs_path = os.path.join(cwd_abs_path, cli.CLI_INSTALL_PLAYBOOK) ansible_command = create_ansible_command(self.args, playbook_abs_path) try: process = subprocess.Popen(ansible_command, stderr=subprocess.PIPE, stdout=subprocess.PIPE) for line in iter(process.stdout.readline, b''): format_line = line.decode('utf-8').strip('\n') print(format_line) # process.communicate performs a wait until playbooks is done stderr_data = process.communicate()[1] code = process.returncode if code == 0: print(_(messages.CLI_INSTALLATION_SUCCESSFUL)) else: print(_(messages.CLI_INSTALLATION_FAILED)) if stderr_data != b'': format_stderr = stderr_data.decode('utf-8').strip('\n') if 'WARNING' not in format_stderr: print(_(messages.INSTALL_ERROR_MESSAGE % format_stderr)) except ValueError: print(_(messages.CLI_INSTALLATION_FAILED)) except KeyboardInterrupt: print(_(messages.INSTALLATION_CANCELED))
def __init__(self, name='cli_main', usage=None, shortdesc=None, description=None): """Create main command line handler.""" self.shortdesc = shortdesc if shortdesc is not None and description is None: description = shortdesc self.parser = ArgumentParser(usage=usage, description=description) self.parser.add_argument('--version', action='version', version=VERSION) self.parser.add_argument('-v', dest='verbosity', action='count', default=0, help=_(messages.VERBOSITY_HELP)) self.subparsers = self.parser.add_subparsers(dest='subcommand') self.name = name self.args = None self.subcommands = {} self._add_subcommand(cli.SUBCOMMAND, [InstallCLICommand]) self._add_subcommand(server.SUBCOMMAND, [InstallServerCommand]) ensure_data_dir_exists() ensure_config_dir_exists()
def _validate_args(self): """Sub-commands can override.""" if (self.args.server_host or self.args.server_port): if not (self.args.server_host and self.args.server_port): print(_(messages.CLI_INSTALL_MUST_SPECIFY_PORT_AND_HOST)) sys.exit(1) self.args.configure_server = 'true' check_abs_paths(self.args)
def test_keyboard_interupt(self, subprocess): """Testing a value server installlation.""" subprocess.return_value.returncode = 1 subprocess.return_value.communicate.side_effect = KeyboardInterrupt() mock_ansible_logs = 'test0\ntest1\n' byte_ansible_logs = bytes(mock_ansible_logs, 'utf-8') subprocess.return_value.stdout = io.BytesIO(byte_ansible_logs) cred_out = io.StringIO() cac = InstallServerCommand(SUBPARSER) with redirect_stdout(cred_out): cac.main(self.args) expected = mock_ansible_logs + _(messages.INSTALLATION_CANCELED) self.assertIn(expected, cred_out.getvalue().strip())
def test_install_cli_failure(self, subprocess): """Testing a failed CLI installlation.""" subprocess.return_value.returncode = 1 subprocess.return_value.communicate.side_effect = self.effect mock_ansible_logs = 'test0\ntest1\n' byte_ansible_logs = bytes(mock_ansible_logs, 'utf-8') subprocess.return_value.stdout = io.BytesIO(byte_ansible_logs) cred_out = io.StringIO() cac = InstallCLICommand(SUBPARSER) with redirect_stdout(cred_out): cac.main(self.args) expected = mock_ansible_logs + _(messages.CLI_INSTALLATION_FAILED) self.assertIn(expected, cred_out.getvalue().strip())
def test_configure_server_missing_host(self): """Testing option to configure server missing host.""" cred_out = io.StringIO() cac = InstallCLICommand(SUBPARSER) args = Namespace(server_host=None, server_port=9433, offline_files=None, home_dir=None) with redirect_stdout(cred_out): with self.assertRaises(SystemExit): cac.main(args) expected = _(messages.CLI_INSTALL_MUST_SPECIFY_PORT_AND_HOST) self.assertIn(expected, cred_out.getvalue().strip())
def test_install_server_success(self, subprocess): """Testing the installation of server command was successful.""" subprocess.return_value.returncode = 0 subprocess.return_value.communicate.side_effect = self.effect mock_ansible_logs = 'test0\ntest1\n' byte_ansible_logs = bytes(mock_ansible_logs, 'utf-8') subprocess.return_value.stdout = io.BytesIO(byte_ansible_logs) cred_out = io.StringIO() cac = InstallServerCommand(SUBPARSER) with redirect_stdout(cred_out): cac.main(self.args) expected = mock_ansible_logs + _( messages.SERVER_INSTALLATION_SUCCESSFUL) self.assertIn(expected, cred_out.getvalue().strip())
def test_downstream_vars(self, subprocess, downstream): """Test that args are included if downstream is set to true.""" downstream.return_value = True subprocess.return_value.returncode = 0 subprocess.return_value.communicate.side_effect = self.effect mock_ansible_logs = 'test0\ntest1\n' byte_ansible_logs = bytes(mock_ansible_logs, 'utf-8') subprocess.return_value.stdout = io.BytesIO(byte_ansible_logs) cred_out = io.StringIO() cac = InstallServerCommand(SUBPARSER) with redirect_stdout(cred_out): cac.main(self.args) expected = mock_ansible_logs + _( messages.SERVER_INSTALLATION_SUCCESSFUL) self.assertIn(expected, cred_out.getvalue().strip())
def test_install_server_critical_failure(self, subprocess): """Testing a failed server installlation.""" subprocess.return_value.returncode = 1 subprocess.return_value.communicate.side_effect = self.effect_error mock_ansible_logs = 'test0\ntest1\n' byte_ansible_logs = bytes(mock_ansible_logs, 'utf-8') subprocess.return_value.stdout = io.BytesIO(byte_ansible_logs) cred_out = io.StringIO() cac = InstallServerCommand(SUBPARSER) with redirect_stdout(cred_out): cac.main(self.args) expected = mock_ansible_logs + _( messages.SERVER_INSTALLATION_FAILED) cred_output = cred_out.getvalue().strip() self.assertIn(expected, cred_output) byte_string = self.effect_error[0][1] self.assertIn(byte_string.decode('utf-8'), cred_output)
def test_configure_server(self, subprocess): """Testing option to configure server.""" subprocess.return_value.returncode = 1 subprocess.return_value.communicate.side_effect = ValueError() mock_ansible_logs = 'test0\ntest1\n' byte_ansible_logs = bytes(mock_ansible_logs, 'utf-8') subprocess.return_value.stdout = io.BytesIO(byte_ansible_logs) cred_out = io.StringIO() cac = InstallCLICommand(SUBPARSER) args = Namespace(server_port='9433', server_host='127.0.0.1', offline_files=None, home_dir=None) with redirect_stdout(cred_out): cac.main(args) expected = mock_ansible_logs + _(messages.CLI_INSTALLATION_FAILED) self.assertIn(expected, cred_out.getvalue().strip())
def check_abs_paths(args): """Check and convert all paths to an absolute path. :param path: (args) commands arguments :returns: None """ if not DOWNSTREAM: if args.offline_files: abs_offline_files = make_path_absolute(args.offline_files) if not os.path.exists(abs_offline_files): print( _(messages.ALL_DIRECTORY_DOES_NOT_EXIST % ('offline-files', abs_offline_files))) sys.exit(1) args.offline_files = abs_offline_files if args.home_dir: args.home_dir = make_path_absolute(args.home_dir)
def create_ansible_command(namespace_args, playbook): """Build Ansible Command. :param namespace_args: arguments passed in by the user :param playbook: name of the playbook :returns: The ansible command that will be run """ # Initial command setup cmd_list = ['ansible-playbook'] cmd_list.append(playbook) verbosity_lvl = '-vv' cmd_list.append(verbosity_lvl) # Filter Extra Vars args_dictionary = check_offline(namespace_args.__dict__) install_vars = get_password(args_dictionary) for key in NOT_ANSIBLE_KEYS: if key in install_vars.keys(): install_vars.pop(key, None) # grab the advanced args advanced_args = install_vars.pop('server_advanced', []) or [] install_vars = {k: v for k, v in install_vars.items() if v is not None} # Add extra vars to command extra_format = '-e %s=%s' for key, value in install_vars.items(): extra_var = extra_format % (key, value) cmd_list.append(extra_var) # loop through advanced args and add them to the command for advanced_cmd in advanced_args: cmd_list.append('-e %s' % advanced_cmd) # print command and mask passwords tmp_list = cmd_list.copy() for arg in tmp_list: if 'password' in arg: mask_arg = arg.split('=')[0] + '=' + '*******' tmp_list.remove(arg) tmp_list.append(mask_arg) print(_(messages.PLAYBOOK_COMMAND % (' '.join(tmp_list)))) return cmd_list
def __init__(self, subparsers): """Create command.""" # pylint: disable=no-member CliCommand.__init__(self, self.SUBCOMMAND, self.ACTION, subparsers.add_parser(self.ACTION)) if DOWNSTREAM: # Be careful adding defaults here, because it would require a new # upstream release to change the downstream defaults. self.parser.add_argument('--registry-no-auth', dest='registry_no_auth', action='store_true', help=_(messages.SERVER_INSTALL_REGISTRY_NO_AUTH_HELP), required=False) self.parser.add_argument('--registry-url', dest='registry_url', default='registry.redhat.io', help=_(messages.SERVER_INSTALL_REGISTRY_URL_HELP), required=False) self.parser.add_argument('--registry-user', dest='registry_username', help=_(messages.SERVER_INSTALL_REGISTRY_UN_HELP), required=False) self.parser.add_argument('--registry-password', dest='registry_password', help=_(messages.SERVER_INSTALL_REGISTRY_PASS_HELP), required=False) self.parser.add_argument('--server-image-name', dest='server_image_name', help=_(messages.SERVER_INSTALL_SERVER_IMAGE_HELP), required=False) self.parser.add_argument('--db-image-name', dest='db_image_name', help=_(messages.SERVER_INSTALL_DB_IMAGE_HELP), required=False) else: # Upstream only args self.parser.add_argument('--offline-files', dest='offline_files', help=_(messages.SERVER_INSTALL_OFFLINE_FILES_HELP), required=False) self.parser.add_argument('--version', dest='server_version', help=_(messages.SERVER_INSTALL_VERSION_HELP), required=False) self.parser.add_argument('--home-dir', dest='home_dir', help=_(messages.ALL_INSTALL_HOME_DIR_HELP), required=False) self.parser.add_argument('--port', dest='server_port', default='9443', help=_(messages.SERVER_INSTALL_PORT_HELP), required=False) self.parser.add_argument('--open-port', dest='open_port', choices=BOOLEAN_CHOICES, default='true', help=_(messages.SERVER_INSTALL_OPEN_PORT_HELP), required=False) self.parser.add_argument('--db-user', dest='db_user', default='postgres', help=_(messages.SERVER_INSTALL_DB_USER_HELP), required=False) self.parser.add_argument('--db-password', dest='db_password', help=_(messages.SERVER_INSTALL_DB_PASSWORD_HELP), required=False) self.parser.add_argument('--username', dest='server_username', default='admin', help=_(messages.SERVER_INSTALL_USERNAME_HELP), required=False) self.parser.add_argument('--password', dest='server_password', help=_(messages.SERVER_INSTALL_PASSWORD_HELP), required=False) self.parser.add_argument('--advanced', dest='server_advanced', nargs='+', default=[], help=SUPPRESS, required=False)