Пример #1
0
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])
Пример #2
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)
Пример #3
0
    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)
Пример #4
0
    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
Пример #5
0
    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)
Пример #6
0
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)
Пример #7
0
    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))
Пример #8
0
    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
Пример #9
0
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
Пример #10
0
    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()
Пример #11
0
    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)
Пример #12
0
 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()
Пример #13
0
    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)
Пример #14
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)
Пример #15
0
    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)
Пример #16
0
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])
Пример #17
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)
Пример #18
0
    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)
Пример #19
0
    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
Пример #20
0
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])
Пример #21
0
    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)
Пример #22
0
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])
Пример #23
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)
Пример #24
0
    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
Пример #25
0
    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)
Пример #26
0
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
Пример #27
0
    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
Пример #28
0
    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
Пример #29
0
    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
Пример #30
0
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])
Пример #31
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)
Пример #32
0
    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()
Пример #33
0
    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()
Пример #34
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])
Пример #35
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])
Пример #36
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])
Пример #37
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
Пример #38
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])
Пример #39
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])
Пример #40
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)
Пример #41
0
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])
Пример #42
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])
Пример #43
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)
Пример #44
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])
Пример #45
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])
Пример #46
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])
Пример #47
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])
Пример #48
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()
Пример #49
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])
Пример #50
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)
Пример #52
0
    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)
Пример #53
0
    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])
Пример #54
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)