예제 #1
0
    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()
예제 #2
0
    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)
예제 #3
0
    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)
예제 #4
0
    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
예제 #5
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)')
예제 #6
0
    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
예제 #7
0
    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)
예제 #8
0
    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)
예제 #9
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()
        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))
예제 #10
0
 def setUp(self):
     pseudo_state.reset()
예제 #11
0
        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