示例#1
0
    def evaluate_results(self, callback):
        """ prepare the result of runner call for use with RunnerResults. """

        for server, result in callback.unreachable.items():
            log.error(u'{} could not be reached'.format(server))
            log.debug(u'ansible-output =>\n{}'.format(pformat(result)))

            if self.api.ignore_unreachable:
                continue

            self.trigger_event(server, 'on_unreachable_host', (self, server))

        for server, answer in callback.contacted.items():

            success = answer['success']
            result = answer['result']

            # none of the modules in our tests hit the 'failed' result
            # codepath (which seems to not be implemented by all modules)
            # seo we ignore this branch since it's rather trivial
            if result.get('failed'):  # pragma: no cover
                success = False

            if 'rc' in result:
                if self.api.is_valid_return_code(result['rc']):
                    success = True

            # Add success to result
            result['success'] = success

            if not success:
                log.error(u'{} failed on {}'.format(self, server))
                log.debug(u'ansible-output =>\n{}'.format(pformat(result)))

                if self.api.ignore_errors:
                    continue

                self.trigger_event(server, 'on_module_error',
                                   (self, server, result))

        # XXX this is a weird structure because RunnerResults still works
        # like it did with Ansible 1.x, where the results where structured
        # like this
        return RunnerResults({
            'contacted': {
                server: answer['result']
                for server, answer in callback.contacted.items()
            },
            'unreachable': {
                server: result
                for server, result in callback.unreachable.items()
            }
        })
示例#2
0
    def evaluate_results(self, callback):
        """ prepare the result of runner call for use with RunnerResults. """

        for server, result in callback.unreachable.items():
            log.error(u'{} could not be reached'.format(server))
            log.debug(u'ansible-output =>\n{}'.format(pformat(result)))

            if self.api.ignore_unreachable:
                continue

            self.trigger_event(server, 'on_unreachable_host', (
                self, server
            ))

        for server, answer in callback.contacted.items():

            success = answer['success']
            result = answer['result']

            # none of the modules in our tests hit the 'failed' result
            # codepath (which seems to not be implemented by all modules)
            # seo we ignore this branch since it's rather trivial
            if result.get('failed'):  # pragma: no cover
                success = False

            if 'rc' in result:
                if self.api.is_valid_return_code(result['rc']):
                    success = True

            if not success:
                log.error(u'{} failed on {}'.format(self, server))
                log.debug(u'ansible-output =>\n{}'.format(pformat(result)))

                if self.api.ignore_errors:
                    continue

                self.trigger_event(server, 'on_module_error', (
                    self, server, result
                ))

        # XXX this is a weird structure because RunnerResults still works
        # like it did with Ansible 1.x, where the results where structured
        # like this
        return RunnerResults({
            'contacted': {
                server: answer['result']
                for server, answer in callback.contacted.items()
            }
        })
示例#3
0
    def evaluate_results(self, callback):
        """ prepare the result of runner call for use with RunnerResults. """

        for server, result in callback.unreachable.items():
            log.error(u'{} could not be reached'.format(server))
            log.debug(u'ansible-output =>\n{}'.format(pformat(result)))

            if self.api.ignore_unreachable:
                continue

            self.trigger_event(server, 'on_unreachable_host', (
                self, server
            ))

        for server, answer in callback.contacted.items():

            success = answer['success']
            result = answer['result']

            if 'failed' in result:
                success = False

            if 'rc' in result:
                if self.api.is_valid_return_code(result['rc']):
                    success = True

            if not success:
                log.error(u'{} failed on {}'.format(self, server))
                log.debug(u'ansible-output =>\n{}'.format(pformat(result)))

                if self.api.ignore_errors:
                    continue

                self.trigger_event(server, 'on_module_error', (
                    self, server, result
                ))

        # XXX this is a weird structure because RunnerResults still works
        # like it did with Ansible 1.x, where the results where structured
        # like this
        return RunnerResults({
            'contacted': {
                server: answer['result']
                for server, answer in callback.contacted.items()
            }
        })
    def evaluate_results(self, callback):
        """ prepare the result of runner call for use with RunnerResults. """

        for server, result in callback.unreachable.items():
            log.error(u'{} could not be reached'.format(server))
            log.debug(u'ansible-output =>\n{}'.format(pformat(result)))

            if self.api.ignore_unreachable:
                continue

            self.trigger_event(server, 'on_unreachable_host', (self, server))

        for server, answer in callback.contacted.items():

            success = answer['success']
            result = answer['result']

            if result.get('failed'):
                success = False

            if 'rc' in result:
                if self.api.is_valid_return_code(result['rc']):
                    success = True

            if not success:
                log.error(u'{} failed on {}'.format(self, server))
                log.debug(u'ansible-output =>\n{}'.format(pformat(result)))

                if self.api.ignore_errors:
                    continue

                self.trigger_event(server, 'on_module_error',
                                   (self, server, result))

        # XXX this is a weird structure because RunnerResults still works
        # like it did with Ansible 1.x, where the results where structured
        # like this
        return RunnerResults({
            'contacted': {
                server: answer['result']
                for server, answer in callback.contacted.items()
            }
        })
