def jsontest_function(self, test_name, test_data): # Create a host with this tests facts and attach to pseudo host host = create_host(facts=test_data.get('facts', {})) pseudo_host.set(host) allowed_exception = test_data.get('exception') with patch_files(test_data.get('files', [])): try: output_commands = op._pyinfra_op( pseudo_state, pseudo_host, *test_data.get('args', []), **test_data.get('kwargs', {})) or [] except Exception as e: if allowed_exception: if e.__class__.__name__ != allowed_exception['name']: print('Wrong execption raised!') raise self.assertEqual(e.args[0], allowed_exception['message']) return raise commands = [] for command in output_commands: if isinstance(command, six.string_types): commands.append(command.strip()) elif isinstance(command, dict): command['command'] = command['command'].strip() commands.append(command) elif isinstance(command, tuple): if isinstance(command[0], FunctionType): commands.append(command) else: if hasattr(command[0], 'read'): data = command[0].read() else: data = command[0] commands.append([data, command[1]]) else: commands.append(command) try: self.assertEqual(commands, test_data['commands']) except AssertionError as e: print() print('--> GOT:\n', json.dumps(commands, indent=4, default=json_encode)) print( '--> WANT:', json.dumps(test_data['commands'], indent=4, default=json_encode)) raise e
def test_pseudo_op(self): inventory = make_inventory() state = State(inventory, Config()) connect_all(state) pseudo_state.set(state) pseudo_host.set(inventory['somehost']) # Exceute the op "bare" server.shell('echo "hi"') # Ensure this is ignored state.active = False server.shell('echo "hi 2"') # We should now have one op self.assertEqual(len(state.op_order), 1) # Ensure only somehost has actual op self.assertEqual(len(state.ops['somehost']), 1) self.assertEqual(len(state.ops['anotherhost']), 0) # Check we can't call it inside another op state.active = True state.in_op = True with self.assertRaises(PyinfraError): server.shell('echo "hi 3"') pseudo_state.reset() pseudo_host.reset()
def loop_hosts(): # This actually does the op build for host in inventory: pseudo_host.set(host) exec_file(arguments['deploy']) logger.info('{0} {1}'.format( '[{}]'.format(colored(host.name, attrs=['bold'])), colored('Ready', 'green')))
def test_pseudo_host_attr(self): host = _create_host() pseudo_host.set(host) with self.assertRaises(AttributeError): host.hello setattr(host, 'hello', 'world') assert pseudo_host.hello == host.hello
def test_pseudo_host_class_attr(self): host = _create_host() pseudo_host.set(host) assert pseudo_host.isset() is True with self.assertRaises(AttributeError): host.hello setattr(Host, 'hello', 'class_world') setattr(host, 'hello', 'instance_world') assert pseudo_host.hello == host.hello # Reset and check fallback to class variable pseudo_host.reset() assert pseudo_host.isset() is False assert pseudo_host.hello == 'class_world'
def test_op_line_numbers(self): inventory = make_inventory() state = State(inventory, Config()) connect_all(state) # Add op to both hosts add_op(state, server.shell, 'echo "hi"') # Add op to just the second host - using the pseudo modules such that # it replicates a deploy file. pseudo_state.set(state) pseudo_host.set(inventory['anotherhost']) first_pseudo_hash = server.user('anotherhost_user').hash first_pseudo_call_line = getframeinfo(currentframe()).lineno - 1 # Add op to just the first host - using the pseudo modules such that # it replicates a deploy file. pseudo_state.set(state) pseudo_host.set(inventory['somehost']) second_pseudo_hash = server.user('somehost_user').hash second_pseudo_call_line = getframeinfo(currentframe()).lineno - 1 pseudo_state.reset() pseudo_host.reset() # Ensure there are two ops op_order = state.get_op_order() self.assertEqual(len(op_order), 3) # And that the two ops above were called in the expected order self.assertEqual(op_order[1], first_pseudo_hash) self.assertEqual(op_order[2], second_pseudo_hash) # And that they have the expected line numbers self.assertEqual( state.op_line_numbers_to_hash.get((0, first_pseudo_call_line)), first_pseudo_hash, ) self.assertEqual( state.op_line_numbers_to_hash.get((0, second_pseudo_call_line)), second_pseudo_hash, ) # Ensure somehost has two ops and anotherhost only has the one self.assertEqual(len(state.ops[inventory.get_host('somehost')]), 2) self.assertEqual(len(state.ops[inventory.get_host('anotherhost')]), 2)
def load_deploy_file(state, filename): state.current_deploy_filename = filename # Copy the inventory hosts (some might be removed during deploy) hosts = list(state.inventory.iter_active_hosts()) for host in hosts: pseudo_host.set(host) exec_file(filename) logger.info('{0}{1} {2}'.format( host.print_prefix, click.style('Ready:', 'green'), click.style(filename, bold=True), )) # Remove any pseudo host pseudo_host.reset()
def load_deploy_file(state, filename): # Copy the inventory hosts (some might be removed during deploy) hosts = list(state.inventory) for host in hosts: if not state.is_host_in_limit(host): continue pseudo_host.set(host) exec_file(filename) logger.info('{0}{1} {2}'.format( host.print_prefix, click.style('Ready:', 'green'), click.style(filename, bold=True), )) # Remove any pseudo host pseudo_host.reset()
def load_deploy_file(state, filename, progress): for host in state.inventory: pseudo_host.set(host) exec_file(filename) state.ready_host(host) progress() logger.info('{0} {1} {2}'.format( '[{}]'.format(click.style(host.name, bold=True)), click.style('Ready:', 'green'), click.style(filename, bold=True), )) # Remove any pseudo host pseudo_host.reset() # Un-ready the hosts - this is so that any hooks or callbacks during the # deploy can still use facts as expected. state.ready_host_names = set()
def load_deploy_file(state, filename): # Copy the inventory hosts (some might be removed during deploy) hosts = list(state.inventory) for host in hosts: # Don't load for anything within our (top level, --limit) limit if (isinstance(state.limit_hosts, list) and host not in state.limit_hosts): continue pseudo_host.set(host) exec_file(filename) logger.info('{0}{1} {2}'.format( host.print_prefix, click.style('Ready:', 'green'), click.style(filename, bold=True), )) # Remove any pseudo host pseudo_host.reset()
def test_cli_op_line_numbers(self): inventory = make_inventory() state = State(inventory, Config()) connect_all(state) pyinfra.is_cli = True pseudo_state.set(state) # Add op to both hosts for name in ('anotherhost', 'somehost'): pseudo_host.set(inventory.get_host(name)) server.shell( 'echo hi') # note this is called twice but on *the same line* # Add op to just the second host - using the pseudo modules such that # it replicates a deploy file. pseudo_host.set(inventory.get_host('anotherhost')) first_pseudo_hash = server.user('anotherhost_user').hash first_pseudo_call_line = getframeinfo(currentframe()).lineno - 1 # Add op to just the first host - using the pseudo modules such that # it replicates a deploy file. pseudo_host.set(inventory.get_host('somehost')) second_pseudo_hash = server.user('somehost_user').hash second_pseudo_call_line = getframeinfo(currentframe()).lineno - 1 pseudo_state.reset() pseudo_host.reset() pyinfra.is_cli = False # Ensure there are two ops op_order = state.get_op_order() assert len(op_order) == 3 # And that the two ops above were called in the expected order assert op_order[1] == first_pseudo_hash assert op_order[2] == second_pseudo_hash # And that they have the expected line numbers assert state.op_line_numbers_to_hash.get( (0, first_pseudo_call_line)) == first_pseudo_hash assert state.op_line_numbers_to_hash.get( (0, second_pseudo_call_line)) == second_pseudo_hash # Ensure somehost has two ops and anotherhost only has the one assert len(state.ops[inventory.get_host('somehost')]) == 2 assert len(state.ops[inventory.get_host('anotherhost')]) == 2
def test_pseudo_host_eq(self): host = _create_host() pseudo_host.set(host) assert host == pseudo_host
def test_pseudo_host_str(self): host = _create_host() pseudo_host.set(host) assert str(pseudo_host) == 'None'
config.SUDO_USER = arguments['sudo_user'] if arguments['su_user']: config.SU_USER = arguments['su_user'] if arguments['parallel']: config.PARALLEL = arguments['parallel'] # If --debug-data dump & exit if arguments['debug_data']: print_data(inventory) _exit() # Load any hooks/config from the deploy file w/fake state & host pseudo_state.set(FakeState()) pseudo_host.set(FakeHost()) load_deploy_config(arguments['deploy'], config) pseudo_host.reset() pseudo_state.reset() # Create/set the state state = State(inventory, config) state.is_cli = True state.deploy_dir = deploy_dir # Setup printing on the new state print_output = arguments['verbose'] > 0 if arguments['deploy'] is None and arguments['op'] is None: print_fact_output = print_output else: print_fact_output = arguments['verbose'] > 1
def jsontest_function(self, test_name, test_data): # Create a host with this tests facts and attach to pseudo host host = create_host(facts=test_data.get('facts', {})) pseudo_host.set(host) allowed_exception = test_data.get('exception') kwargs = test_data.get('kwargs', {}) kwargs['state'] = pseudo_state kwargs['host'] = pseudo_host with patch_files(test_data.get('files', []), test_data.get('directories', [])): try: output_commands = unroll_generators( op._pyinfra_op(*test_data.get('args', []), ** kwargs)) or [] 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 commands = [] for command in output_commands: if isinstance( command, six.string_types): # matches pyinfra/api/operation.py command = StringCommand(command.strip()) if isinstance(command, StringCommand): json_command = get_command_string(command) elif isinstance(command, dict): command['command'] = get_command_string( command['command']).strip() json_command = command elif isinstance(command, FunctionCommand): func_name = (command.function if command.function == '__func__' else command.function.__name__) json_command = [ func_name, list(command.args), command.kwargs, ] elif isinstance(command, FileUploadCommand): if hasattr(command.src, 'read'): command.src.seek(0) data = command.src.read() else: data = command.src json_command = ['upload', data, command.dest] elif isinstance(command, FileDownloadCommand): json_command = ['download', command.src, command.dest] else: raise Exception( '{0} is not a valid command!'.format(command)) if command.executor_kwargs: command.executor_kwargs['command'] = json_command json_command = command.executor_kwargs commands.append(json_command) try: assert commands == test_data['commands'] except AssertionError as e: print() print('--> COMMANDS OUTPUT:') print(json.dumps(commands, indent=4, default=json_encode)) print('--> TEST WANTS:') print( json.dumps( test_data['commands'], indent=4, default=json_encode, )) raise e
def jsontest_function(self, test_name, test_data): # Create a host with this tests facts and attach to pseudo host host = create_host(facts=test_data.get('facts', {})) pseudo_host.set(host) allowed_exception = test_data.get('exception') with patch_files(test_data.get('files', []), test_data.get('directories', [])): try: output_commands = unroll_generators( op._pyinfra_op(pseudo_state, pseudo_host, *test_data.get('args', []), **test_data.get('kwargs', {}))) or [] 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 self.assertEqual(e.args[0], allowed_exception['message']) return raise commands = [] for command in output_commands: if isinstance(command, six.string_types): commands.append(command.strip()) elif isinstance(command, dict): command['command'] = command['command'].strip() commands.append(command) elif isinstance(command, tuple): if command[0] == '__func__': commands.append([ command[0], list(command[1]), command[2], ]) elif isinstance(command[0], FunctionType): commands.append([ command[0].__name__, list(command[1]), command[2], ]) else: if hasattr(command[0], 'read'): command[0].seek(0) data = command[0].read() else: data = command[0] commands.append([data, command[1]]) else: commands.append(command) try: self.assertEqual(commands, test_data['commands']) except AssertionError as e: print() print('--> COMMANDS OUTPUT:') print(json.dumps(commands, indent=4, default=json_encode)) print('--> TEST WANTS:') print( json.dumps( test_data['commands'], indent=4, default=json_encode, )) raise e
def test_pseudo_host_repr(self): host = _create_host() pseudo_host.set(host) assert repr(pseudo_host) == 'PseudoModule(Host):Host(None)'