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 test_deploy(self): task_file_path = path.join('tests', 'deploy', 'tasks', 'a_task.py') nested_task_path = path.join('tests', 'deploy', 'tasks', 'another_task.py') correct_op_name_and_host_names = [ ('First main operation', True), # true for all hosts ('Second main operation', ('somehost', )), ('{0} | First task operation'.format(task_file_path), ('anotherhost', )), ('{0} | Task order loop 1'.format(task_file_path), ('anotherhost', )), ('{0} | 2nd Task order loop 1'.format(task_file_path), ('anotherhost', )), ('{0} | Task order loop 2'.format(task_file_path), ('anotherhost', )), ('{0} | 2nd Task order loop 2'.format(task_file_path), ('anotherhost', )), ( '{0} | {1} | Second task operation'.format( task_file_path, nested_task_path), ('anotherhost', ), ), ('{0} | First task operation'.format(task_file_path), True), ('{0} | Task order loop 1'.format(task_file_path), True), ('{0} | 2nd Task order loop 1'.format(task_file_path), True), ('{0} | Task order loop 2'.format(task_file_path), True), ('{0} | 2nd Task order loop 2'.format(task_file_path), True), ('{0} | {1} | Second task operation'.format( task_file_path, nested_task_path), True), ('My deploy | First deploy operation', True), ('My deploy | My nested deploy | First nested deploy operation', True), ('My deploy | Second deploy operation', True), ('Loop-0 main operation', True), ('Loop-1 main operation', True), ('Third main operation', True), ('Order loop 1', True), ('2nd Order loop 1', True), ('Order loop 2', True), ('2nd Order loop 2', True), ('Final limited operation', ('somehost', )), ] # Run 3 iterations of the test - each time shuffling the order of the # hosts - ensuring that the ordering has no effect on the operation order. for _ in range(3): pseudo_state.reset() hosts = ['somehost', 'anotherhost', 'someotherhost'] shuffle(hosts) result = run_cli( ','.join(hosts), path.join('tests', 'deploy', 'deploy.py'), ) assert result.exit_code == 0, result.stderr self._assert_op_data(correct_op_name_and_host_names)
def _do_test_deploy(self): pseudo_state.reset() correct_op_name_and_host_names = [ ('First main operation', True), # true for all hosts ('Second main operation', ('somehost', )), ('tests/deploy/tasks/a_task.py | First task operation', ('anotherhost', )), ('tests/deploy/tasks/a_task.py | Second task operation', ('anotherhost', )), ('tests/deploy/tasks/a_task.py | First task operation', True), ('tests/deploy/tasks/a_task.py | Second task operation', True), ('Loop-0 main operation', True), ('Loop-1 main operation', True), ('Third main operation', True), ('Order loop 1', True), ('2nd Order loop 1', True), ('Order loop 2', True), ('2nd Order loop 2', True), ('Final limited operation', ('somehost', )), ] hosts = ['somehost', 'anotherhost', 'someotherhost'] shuffle(hosts) result = run_cli( ','.join(hosts), path.join('tests', 'deploy', 'deploy.py'), ) assert result.exit_code == 0 state = pseudo_state op_order = state.get_op_order() self.assertEqual( len(correct_op_name_and_host_names), len(op_order), 'Incorrect number of operations detected', ) for i, (correct_op_name, correct_host_names) in enumerate( correct_op_name_and_host_names, ): op_hash = op_order[i] op_meta = state.op_meta[op_hash] self.assertEqual(list(op_meta['names'])[0], correct_op_name) for host in state.inventory: op_hashes = state.meta[host]['op_hashes'] if correct_host_names is True or host.name in correct_host_names: self.assertIn(op_hash, op_hashes) else: self.assertNotIn(op_hash, op_hashes)
def test_interdependent_deploy(self): pseudo_state.reset() result = run_cli( 'somehost', path.join('tests', 'deploy', 'deploy_interdependent.py'), ) assert result.exit_code == 0, result.stderr # Check every operation had commands/changes - this ensures that each # combo (add/remove/add) always had changes. for host, ops in pseudo_state.ops.items(): for _, op in ops.items(): assert len(op['commands']) > 0
def test_op_call_rejects_in_op(self): state = FakeState() pyinfra.is_cli = True pseudo_state.set(state) with self.assertRaises(PyinfraError) as context: server.shell() pyinfra.is_cli = False pseudo_state.reset() assert context.exception.args[0] == ( 'Nested operation called without state/host: ' 'server.shell (line 387 in tests/test_api/test_api_operations.py)')
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_legacy_deploy(self): pseudo_state.reset() result = run_cli( 'somehost', path.join('tests', 'deploy', 'deploy_legacy.py'), ) assert result.exit_code == 0, result.stderr correct_op_name_and_host_names = [ ('First main operation', True), ('My deploy | My nested deploy | First nested deploy operation', True), ('My deploy | Second deploy operation', True), ] self._assert_op_data(correct_op_name_and_host_names)
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 test_op_call_rejects_in_op(self): state = FakeState() pyinfra.is_cli = True pseudo_state.set(state) with self.assertRaises(PyinfraError) as context: server.shell() call_line = getframeinfo(currentframe()).lineno - 1 pyinfra.is_cli = False pseudo_state.reset() assert context.exception.args[0] == ( 'Nested operation called without state/host: ' 'server.shell (line {0} in tests/test_api/test_api_operations.py)'. format(call_line))
def setUp(self): pseudo_state.reset()
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 state.print_output = print_output # -v state.print_fact_info = print_output # -v