示例#5
0
    def parse_results(self, results):
        """ Parses the result of runner call. """

        unreachable_servers = results['dark']

        for server, result in unreachable_servers.items():
            log.error(u'{} could not be reached'.format(server))
            log.debug(u'ansible-output =>\n{}'.format(pformat(result)))

            if self.api.ignore_unreachable:
                continue

            self.trigger_event(server, 'on_unreachable_host', (
                self, server
            ))

        contacted_servers = results['contacted']

        for server, result in contacted_servers.items():
            failure = False

            if 'failed' in result:
                failure = True

            if 'rc' in result:
                if not self.api.is_valid_return_code(result['rc']):
                    failure = True

            if failure:
                log.error(u'{} failed on {}'.format(self, server))
                log.debug(u'ansible-output =>\n{}'.format(pformat(result)))

                if self.api.ignore_errors:
                    continue

                self.trigger_event(server, 'on_module_error', (
                    self, server, result
                ))

        return results
示例#6
0
    def execute(self, *args, **kwargs):
        """ Puts args and kwargs in a way ansible can understand. Calls ansible
        and interprets the result.

        """
        assert self.is_hooked_up, "the module should be hooked up to the api"

        if set_global_context:
            set_global_context(self.api.options)

        # legacy key=value pairs shorthand approach
        if args:
            self.module_args = module_args = self.get_module_args(args, kwargs)
        else:
            self.module_args = module_args = kwargs

        loader = DataLoader()
        inventory_manager = SourcelessInventoryManager(loader=loader)

        for host, port in self.api.hosts_with_ports:
            inventory_manager._inventory.add_host(host, group='all', port=port)

        for key, value in self.api.options.extra_vars.items():
            inventory_manager._inventory.set_variable('all', key, value)

        variable_manager = VariableManager(
            loader=loader, inventory=inventory_manager)

        play_source = {
            'name': "Suitable Play",
            'hosts': 'all',
            'gather_facts': 'no',
            'tasks': [{
                'action': {
                    'module': self.module_name,
                    'args': module_args,
                },
                'environment': self.api.environment,
            }]
        }

        try:
            play = Play.load(
                play_source,
                variable_manager=variable_manager,
                loader=loader,
            )

            if self.api.strategy:
                play.strategy = self.api.strategy

            log.info(
                u'running {}'.format(u'- {module_name}: {module_args}'.format(
                    module_name=self.module_name,
                    module_args=module_args
                ))
            )

            start = datetime.utcnow()
            task_queue_manager = None
            callback = SilentCallbackModule()

            # ansible uses various levels of verbosity (from -v to -vvvvvv)
            # offering various amounts of debug information
            #
            # we keep it a bit simpler by activating all of it during debug,
            # and falling back to the default of 0 otherwise
            verbosity = self.api.options.verbosity == logging.DEBUG and 6 or 0

            with ansible_verbosity(verbosity):

                # host_key_checking is special, since not each connection
                # plugin handles it the same way, we need to apply both
                # environment variable and Ansible constant when running a
                # command in the runner to be successful
                with host_key_checking(self.api.host_key_checking):
                    kwargs = dict(
                        inventory=inventory_manager,
                        variable_manager=variable_manager,
                        loader=loader,
                        options=self.api.options,
                        passwords=getattr(self.api.options, 'passwords', {}),
                        stdout_callback=callback
                    )

                    if set_global_context:
                        del kwargs['options']

                    task_queue_manager = TaskQueueManager(**kwargs)

                    try:
                        task_queue_manager.run(play)
                    except SystemExit:

                        # Mitogen forks our process and exits it in one
                        # instance before returning
                        #
                        # This is fine, but it does lead to a very messy exit
                        # by py.test which will essentially return with a test
                        # that is first successful and then failed as each
                        # forked process dies.
                        #
                        # To avoid this we commit suicide if we are run inside
                        # a pytest session. Normally this would just result
                        # in a exit code of zero, which is good.
                        if 'pytest' in sys.modules:
                            try:
                                atexit._run_exitfuncs()
                            except Exception:
                                pass
                            os.kill(os.getpid(), signal.SIGKILL)

                        raise
        finally:
            if task_queue_manager is not None:
                task_queue_manager.cleanup()

            if set_global_context:

                # Ansible 2.8 introduces a global context which persists
                # during the lifetime of the process - for Suitable this
                # singleton/cache needs to be cleared after each call
                # to make sure that API calls do not carry over state.
                #
                # The docs hint at a future inclusion of local contexts, which
                # would of course be preferable.
                from ansible.utils.context_objects import GlobalCLIArgs
                GlobalCLIArgs._Singleton__instance = None

        log.debug(u'took {} to complete'.format(datetime.utcnow() - start))

        return self.evaluate_results(callback)
