def add_deploy(state, deploy_func, *args, **kwargs): """ Prepare & add an deploy to pyinfra.state by executing it on all hosts. Args: state (``pyinfra.api.State`` obj): the deploy state to add the operation deploy_func (function): the operation function from one of the modules, ie ``server.user`` args/kwargs: passed to the operation function """ if pyinfra.is_cli: raise PyinfraError( ( "`add_deploy` should not be called when pyinfra is executing in CLI mode! ({0})" ).format(get_call_location()), ) hosts = kwargs.pop("host", state.inventory.iter_active_hosts()) if isinstance(hosts, Host): hosts = [hosts] with ctx_state.use(state): for deploy_host in hosts: with ctx_host.use(deploy_host): deploy_func(*args, **kwargs)
def add_op(state, op_func, *args, **kwargs): """ Prepare & add an operation to ``pyinfra.state`` by executing it on all hosts. Args: state (``pyinfra.api.State`` obj): the deploy state to add the operation to op_func (function): the operation function from one of the modules, ie ``server.user`` args/kwargs: passed to the operation function """ allow_cli_mode = kwargs.pop("_allow_cli_mode", False) after_host_callback = kwargs.pop("_after_host_callback", lambda host: None) if pyinfra.is_cli and not allow_cli_mode: raise PyinfraError(( "`add_op` should not be called when pyinfra is executing in CLI mode! ({0})" ).format(get_call_location(), ), ) hosts = kwargs.pop("host", state.inventory.iter_active_hosts()) if isinstance(hosts, Host): hosts = [hosts] with ctx_state.use(state): results = {} for op_host in hosts: with ctx_host.use(op_host): results[op_host] = op_func(*args, **kwargs) after_host_callback(op_host) return results
def load_file(local_host): with ctx_config.use(state.config.copy()): with ctx_host.use(local_host): exec_file(filename) logger.info( "{0}{1} {2}".format( local_host.print_prefix, click.style("Ready:", "green"), click.style(filename, bold=True), ), )
def get_fact_with_context(state, host, *args, **kwargs): with ctx_state.use(state): with ctx_host.use(host): return get_fact(state, host, *args, **kwargs)
def _run_host_op_with_context(state, host, op_hash): with ctx_host.use(host): return run_host_op(state, host, op_hash)
def jsontest_function(self, test_name, test_data): if ("require_platform" in test_data and PLATFORM_NAME not in test_data["require_platform"]): return op_test_name = "{0}/{1}.json".format(arg, test_name) # Create a host with this tests facts and attach to context host host = create_host(facts=test_data.get("facts", {})) allowed_exception = test_data.get("exception") args = parse_value(test_data.get("args", [])) kwargs = parse_value(test_data.get("kwargs", {})) with ctx_state.use(self.state): with ctx_host.use(host): with patch_files(test_data.get("local_files", {})): try: output_commands = list( op._pyinfra_op(*args, **kwargs)) except Exception as e: if allowed_exception: allowed_exception_names = allowed_exception.get( "names") if not allowed_exception_names: allowed_exception_names = [ allowed_exception["name"] ] if e.__class__.__name__ not in allowed_exception_names: print("Wrong execption raised!") raise assert e.args[0] == allowed_exception[ "message"] return raise op_is_idempotent = getattr(op._pyinfra_op, "is_idempotent", True) second_output_commands = [] test_second_output_commands = "second_output_commands" in test_data if op_is_idempotent or test_second_output_commands: second_output_commands = list( op._pyinfra_op(*args, **kwargs)) if op_is_idempotent: if test_data.get("idempotent", True): if second_output_commands: raise Exception( "Operation not idempotent, second output commands: {0}" .format(second_output_commands, ), ) else: if not second_output_commands: raise Exception( ("Operation tests as idempotent but test " "says it is not: {0}").format(op_test_name), ) if not test_data.get("disable_idempotent_warning_reason"): warnings.warn(( "This operation should be idempotent, but the test has " "disabled this check without reason: {0}" ).format(op_test_name), ) if op_is_idempotent is False: if "disable_idempotent_warning_reason" in test_data: warnings.warn(( "This operation is not idempotent and so the test does not need " "`disable_idempotent_warning_reason` set: {0}" ).format(op_test_name), ) commands = parse_commands(output_commands) assert_commands(commands, test_data["commands"]) if test_second_output_commands: assert_commands( parse_commands(second_output_commands), test_data["second_output_commands"], ) noop_description = test_data.get("noop_description") if len(commands) == 0 or noop_description: if noop_description is not None: assert host.noop_description == noop_description else: assert host.noop_description is not None, "no noop description was set" warnings.warn( 'No noop_description set for test: {0} (got "{1}")'. format( op_test_name, host.noop_description, ), )