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), )
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), )
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
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
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) }
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)
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)