示例#7
0
    def execute(self, *args, **kwargs):
        """ Puts args and kwargs in a way ansible can understand. Calls ansible
        and interprets the result.

        """
        assert self.is_hooked_up, "the module should be hooked up to the api"

        if set_global_context:
            set_global_context(self.api.options)

        # legacy key=value pairs shorthand approach
        if args:
            self.module_args = module_args = self.get_module_args(args, kwargs)
        else:
            self.module_args = module_args = kwargs

        loader = DataLoader()
        inventory_manager = SourcelessInventoryManager(loader=loader)

        for host, host_variables in self.api.inventory.items():
            inventory_manager._inventory.add_host(host, group='all')
            for key, value in host_variables.items():
                inventory_manager._inventory.set_variable(host, key, value)

        for key, value in self.api.options.extra_vars.items():
            inventory_manager._inventory.set_variable('all', key, value)

        variable_manager = VariableManager(loader=loader,
                                           inventory=inventory_manager)

        play_source = {
            'name':
            "Suitable Play",
            'hosts':
            'all',
            'gather_facts':
            'no',
            'tasks': [{
                'action': {
                    'module': self.module_name,
                    'args': module_args,
                },
                'environment': self.api.environment,
            }]
        }

        try:
            play = Play.load(
                play_source,
                variable_manager=variable_manager,
                loader=loader,
            )

            if self.api.strategy:
                play.strategy = self.api.strategy

            log.info(u'running {}'.format(
                u'- {module_name}: {module_args}'.format(
                    module_name=self.module_name, module_args=module_args)))

            start = datetime.utcnow()
            task_queue_manager = None
            callback = SilentCallbackModule()

            # ansible uses various levels of verbosity (from -v to -vvvvvv)
            # offering various amounts of debug information
            #
            # we keep it a bit simpler by activating all of it during debug,
            # and falling back to the default of 0 otherwise
            verbosity = self.api.options.verbosity == logging.DEBUG and 6 or 0

            with ansible_verbosity(verbosity):

                # host_key_checking is special, since not each connection
                # plugin handles it the same way, we need to apply both
                # environment variable and Ansible constant when running a
                # command in the runner to be successful
                with host_key_checking(self.api.host_key_checking):
                    kwargs = dict(inventory=inventory_manager,
                                  variable_manager=variable_manager,
                                  loader=loader,
                                  options=self.api.options,
                                  passwords=getattr(self.api.options,
                                                    'passwords', {}),
                                  stdout_callback=callback)

                    if set_global_context:
                        del kwargs['options']

                    task_queue_manager = TaskQueueManager(**kwargs)

                    try:
                        task_queue_manager.run(play)
                    except SystemExit:

                        # Mitogen forks our process and exits it in one
                        # instance before returning
                        #
                        # This is fine, but it does lead to a very messy exit
                        # by py.test which will essentially return with a test
                        # that is first successful and then failed as each
                        # forked process dies.
                        #
                        # To avoid this we commit suicide if we are run inside
                        # a pytest session. Normally this would just result
                        # in a exit code of zero, which is good.
                        if 'pytest' in sys.modules:
                            try:
                                atexit._run_exitfuncs()
                            except Exception:
                                pass
                            os.kill(os.getpid(), signal.SIGKILL)

                        raise
        finally:
            if task_queue_manager is not None:
                task_queue_manager.cleanup()

            if set_global_context:
                # Ansible 2.8 introduces a global context which persists
                # during the lifetime of the process - for Suitable this
                # singleton/cache needs to be cleared after each call
                # to make sure that API calls do not carry over state.
                #
                # The docs hint at a future inclusion of local contexts, which
                # would of course be preferable.
                from ansible.utils.context_objects import GlobalCLIArgs
                GlobalCLIArgs._Singleton__instance = None

        log.debug(u'took {} to complete'.format(datetime.utcnow() - start))

        return self.evaluate_results(callback)
