Esempio n. 1
0
def include(filename, hosts=False, when=True):
    '''
    Executes a local python file within the ``pyinfra.pseudo_state.deploy_dir``
    directory.

    Args:
        hosts (string, list): group name or list of hosts to limit this include to
        when (bool): indicate whether to trigger operations in this include
    '''

    if not pyinfra.is_cli:
        raise PyinfraError('local.include is only available in CLI mode.')

    if not when:
        return

    if hosts is not False:
        hosts = ensure_host_list(hosts, inventory=pseudo_state.inventory)
        if pseudo_host not in hosts:
            return

    if pseudo_state.deploy_dir:
        filename = path.join(pseudo_state.deploy_dir, filename)

    frameinfo = get_caller_frameinfo()

    logger.debug('Including local file: {0}'.format(filename))

    try:
        # Fixes a circular import because `pyinfra.local` is really a CLI
        # only thing (so should be `pyinfra_cli.local`). It is kept here
        # to maintain backwards compatability and the nicer public import
        # (ideally users never need to import from `pyinfra_cli`).

        from pyinfra_cli.config import extract_file_config
        from pyinfra_cli.util import exec_file

        # Load any config defined in the file and setup like a @deploy
        config_data = extract_file_config(filename)
        kwargs = {
            key.lower(): value
            for key, value in six.iteritems(config_data)
            if key in [
                'SUDO', 'SUDO_USER', 'SU_USER',
                'PRESERVE_SUDO_ENV', 'IGNORE_ERRORS',
            ]
        }
        with pseudo_state.deploy(
            filename, kwargs, None, frameinfo.lineno,
            in_deploy=False,
        ):
            exec_file(filename)

        # One potential solution to the above is to add local as an actual
        # module, ie `pyinfra.modules.local`.

    except IOError as e:
        raise PyinfraError(
            'Could not include local file: {0}\n{1}'.format(filename, e),
        )
Esempio n. 2
0
def include(filename):
    '''
    Executes a local python file within the ``pyinfra.pseudo_state.deploy_dir``
    directory.
    '''

    if not pyinfra.is_cli:
        raise PyinfraError('local.include is only available in CLI mode.')

    if filename.startswith('.'):
        filename = path.join(path.dirname(pseudo_state.current_exec_filename),
                             filename)
    elif pseudo_state.deploy_dir:
        filename = path.join(pseudo_state.deploy_dir, filename)

    logger.debug('Including local file: {0}'.format(filename))

    try:
        # Fixes a circular import because `pyinfra.local` is really a CLI
        # only thing (so should be `pyinfra_cli.local`). It is kept here
        # to maintain backwards compatibility and the nicer public import
        # (ideally users never need to import from `pyinfra_cli`).

        from pyinfra_cli.config import extract_file_config
        from pyinfra_cli.util import exec_file

        # Load any config defined in the file and setup like a @deploy
        config_data = extract_file_config(filename)
        kwargs = {
            key.lower(): value
            for key, value in six.iteritems(config_data) if key in [
                'SUDO',
                'SUDO_USER',
                'SU_USER',
                'PRESERVE_SUDO_ENV',
                'IGNORE_ERRORS',
            ]
        }
        with pseudo_state.deploy(path.normpath(filename),
                                 kwargs,
                                 None,
                                 in_deploy=False):
            exec_file(filename)

        # One potential solution to the above is to add local as an actual
        # module, ie `pyinfra.operations.local`.

    except Exception as e:
        raise PyinfraError(
            'Could not include local file: {0}:\n{1}'.format(filename, e), )
Esempio n. 3
0
def _get_group_data(deploy_dir):
    group_data = {}
    group_data_directory = path.join(deploy_dir, 'group_data')

    if path.exists(group_data_directory):
        files = listdir(group_data_directory)

        for file in files:
            if not file.endswith('.py'):
                continue

            group_data_file = path.join(group_data_directory, file)
            group_name = path.basename(file)[:-3]

            logger.debug(
                'Looking for group data in: {0}'.format(group_data_file))

            # Read the files locals into a dict
            attrs = exec_file(group_data_file, return_locals=True)

            group_data[group_name] = {
                key: value
                for key, value in six.iteritems(attrs)
                if not key.startswith('_')
            }

    return group_data
Esempio n. 4
0
def _get_group_data(dirname):
    group_data = {}
    group_data_directory = path.join(dirname, "group_data")

    logger.debug("Checking possible group_data directory: %s", dirname)

    if path.exists(group_data_directory):
        files = listdir(group_data_directory)

        for file in files:
            if not file.endswith(".py"):
                continue

            group_data_file = path.join(group_data_directory, file)
            group_name = path.basename(file)[:-3]

            logger.debug("Looking for group data in: %s", group_data_file)

            # Read the files locals into a dict
            attrs = exec_file(group_data_file, return_locals=True)
            keys = attrs.get("__all__", attrs.keys())

            group_data[group_name] = {
                key: value
                for key, value in attrs.items()
                if key in keys and not key.startswith("_")
            }

    return group_data
Esempio n. 5
0
def _get_groups_from_filename(inventory_filename):
    attrs = exec_file(inventory_filename, return_locals=True)

    return {
        key: value
        for key, value in six.iteritems(attrs)
        if _is_inventory_group(key, value)
    }
Esempio n. 6
0
def include(filename):
    """
    Executes a local python file within the ``pyinfra.state.cwd``
    directory.
    """

    if not pyinfra.is_cli:
        raise PyinfraError("local.include is only available in CLI mode.")

    filename = get_file_path(state, filename)

    logger.debug("Including local file: %s", filename)

    config_state = config.get_current_state()

    try:
        # Fixes a circular import because `pyinfra.local` is really a CLI
        # only thing (so should be `pyinfra_cli.local`). It is kept here
        # to maintain backwards compatibility and the nicer public import
        # (ideally users never need to import from `pyinfra_cli`).

        from pyinfra_cli.util import exec_file

        with host.deploy(path.relpath(filename, state.cwd),
                         None,
                         None,
                         in_deploy=False):
            exec_file(filename)

        # One potential solution to the above is to add local as an actual
        # module, ie `pyinfra.operations.local`.

    except Exception as e:
        raise PyinfraError(
            "Could not include local file: {0}:\n{1}".format(filename, e), )

    finally:
        config.set_current_state(config_state)
Esempio n. 7
0
def _get_groups_from_filename(inventory_filename):
    try:
        attrs = exec_file(inventory_filename, return_locals=True)

        return {
            key: value
            for key, value in six.iteritems(attrs)
            if _is_inventory_group(key, value)
        }

    # Syntax error implies this is not a Python file! Let's try parsing as Ansible
    except SyntaxError:
        if inventory_filename.endswith('.py'):
            raise

        return load_ansible_ini_inventory(inventory_filename)