Example #1
0
        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
Example #2
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()
Example #3
0
 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'
Example #6
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)
Example #7
0
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()
Example #8
0
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()
Example #9
0
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()
Example #10
0
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()
Example #11
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
 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'
Example #14
0
            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
Example #15
0
        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
Example #16
0
        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)'