示例#8
0
    def execute(self, *args, **kwargs):
        """ Puts args and kwargs in a way ansible can understand. Calls ansible
        and interprets the result.

        """

        assert self.is_hooked_up, "the module should be hooked up to the api"

        # legacy key=value pairs shorthand approach
        if args:
            self.module_args = module_args = self.get_module_args(args, kwargs)
        else:
            self.module_args = module_args = kwargs

        loader = DataLoader()
        inventory_manager = SourcelessInventoryManager(loader=loader)

        hosts_with_ports = tuple(self.api.hosts_with_ports)

        for host, port in hosts_with_ports:
            inventory_manager._inventory.add_host(host, group='all', port=port)

        for key, value in self.api.options.extra_vars.items():
            inventory_manager._inventory.set_variable('all', key, value)

        variable_manager = VariableManager(
            loader=loader, inventory=inventory_manager)

        play_source = {
            'name': "Suitable Play",
            'hosts': [h for h, p in hosts_with_ports],  # *must* be a list
            'gather_facts': 'no',
            'tasks': [{
                'action': {
                    'module': self.module_name,
                    'args': module_args,
                },
                'environment': self.api.environment
            }]
        }

        play = Play.load(
            play_source,
            variable_manager=variable_manager,
            loader=loader,
        )

        if self.api.strategy:
            play.strategy = self.api.strategy

        log.info(u'running {}'.format(u'- {module_name}: {module_args}'.format(
            module_name=self.module_name,
            module_args=module_args
        )))

        start = datetime.utcnow()
        task_queue_manager = None
        callback = SilentCallbackModule()

        # ansible uses various levels of verbosity (from -v to -vvvvvv)
        # offering various amounts of debug information
        #
        # we keep it a bit simpler by activating all of it during debug, and
        # falling back to the default of 0 otherwise
        verbosity = self.api.options.verbosity == logging.DEBUG and 6 or 0

        try:
            with ansible_verbosity(verbosity):
                task_queue_manager = TaskQueueManager(
                    inventory=inventory_manager,
                    variable_manager=variable_manager,
                    loader=loader,
                    options=self.api.options,
                    passwords=getattr(self.api.options, 'passwords', {}),
                    stdout_callback=callback
                )
                task_queue_manager.run(play)
        finally:
            if task_queue_manager is not None:
                task_queue_manager.cleanup()

        log.debug(u'took {} to complete'.format(datetime.utcnow() - start))

        return self.evaluate_results(callback)
示例#9
0
    def execute(self, *args, **kwargs):
        """ Puts args and kwargs in a way ansible can understand. Calls ansible
        and interprets the result.

        """

        assert self.is_hooked_up, "the module should be hooked up to the api"

        # legacy key=value pairs shorthand approach
        if args:
            self.module_args = module_args = self.get_module_args(args, kwargs)
        else:
            self.module_args = module_args = kwargs

        loader = DataLoader()
        inventory_manager = SourcelessInventoryManager(loader=loader)

        hosts_with_ports = tuple(self.api.hosts_with_ports)

        for host, port in hosts_with_ports:
            inventory_manager._inventory.add_host(host, group='all', port=port)

        for key, value in self.api.options.extra_vars.items():
            inventory_manager._inventory.set_variable('all', key, value)

        variable_manager = VariableManager(loader=loader,
                                           inventory=inventory_manager)

        play_source = {
            'name':
            "Suitable Play",
            'hosts': [h for h, p in hosts_with_ports],  # *must* be a list
            'gather_facts':
            'no',
            'tasks': [{
                'action': {
                    'module': self.module_name,
                    'args': module_args,
                },
                'environment': self.api.environment
            }]
        }

        play = Play.load(
            play_source,
            variable_manager=variable_manager,
            loader=loader,
        )

        if self.api.strategy:
            play.strategy = self.api.strategy

        log.info(u'running {}'.format(u'- {module_name}: {module_args}'.format(
            module_name=self.module_name, module_args=module_args)))

        start = datetime.utcnow()
        task_queue_manager = None
        callback = SilentCallbackModule()

        # ansible uses various levels of verbosity (from -v to -vvvvvv)
        # offering various amounts of debug information
        #
        # we keep it a bit simpler by activating all of it during debug, and
        # falling back to the default of 0 otherwise
        verbosity = self.api.options.verbosity == logging.DEBUG and 6 or 0

        try:
            with ansible_verbosity(verbosity):
                task_queue_manager = TaskQueueManager(
                    inventory=inventory_manager,
                    variable_manager=variable_manager,
                    loader=loader,
                    options=self.api.options,
                    passwords=getattr(self.api.options, 'passwords', {}),
                    stdout_callback=callback)
                task_queue_manager.run(play)
        finally:
            if task_queue_manager is not None:
                task_queue_manager.cleanup()

        log.debug(u'took {} to complete'.format(datetime.utcnow() - start))

        return self.evaluate_results(callback)