def list(ctx, porcelain): # pragma: no cover """ Prints a list of currently available platforms. """ command_args = {'porcelain': porcelain} l = List(ctx.obj.get('args'), command_args) l.execute util.sysexit(l.execute()[0])
def execute_with_retries(self): """Run dependency downloads with retry and timed back-off.""" exception = None try: util.run_command(self._sh_command, debug=self._config.debug) msg = "Dependency completed successfully." LOG.success(msg) return except sh.ErrorReturnCode: pass for counter in range(1, (self.RETRY + 1)): msg = "Retrying dependency ... {}/{} time(s)".format( counter, self.RETRY) LOG.warning(msg) msg = "Sleeping {} seconds before retrying ...".format(self.SLEEP) LOG.warning(msg) time.sleep(self.SLEEP) self.SLEEP += self.BACKOFF try: util.run_command(self._sh_command, debug=self._config.debug) msg = "Dependency completed successfully." LOG.success(msg) return except sh.ErrorReturnCode as _exception: exception = _exception util.sysexit(exception.exit_code)
def _rubocop(self, serverspec_dir, debug=False, pattern='/**/*.rb', out=util.callback_info, err=util.callback_error): """ Executes rubocop against specified directory/pattern and returns a :func:`sh` response object. :param serverspec_dir: A string containing the directory with files to lint. :param debug: An optional bool to toggle debug output. :param pattern: A string containing the pattern of files to lint. :param out: An optional function to process STDOUT for underlying :func:`sh` call. :param err: An optional function to process STDERR for underlying :func:`sh` call. :return: :func:`sh` response object. """ kwargs = {'_out': out, '_err': err, 'debug': debug} msg = 'Executing rubocop on *.rb files found in {}/...'.format( serverspec_dir) util.print_info(msg) match = serverspec_dir + pattern try: cmd = sh.rubocop.bake(match, **kwargs) except sh.CommandNotFound: msg = 'Verifier missing, gem install rubocop.' util.print_error(msg) util.sysexit() return util.run_command(cmd, debug=self._debug)
def execute(self, exit=True): """ Execute the actions necessary to perform a `molecule idempotence` and return a tuple. :param exit: An optional flag to toggle the exiting of the module on command failure. :return: Return a tuple of (`exit status`, `command output`), otherwise sys.exit on command failure. """ util.print_info( 'Idempotence test in progress (can take a few minutes) ...') c = converge.Converge(self.args, self.command_args, self.molecule) status, output = c.execute( idempotent=True, exit=False, hide_errors=True) if status is not None: msg = 'Skipping due to errors during converge.' util.print_info(msg) return status, None idempotent = self._is_idempotent(output) if idempotent: util.print_success('Idempotence test passed.') return None, None else: LOG.error( 'Idempotence test failed because of the following tasks:') LOG.error('\n'.join(self._non_idempotent_tasks(output))) if exit: util.sysexit() return 1, None
def execute(self): if not self.enabled: msg = "Skipping, verifier is disabled." LOG.warning(msg) return if not len(self._tests) > 0: msg = "Skipping, no tests found." LOG.warning(msg) return if self._testinfra_command is None: self.bake() msg = "Executing Testinfra tests found in {}/...".format( self.directory) LOG.info(msg) result = util.run_command(self._testinfra_command, debug=self._config.debug) if result.returncode == 0: msg = "Verifier completed successfully." LOG.info(msg) else: util.sysexit(result.returncode)
def ansible_version(version: str = "") -> Version: """Return current Version object for Ansible. If version is not mentioned, it returns current version as detected. When version argument is mentioned, it return converts the version string to Version object in order to make it usable in comparisons. """ if not version: proc = run_command(["ansible", "--version"], quiet=True) if proc.returncode != 0: LOG.fatal( "Unable to find a working copy of ansible executable. Read https://molecule.readthedocs.io/en/latest/installation.html\n%s", proc, ) sysexit(RC_SETUP_ERROR) # First line of the `ansible --version` output is: # # 1. `ansible <version>` on ansible < 2.10 and on ansible-base. # 2. `ansible [core <version>]` on ansible-core. # # The code below grabs the last component in that line and strips trailing ] if # present. version = proc.stdout.splitlines()[0].split()[-1].rstrip("]") return Version(version)
def execute_with_retries(self): """Run dependency downloads with retry and timed back-off.""" exception = None try: # print(555, self._sh_command) util.run_command(self._sh_command, debug=self._config.debug) msg = "Dependency completed successfully." LOG.success(msg) return except Exception: pass for counter in range(1, (self.RETRY + 1)): msg = "Retrying dependency ... {}/{} time(s)".format(counter, self.RETRY) LOG.warning(msg) msg = "Sleeping {} seconds before retrying ...".format(self.SLEEP) LOG.warning(msg) time.sleep(self.SLEEP) self.SLEEP += self.BACKOFF try: util.run_command(self._sh_command, debug=self._config.debug) msg = "Dependency completed successfully." LOG.success(msg) return except Exception as _exception: exception = _exception LOG.error(str(exception), self._sh_command) util.sysexit(getattr(exception, "exit_code", constants.RC_UNKNOWN_ERROR))
def execute(self, exit=True): """ Execute the actions necessary to perform a `molecule idempotence` and return a tuple. :param exit: An optional flag to toggle the exiting of the module on command failure. :return: Return a tuple of (`exit status`, `command output`), otherwise sys.exit on command failure. """ util.print_info("Idempotence test in progress (can take a few minutes) ...") c = converge.Converge(self.command_args, self.args, self.molecule) status, output = c.execute(idempotent=True, exit=False, hide_errors=True) if status is not None: msg = "Skipping due to errors during converge." util.print_info(msg) return status, None idempotent = self._is_idempotent(output) if idempotent: util.print_success("Idempotence test passed.") return None, None else: LOG.error("Idempotence test failed because of the following tasks:") LOG.error("\n".join(self._non_idempotent_tasks(output))) if exit: util.sysexit() return 1, None
def test(ctx, scenario_name, driver_name, __all, destroy): # pragma: no cover """ Test (lint, destroy, dependency, syntax, create, prepare, converge, idempotence, side_effect, verify, destroy). """ args = ctx.obj.get('args') subcommand = base._get_subcommand(__name__) command_args = { 'destroy': destroy, 'subcommand': subcommand, 'driver_name': driver_name, } if __all: scenario_name = None s = scenarios.Scenarios(base.get_configs(args, command_args), scenario_name) s.print_matrix() for scenario in s: try: for term in scenario.sequence: base.execute_subcommand(scenario.config, term) except SystemExit: if destroy == 'always': msg = ('An error occured during the test sequence. ' 'Cleaning up.') LOG.warn(msg) base.execute_subcommand(scenario.config, 'destroy') util.sysexit() raise
def execute(self, exit=True): # pragma: no cover """ Executes trailing linters, and returns None, otherwise sys.exit on command failure. :return: None :param ignore_paths: List of paths to ignore during checks. :return: None, otherwise sys.exit on command failure. """ filenames = [] pruned_filenames = [] found_error = False valid_extensions = ['py', 'yml', 'rb'] for root, dirs, files in os.walk('.'): # gets ./subdirectory/filename filenames.extend( [os.path.join(root, name) for name in files if name.split(os.extsep)[-1] in valid_extensions]) # gets ./filename filenames.extend( [os.path.join(root, name) for name in dirs if name.split(os.extsep)[-1] in valid_extensions]) # only work on files not in our ignore paths for f in filenames: f_parts = f.split(os.sep) try: if f_parts[1] in self._ignore_paths: continue except IndexError: continue # don't add directories if os.path.isfile(f): pruned_filenames.append(f) for filename in pruned_filenames: # don't process blank files if os.path.getsize(filename) < 1: continue data = [line for line in open(filename, 'r')] newline = self._trailing_newline(data) whitespace = self._trailing_whitespace(data) if newline: msg = 'Trailing newline found at the end of {}' LOG.error(msg.format(filename)) found_error = True if len(whitespace) > 0: msg = 'Trailing whitespace found in {} on lines: {}' lines = ', '.join(str(x) for x in whitespace) LOG.error(msg.format(filename, lines, )) found_error = True if exit and found_error: util.sysexit()
def execute(self): if not self.enabled: msg = 'Skipping, verifier is disabled.' LOG.warn(msg) return if not len(self._tests) > 0: msg = 'Skipping, no tests found.' LOG.warn(msg) return if self._testinfra_command is None: self.bake() msg = 'Executing Testinfra tests found in {}/...'.format( self.directory) LOG.info(msg) try: util.run_command(self._testinfra_command, debug=self._config.debug) msg = 'Verifier completed successfully.' LOG.success(msg) except sh.ErrorReturnCode as e: util.sysexit(e.exit_code)
def main(self): c = self.molecule.config if not c.molecule_file_exists(): msg = 'Unable to find {}. Exiting.' LOG.error(msg.format(c.molecule_file)) util.sysexit() self.molecule.main()
def execute(self, exit=True): """ Execute the actions necessary to perform a `molecule init` and exit. :param exit: (Unused) Provided to complete method signature. :return: None """ role = self.command_args.get('role') role_path = os.getcwd() driver = self._get_driver() verifier = self._get_verifier() if not role: role = os.getcwd().split(os.sep)[-1] role_path = os.path.abspath(os.path.join(os.getcwd(), os.pardir)) self._init_existing_role(role, role_path, driver, verifier) else: if os.path.isdir(role): msg = 'The directory {} exists. Cannot create new role.' LOG.error(msg.format(role)) util.sysexit() self._init_new_role(role, role_path, driver, verifier) msg = 'Successfully initialized new role in {} ...' util.print_success(msg.format(os.path.join(role_path, role))) util.sysexit(0)
def execute(self, exit=True): """ Execute the actions necessary to perform a `molecule check` and return a tuple. :param exit: (Unused) Provided to complete method signature. :return: Return a tuple provided by :meth:`.AnsiblePlaybook.execute`. """ if not self.molecule.state.created: msg = ('Instance(s) not created, `check` should be run ' 'against created instance(s).') util.print_error(msg) util.sysexit() debug = self.args.get('debug') ansible = ansible_playbook.AnsiblePlaybook( self.molecule.config.config['ansible'], self.molecule.driver.ansible_connection_params, debug=debug) ansible.add_cli_arg('check', True) util.print_info("Performing a 'Dry Run' of playbook...") return ansible.execute(hide_errors=True) return (None, None)
def verify(ctx, platform, provider, sudo): # pragma: no cover """ Performs verification steps on running instances. """ command_args = {'platform': platform, 'provider': provider, 'sudo': sudo} v = Verify(ctx.obj.get('args'), command_args) v.execute util.sysexit(v.execute()[0])
def ansible_version(version: str = None) -> Version: """Return current Version object for Ansible. If version is not mentioned, it returns current version as detected. When version argument is mentioned, it return converts the version string to Version object in order to make it usable in comparisons. """ if not version: try: version = ( subprocess.run( ["ansible", "--version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, ) .stdout.splitlines()[0] .split()[1] ) except FileNotFoundError: LOG.fatal( "Unable to find ansible executable. Read https://molecule.readthedocs.io/en/latest/installation.html" ) sysexit(RC_SETUP_ERROR) return Version(version)
def execute(self): """Execute the pre-commit command.""" if not self.enabled: msg = 'Skipping, verifier_lint is disabled.' LOG.warn(msg) return if not self._tests: msg = 'Skipping, no tests found.' LOG.warn(msg) return if self._precommit_command is None: self.bake() msg = 'Executing pre-commit on files found in {}/...'.format( self._config.verifier.directory) LOG.info(msg) try: util.run_command(self._precommit_command, debug=self._config.debug) msg = 'Lint completed successfully.' LOG.success(msg) except sh.ErrorReturnCode as e: util.sysexit(e.exit_code)
def execute(self, exit=True): util.print_info( 'Idempotence test in progress (can take a few minutes)...') c = converge.Converge(self.command_args, self.args, self.molecule) status, output = c.execute(idempotent=True, exit=False, hide_errors=True) if status is not None: msg = 'Skipping due to errors during converge.' util.print_info(msg) return status, None idempotent, changed_tasks = self.molecule._parse_provisioning_output( output) if idempotent: util.print_success('Idempotence test passed.') return None, None # Display the details of the idempotence test. if changed_tasks: LOG.error( 'Idempotence test failed because of the following tasks:') LOG.error('{}'.format('\n'.join(changed_tasks))) else: # But in case the idempotence callback plugin was not found, we just display an error message. LOG.error('Idempotence test failed.') warning_msg = "The idempotence plugin was not found or did not provide the required information. " \ "Therefore the failure details cannot be displayed." LOG.warning(warning_msg) if exit: util.sysexit() return 1, None
def idempotence(ctx, platform, provider): # pragma: no cover """ Provisions instances and parses output to determine idempotence. """ command_args = {"platform": platform, "provider": provider} i = Idempotence(ctx.obj.get("args"), command_args) i.execute util.sysexit(i.execute()[0])
def execute(self): """ Executes `testinfra` and returns None. :return: None """ if not self.enabled: LOG.warn('Skipping, verifier is disabled.') return if not len(self._tests) > 0: LOG.warn('Skipping, no tests found.') return if self._testinfra_command is None: self.bake() f = flake8.Flake8(self._config) f.execute() msg = 'Executing Testinfra tests found in {}/...'.format( self.directory) LOG.info(msg) try: util.run_command(self._testinfra_command, debug=self._config.args.get('debug')) LOG.success('Verifier completed successfully.') except sh.ErrorReturnCode as e: util.sysexit(e.exit_code)
def _symlink_vars(self): """Creates or updates the symlink to group_vars if needed.""" SYMLINK_NAME = 'group_vars' group_vars_target = self.config.config.get('molecule', {}).get('group_vars') molecule_dir = self.config.config['molecule']['molecule_dir'] group_vars_link_path = os.path.join(molecule_dir, SYMLINK_NAME) # Remove any previous symlink. if os.path.lexists(group_vars_link_path): try: os.unlink(group_vars_link_path) except: pass # Do not create the symlink if nothing is specified in the config. if not group_vars_target: return # Otherwise create the new symlink. symlink = os.path.join(os.path.abspath(molecule_dir), group_vars_target) if not os.path.exists(symlink): LOG.error( 'ERROR: the group_vars path {} does not exist. Check your configuration file' .format(group_vars_target)) util.sysexit() os.symlink(group_vars_target, group_vars_link_path)
def test(ctx, scenario_name, driver_name, __all, destroy): # pragma: no cover """ Test (destroy, create, converge, lint, verify, destroy). """ args = ctx.obj.get('args') subcommand = base._get_subcommand(__name__) command_args = { 'subcommand': subcommand, 'driver_name': driver_name, } if __all: scenario_name = None s = scenarios.Scenarios( base.get_configs(args, command_args), scenario_name) s.print_matrix() for scenario in s: try: for term in scenario.sequence: base.execute_subcommand(scenario.config, term) except SystemExit: if destroy == 'always': msg = ('An error occured during the test sequence. ' 'Cleaning up.') LOG.warn(msg) base.execute_subcommand(scenario.config, 'destroy') util.sysexit() raise
def execute(self, exit=True): """ Execute the actions necessary to perform a `molecule verify` and return a tuple. :param exit: An optional flag to toggle the exiting of the module on command failure. :return: Return a tuple of None, otherwise sys.exit on command failure. """ for v in [ansible_lint.AnsibleLint(self.molecule), trailing.Trailing(self.molecule)]: v.execute() self.molecule.write_ssh_config() try: if self.molecule.verifier == 'serverspec': v = serverspec.Serverspec(self.molecule) elif self.molecule.verifier == 'goss': v = goss.Goss(self.molecule) else: v = testinfra.Testinfra(self.molecule) v.execute() except sh.ErrorReturnCode as e: LOG.error('ERROR: {}'.format(e)) if exit: util.sysexit(e.exit_code) return e.exit_code, e.stdout return None, None
def execute(self, exit=True): """ Execute the actions necessary to perform a `molecule create` and return a tuple. :param exit: An optional flag to toggle the exiting of the module on command failure. :return: Return a tuple of None, otherwise sys.exit on command failure. """ self.molecule.remove_inventory_file() self.molecule.create_templates() try: util.print_info('Creating instances...') self.molecule.driver.up(no_provision=True) self.molecule.state.change_state('created', True) if self.command_args.get('platform') == 'all': self.molecule.state.change_state('multiple_platforms', True) except subprocess.CalledProcessError as e: util.print_error(str(e)) if exit: util.sysexit(e.returncode) return e.returncode, e.message self.molecule.create_inventory_file() self.molecule.write_instances_state() return None, None
def execute(self, exit=True): """ Execute the actions necessary to perform a `molecule verify` and return a tuple. :param exit: An optional flag to toggle the exiting of the module on command failure. :return: Return a tuple of None, otherwise sys.exit on command failure. """ try: v = ansible_lint.AnsibleLint(self.molecule) v.execute() except sh.ErrorReturnCode_2: util.sysexit() v = trailing.Trailing(self.molecule) v.execute() self.molecule.write_ssh_config() try: if self.molecule.verifier == 'serverspec': v = serverspec.Serverspec(self.molecule) elif self.molecule.verifier == 'goss': v = goss.Goss(self.molecule) else: v = testinfra.Testinfra(self.molecule) v.execute() except sh.ErrorReturnCode as e: LOG.error('ERROR: {}'.format(e)) if exit: util.sysexit(e.exit_code) return e.exit_code, e.stdout return None, None
def idempotence(ctx, platform, provider): # pragma: no cover """ Provisions instances and parses output to determine idempotence. """ command_args = {'platform': platform, 'provider': provider} i = Idempotence(ctx.obj.get('args'), command_args) i.execute util.sysexit(i.execute()[0])
def _rake(self, rakefile, debug=False, out=util.callback_info, err=util.callback_error): """ Executes rake against specified rakefile and returns a :func:`sh` response object. :param rakefile: A string containing path to the rakefile. :param debug: An optional bool to toggle debug output. :param out: An optional function to process STDOUT for underlying :func:`sh` call. :param err: An optional function to process STDERR for underlying :func:`sh` call. :return: :func:`sh` response object. """ kwargs = { '_out': out, '_err': err, 'trace': debug, 'rakefile': rakefile } msg = 'Executing serverspec tests found in {}/...'.format( self._serverspec_dir) util.print_info(msg) try: cmd = sh.rake.bake(**kwargs) except sh.CommandNotFound: msg = 'Verifier missing, gem install rake.' util.print_error(msg) util.sysexit() return util.run_command(cmd, debug=self._debug)
def execute(self, exit=True): """ Recursively finds all files relative to CWD, and checks them for trailing whitespace and newlines. :param ignore_paths: list of paths to ignore during checks :return: A ``sys.exit`` code if found an error, otherwise None """ filenames = [] pruned_filenames = [] found_error = False valid_extensions = ['py', 'yml', 'rb'] for root, dirs, files in os.walk('.'): # gets ./subdirectory/filename filenames.extend( [os.path.join(root, name) for name in files if name.split(os.extsep)[-1] in valid_extensions]) # gets ./filename filenames.extend( [os.path.join(root, name) for name in dirs if name.split(os.extsep)[-1] in valid_extensions]) # only work on files not in our ignore paths for f in filenames: f_parts = f.split(os.sep) try: if f_parts[1] in self._ignore_paths: continue except IndexError: continue # don't add directories if os.path.isfile(f): pruned_filenames.append(f) for filename in pruned_filenames: # don't process blank files if os.path.getsize(filename) < 1: continue data = [line for line in open(filename, 'r')] newline = self._trailing_newline(data) whitespace = self._trailing_whitespace(data) if newline: msg = 'Trailing newline found at the end of {}' LOG.error(msg.format(filename)) found_error = True if whitespace: msg = 'Trailing whitespace found in {} on lines: {}' lines = ', '.join(str(x) for x in whitespace) LOG.error(msg.format(filename, lines, )) found_error = True if exit and found_error: util.sysexit()
def up(self, no_provision=True): self.molecule.state.change_state('driver', self.name) kpn = self._get_keypair() active_instances = self._openstack.list_servers() active_instance_names = { instance['name']: instance['status'] for instance in active_instances } util.print_warn('Creating openstack instances...') for instance in self.instances: try: # We divide the ssh_timeout by 2, because the connect # itself takes at least a second and is followed by # a 1 sec sleep ssh_timeout = int( instance.get('ssh_timeout', self.ssh_timeout) / 2) except TypeError: util.print_error('Can not cast ssh_timeout setting "%s"' ' to int' % instance.get('ssh_timeout', self.ssh_timeout)) util.sysexit() if instance['name'] not in active_instance_names: msg = '\tBringing up {}...'.format(instance['name']) util.print_info(msg) server = self._openstack.create_server( name=instance['name'], image=self._openstack.get_image(instance['image']), flavor=self._openstack.get_flavor(instance['flavor']), auto_ip=True, wait=True, key_name=kpn, ip_pool=instance.get('ip_pool') if instance.get('ip_pool') else self.ip_pool, network=instance.get('networks', []), security_groups=instance.get('security_groups', [])) instance['created'] = True instance['reachable'] = False for _ in range(ssh_timeout): util.print_info('\t Waiting for ssh availability...') if self._check_ssh_availability( server['interface_ip'], instance['sshuser'], timeout=1, sshkey_filename=self._get_keyfile()): instance['reachable'] = True break if not instance['reachable']: util.print_error( 'Could not reach instance "%s"' ' within limit of %s seconds' % (instance['name'], instance.get('ssh_timeout', self.ssh_timeout))) util.sysexit()
def destroy(ctx, driver, platform, provider): # pragma: no cover """ Destroys all instances created by molecule. """ command_args = {'driver': driver, 'platform': platform, 'provider': provider} d = Destroy(ctx.obj.get('args'), command_args) d.execute util.sysexit(d.execute()[0])
def create(ctx, driver, platform, provider): # pragma: no cover """ Creates all instances defined in molecule.yml. """ command_args = {'driver': driver, 'platform': platform, 'provider': provider} c = Create(ctx.obj.get('args'), command_args) c.execute util.sysexit(c.execute()[0])
def init(ctx, role, driver, verifier): # pragma: no cover """ Creates the scaffolding for a new role intended for use with molecule. """ command_args = {'role': role, 'driver': driver, 'verifier': verifier} i = Init(ctx.obj.get('args'), command_args) i.execute util.sysexit(i.execute()[0])
def execute_cmdline_scenarios(scenario_name, args, command_args, ansible_args=()): """ Execute scenario sequences based on parsed command-line arguments. This is useful for subcommands that run scenario sequences, which excludes subcommands such as ``list``, ``login``, and ``matrix``. ``args`` and ``command_args`` are combined using :func:`get_configs` to generate the scenario(s) configuration. :param scenario_name: Name of scenario to run, or ``None`` to run all. :param args: ``args`` dict from ``click`` command context :param command_args: dict of command arguments, including the target subcommand to execute :returns: None """ glob_str = MOLECULE_GLOB if scenario_name: glob_str = glob_str.replace("*", scenario_name) scenarios = molecule.scenarios.Scenarios( get_configs(args, command_args, ansible_args, glob_str), scenario_name) if scenario_name and scenarios: LOG.info( "%s scenario test matrix: %s", scenario_name, ", ".join(scenarios.sequence(scenario_name)), ) for scenario in scenarios: if command_args.get("subcommand") == "reset": LOG.info("Removing %s" % scenario.ephemeral_directory) shutil.rmtree(scenario.ephemeral_directory) return try: execute_scenario(scenario) except SystemExit: # if the command has a 'destroy' arg, like test does, # handle that behavior here. if command_args.get("destroy") == "always": msg = ("An error occurred during the {} sequence action: " "'{}'. Cleaning up.").format(scenario.config.subcommand, scenario.config.action) LOG.warning(msg) execute_subcommand(scenario.config, "cleanup") execute_subcommand(scenario.config, "destroy") # always prune ephemeral dir if destroying on failure scenario.prune() if scenario.config.is_parallel: scenario._remove_scenario_state_directory() util.sysexit() else: raise
def converge(ctx, driver, platform, provider, tags): # pragma: no cover """ Provisions all instances defined in molecule.yml. """ command_args = {'driver': driver, 'platform': platform, 'provider': provider, 'tags': tags} c = Converge(ctx.obj.get('args'), command_args) c.execute util.sysexit(c.execute()[0])
def execute(self): """ Executes Goss integration tests and returns None. :return: None """ if self._get_tests(): status, output = self._goss() if status is not None: util.sysexit(status)
def status(ctx, platforms, providers, hosts, porcelain): # pragma: no cover """ Prints status of configured instances. """ command_args = {'platforms': platforms, 'providers': providers, 'hosts': hosts, 'porcelain': porcelain} s = Status(ctx.obj.get('args'), command_args) s.execute util.sysexit(s.execute()[0])
def test(ctx, driver, platform, provider, destroy, sudo): # pragma: no cover """ Runs a series of commands (defined in config) against instances for a full test/verify run. """ command_args = {"driver": driver, "platform": platform, "provider": provider, "destroy": destroy, "sudo": sudo} t = Test(ctx.obj.get("args"), command_args) t.execute util.sysexit(t.execute()[0])
def destroy(ctx, driver, platform, provider): # pragma: no cover """ Destroys all instances created by molecule. """ command_args = { 'driver': driver, 'platform': platform, 'provider': provider } d = Destroy(ctx.obj.get('args'), command_args) d.execute util.sysexit(d.execute()[0])
def status(ctx, driver, platforms, providers, hosts, porcelain): # pragma: no cover """ Prints status of configured instances. """ command_args = {'driver': driver, 'platforms': platforms, 'providers': providers, 'hosts': hosts, 'porcelain': porcelain} s = Status(ctx.obj.get('args'), command_args) s.execute util.sysexit(s.execute()[0])
def converge(ctx, driver, platform, provider, tags): # pragma: no cover """ Provisions all instances defined in molecule.yml. """ command_args = { 'driver': driver, 'platform': platform, 'provider': provider, 'tags': tags } c = Converge(ctx.obj.get('args'), command_args) c.execute util.sysexit(c.execute()[0])
def login(ctx, host): # pragma: no cover """ Initiates an interactive ssh session with the given host. \b If no `--host` flag provided, will login to the instance. If more than once instance exists, the `--host` flag must be provided. """ command_args = {"host": host} l = Login(ctx.obj.get("args"), command_args) l.execute util.sysexit(l.execute()[0])
def main(self): """ A mechanism to initialize molecule by calling its main method. This can be redefined by classes which do not want this behavior (:class:`.Init`). :returns: None """ c = self.molecule.config if not c.molecule_file_exists(): msg = 'Unable to find {}. Exiting.' LOG.error(msg.format(c.molecule_file)) util.sysexit() self.molecule.main()
def test(ctx, driver, platform, provider, destroy, sudo): # pragma: no cover """ Runs a series of commands (defined in config) against instances for a full test/verify run. """ command_args = {'driver': driver, 'platform': platform, 'provider': provider, 'destroy': destroy, 'sudo': sudo} t = Test(ctx.obj.get('args'), command_args) t.execute util.sysexit(t.execute()[0])
def main(self): """ A mechanism to initialize molecule by calling its main method. This can be redefined by classes which do not want this behavior (:class:`.Init`). :returns: None """ if not self._config.molecule_file_exists(): msg = ('Unable to find {}. ' 'Exiting.').format(self._config.molecule_file) util.print_error(msg) util.sysexit() self.molecule.main()
def execute(self): """ Executes ansible-galaxy install, and returns command's stdout. , :return: The command's output, otherwise sys.exit on command failure. """ if self._galaxy is None: self.bake() try: return self._galaxy().stdout except sh.ErrorReturnCode as e: LOG.error('ERROR: {}'.format(e)) util.sysexit(e.exit_code)
def execute(self): """ Executes shell command and returns the command's stdout. :return: The command's output, otherwise sys.exit on command failure. """ if self._command is None: self.bake() try: return util.run_command(self._command, debug=self._debug).stdout except sh.ErrorReturnCode as e: util.print_error(str(e)) util.sysexit(e.exit_code)
def main(self): args = docopt.docopt(__doc__, version=molecule.__version__, options_first=True) command_name = args.get('<command>') command_args = {} if args.get('<args>') is None else args.pop('<args>') try: command_module = getattr(command, command_name) command_clazz = getattr(command_module, command_name.capitalize()) except AttributeError: raise docopt.DocoptExit() c = command_clazz(command_args, args) util.sysexit(c.execute()[0])
def execute(self): """ Executes ansible-galaxy install :return: sh.stdout on success, else None :return: None """ if self._galaxy is None: self.bake() try: return self._galaxy().stdout except sh.ErrorReturnCode as e: LOG.error('ERROR: {}'.format(e)) util.sysexit(e.exit_code)