コード例 #1
0
    def take_action(self, args):
        test_cases = []
        if args.playbook is not None:
            playbooks = args.playbook
            results = (models.TaskResult().query.join(models.Task).filter(
                models.TaskResult.task_id == models.Task.id).filter(
                    models.Task.playbook_id.in_(playbooks)))
        else:
            results = models.TaskResult().query.all()

        for result in results:
            task_name = result.task.name
            if not task_name:
                task_name = result.task.action
            additional_results = {
                'host': result.host.name,
                'playbook_path': result.task.playbook.path
            }
            result_str = jsonutils.dumps(additional_results)
            test_path = \
                u'{playbook_file}.{play_name}'.format(
                    playbook_file=os.path.basename(result.task.playbook.path),
                    play_name=result.task.play.name)
            test_case = TestCase(name=task_name,
                                 classname=test_path,
                                 elapsed_sec=result.duration.seconds,
                                 stdout=result_str)
            if result.status == 'skipped':
                test_case.add_skipped_info(message=result.result)
            elif ((result.status in ('failed', 'unreachable')
                   and result.ignore_errors is False
                   and 'EXPECTED FAILURE' not in task_name
                   and 'TOGGLE RESULT' not in task_name)
                  or (result.status == 'ok' and 'TOGGLE RESULT' in task_name)):
                test_case.add_failure_info(message=result.result)
            test_cases.append(test_case)
        test_suite = TestSuite('Ansible Tasks', test_cases)

        # TODO: junit_xml doesn't order the TestCase parameters.
        # This makes it so the order of the parameters for the same exact
        # TestCase is not guaranteed to be the same and thus results in a
        # different stdout (or file). This is easily reproducible on Py3.
        xml_string = six.text_type(test_suite.to_xml_string([test_suite]))
        if args.output_file == '-':
            if six.PY2:
                sys.stdout.write(encodeutils.safe_encode(xml_string))
            else:
                sys.stdout.buffer.write(encodeutils.safe_encode(xml_string))
        else:
            with open(args.output_file, 'wb') as f:
                f.write(encodeutils.safe_encode(xml_string))
コード例 #2
0
    def log_task(self, result, status, **kwargs):
        '''`log_task` is called when an individual task instance on a single
        host completes. It is responsible for logging a single
        `TaskResult` record to the database.'''
        LOG.debug('logging task result for task %s (%s), host %s',
                  self.task.name, self.task.id, result._host.name)

        result.task_start = self.task.time_start
        result.task_end = datetime.now()
        host = self.get_or_create_host(result._host.name)
        if self.playbook not in host.playbooks:
            host.playbooks.append(self.playbook)

        self.taskresult = models.TaskResult(
            task=self.task,
            host=host,
            time_start=result.task_start,
            time_end=result.task_end,
            result=json.dumps(result._result),
            status=status,
            changed=result._result.get('changed', False),
            failed=result._result.get('failed', False),
            skipped=result._result.get('skipped', False),
            unreachable=result._result.get('unreachable', False),
            ignore_errors=kwargs.get('ignore_errors', False),
        )

        db.session.add(self.taskresult)

        if self.task.action == 'setup' and 'ansible_facts' in result._result:
            values = json.dumps(result._result['ansible_facts'])
            facts = models.HostFacts(values=values)
            host.facts = facts

            db.session.add(facts)
コード例 #3
0
ファイル: common.py プロジェクト: 40a/ara
def ansible_run(complete=True, gather_facts=True):
    '''Simulate a simple Ansible run by creating the
    expected database objects.  This roughly approximates the
    following playbook:

        - hosts: host-<int>
          gather_facts: true
          tasks:
            - test-action:

    Where `<int>` is a random integer generated each time this
    function is called.

    Set the `complete` parameter to `False` to simulate an
    aborted Ansible run.
    Set the `gathered_facts` parameter to `False` to simulate a run with no
    facts gathered.
    '''

    playbook = m.Playbook(path='testing.yml')
    play = m.Play(playbook=playbook, name='test play')
    task = m.Task(play=play, playbook=playbook, action='test-action')
    host = m.Host(name='host-%04d' % random.randint(0, 9999))
    host.playbooks.append(playbook)
    result = m.TaskResult(task=task,
                          status='ok',
                          host=host,
                          result='this is a test')

    ctx = dict(playbook=playbook,
               play=play,
               task=task,
               host=host,
               result=result)

    if gather_facts:
        facts = m.HostFacts(host=host, values='{"fact": "value"}')
        ctx['facts'] = facts

    for obj in ctx.values():
        if hasattr(obj, 'start'):
            obj.start()
        db.session.add(obj)

    db.session.commit()

    if complete:
        stats = m.Stats(playbook=playbook, host=host)
        ctx['stats'] = stats
        db.session.add(stats)
        ctx['playbook'].complete = True

        for obj in ctx.values():
            if hasattr(obj, 'stop'):
                obj.stop()

    db.session.commit()

    return ctx
コード例 #4
0
ファイル: log_ara.py プロジェクト: sunfinite/ara
    def log_task(self, result, status, **kwargs):
        """
        'log_task' is called when an individual task instance on a single
        host completes. It is responsible for logging a single
        'TaskResult' record to the database.
        """
        LOG.debug('logging task result for task %s (%s), host %s',
                  self.task.name, self.task.id, result._host.get_name())

        # An include_role task might end up putting an IncludeRole object
        # inside the result object which we don't need
        # https://github.com/ansible/ansible/issues/30385
        if 'include_role' in result._result:
            del result._result['include_role']

        result.task_start = self.task.time_start
        result.task_end = datetime.now()
        host = self.get_or_create_host(result._host.get_name())

        # Use Ansible's CallbackBase._dump_results in order to strip internal
        # keys, respect no_log directive, etc.
        if self.loop_items:
            # NOTE (dmsimard): There is a known issue in which Ansible can send
            # callback hooks out of order and "exit" the task before all items
            # have returned, this can cause one of the items to be missing
            # from the task result in ARA.
            # https://github.com/ansible/ansible/issues/24207
            results = [self._dump_results(result._result)]
            for item in self.loop_items:
                results.append(self._dump_results(item._result))
            results = jsonutils.loads(jsonutils.dumps(results))
        else:
            results = jsonutils.loads(self._dump_results(result._result))

        self.taskresult = models.TaskResult(
            task=self.task,
            host=host,
            time_start=result.task_start,
            time_end=result.task_end,
            result=jsonutils.dumps(results),
            status=status,
            changed=result._result.get('changed', False),
            failed=result._result.get('failed', False),
            skipped=result._result.get('skipped', False),
            unreachable=result._result.get('unreachable', False),
            ignore_errors=kwargs.get('ignore_errors', False),
        )

        db.session.add(self.taskresult)
        db.session.commit()

        if self.task.action == 'setup' and 'ansible_facts' in result._result:
            values = jsonutils.dumps(result._result['ansible_facts'])
            facts = models.HostFacts(values=values)
            host.facts = facts

            db.session.add(facts)
            db.session.commit()
コード例 #5
0
ファイル: fakes.py プロジェクト: selvaraju/ara
 def model(self):
     return m.TaskResult(task=self.task,
                         host=self.host,
                         status=self.status,
                         ignore_errors=self.ignore_errors,
                         changed=self.changed,
                         failed=self.failed,
                         skipped=self.skipped,
                         unreachable=self.unreachable,
                         result=self.result)
コード例 #6
0
ファイル: generate.py プロジェクト: rbramwell/ara-1
    def take_action(self, args):
        test_cases = []
        if args.playbook is not None:
            playbooks = args.playbook
            results = (models.TaskResult().query
                       .join(models.Task)
                       .filter(models.TaskResult.task_id == models.Task.id)
                       .filter(models.Task.playbook_id.in_(playbooks)))
        else:
            results = models.TaskResult().query.all()

        for result in results:
            task_name = result.task.name
            if not task_name:
                task_name = result.task.action
            additional_results = {
                'host': result.host.name,
                'playbook_path': result.task.playbook.path
            }
            result_str = json.dumps(additional_results)
            test_path = \
                "{playbook_file}.{play_name}".format(
                    playbook_file=os.path.basename(result.task.playbook.path),
                    play_name=result.task.play.name)
            test_case = TestCase(
                name=task_name,
                classname=test_path,
                elapsed_sec=result.duration.seconds,
                stdout=result_str)
            if result.status == "skipped":
                test_case.add_skipped_info(message=result.result)
            elif (result.status in ("failed", "unreachable") and
                    result.ignore_errors is False):
                test_case.add_failure_info(message=result.result)
            test_cases.append(test_case)
        test_suite = TestSuite("Ansible Tasks", test_cases)

        xml_string = test_suite.to_xml_string([test_suite])
        if args.output_file == "-":
            sys.stdout.write(xml_string)
        else:
            with open(args.output_file, "w") as f:
                f.write(xml_string)
コード例 #7
0
ファイル: test_models.py プロジェクト: hughsaunders/ara
    def setUp(self):
        super(TestModels, self).setUp()

        self.playbook = m.Playbook(path='testing.yml')

        self.play = m.Play(
            name='test play',
            playbook=self.playbook,
        )

        self.task = m.Task(
            name='test task',
            play=self.play,
            playbook=self.playbook,
        )

        self.data = m.Data(playbook=self.playbook,
                           key='test key',
                           value='test value')

        self.host = m.Host(
            name='localhost',
            playbook=self.playbook,
        )

        self.host_facts = m.HostFacts(host=self.host,
                                      values=json.dumps('{"fact": "value"}'))

        self.task_result = m.TaskResult(
            task=self.task,
            status='ok',
            host=self.host,
        )

        self.stats = m.Stats(
            playbook=self.playbook,
            host=self.host,
            changed=0,
            failed=0,
            skipped=0,
            unreachable=0,
            ok=0,
        )

        for obj in [
                self.playbook, self.play, self.task, self.data, self.host,
                self.task_result, self.stats
        ]:
            m.db.session.add(obj)

        m.db.session.commit()
コード例 #8
0
    def ansible_run(self, complete=True):
        '''Simulate a simple Ansible run by creating the
        expected database objects.  This roughly approximates the
        following playbook:

            - hosts: localhost
              tasks:
                - test-action:

        Set the `complete` parameter to `False` to simulate an
        aborted Ansible run.
        '''

        playbook = m.Playbook(path='testing.yml')
        play = m.Play(playbook=playbook, name='test play')
        task = m.Task(play=play, playbook=playbook, action='test-action')
        host = m.Host(name='localhost')
        host.playbooks.append(playbook)
        result = m.TaskResult(task=task,
                              status='ok',
                              host=host,
                              result='this is a test')

        self.ctx = dict(playbook=playbook,
                        play=play,
                        task=task,
                        host=host,
                        result=result)

        for obj in self.ctx.values():
            if hasattr(obj, 'start'):
                obj.start()
            db.session.add(obj)

        db.session.commit()

        if complete:
            stats = m.Stats(playbook=playbook, host=host)
            self.ctx['stats'] = stats
            db.session.add(stats)

            for obj in self.ctx.values():
                if hasattr(obj, 'stop'):
                    obj.stop()

        db.session.commit()
コード例 #9
0
    def setUp(self):
        m.db.create_all()

        self.playbook = m.Playbook(path='testing.yml')

        self.play = m.Play(
            name='test play',
            playbook=self.playbook,
        )

        self.task = m.Task(
            name='test task',
            play=self.play,
            playbook=self.playbook,
        )

        self.host = m.Host(name='localhost', )

        self.task_result = m.TaskResult(
            task=self.task,
            status='ok',
            host=self.host,
        )

        self.stats = m.Stats(
            playbook=self.playbook,
            host=self.host,
            changed=0,
            failed=0,
            skipped=0,
            unreachable=0,
            ok=0,
        )

        for obj in [
                self.playbook, self.play, self.task, self.host,
                self.task_result, self.stats
        ]:
            m.db.session.add(obj)

        m.db.session.commit()
コード例 #10
0
ファイル: log_ara.py プロジェクト: lastsky/ara
    def log_task(self, result, status, **kwargs):
        """
        'log_task' is called when an individual task instance on a single
        host completes. It is responsible for logging a single
        'TaskResult' record to the database.
        """
        LOG.debug('logging task result for task %s (%s), host %s',
                  self.task.name, self.task.id, result._host.name)

        result.task_start = self.task.time_start
        result.task_end = datetime.now()
        host = self.get_or_create_host(result._host.name)

        # Use Ansible's CallbackBase._dump_results in order to strip internal
        # keys, respect no_log directive, etc.
        results = json.loads(self._dump_results(result._result))

        self.taskresult = models.TaskResult(
            task=self.task,
            host=host,
            time_start=result.task_start,
            time_end=result.task_end,
            result=json.dumps(results),
            status=status,
            changed=result._result.get('changed', False),
            failed=result._result.get('failed', False),
            skipped=result._result.get('skipped', False),
            unreachable=result._result.get('unreachable', False),
            ignore_errors=kwargs.get('ignore_errors', False),
        )

        db.session.add(self.taskresult)

        if self.task.action == 'setup' and 'ansible_facts' in result._result:
            values = json.dumps(result._result['ansible_facts'])
            facts = models.HostFacts(values=values)
            host.facts = facts

            db.session.add(facts)
コード例 #11
0
def ansible_run(complete=True, gather_facts=True, ara_record=False):
    '''Simulate a simple Ansible run by creating the
    expected database objects.  This roughly approximates the
    following playbook:

        - hosts: host-<int>
          gather_facts: true
          tasks:
            - test-action:
              when: not ara_record
            - ara_record:
                key: 'test key'
                value: 'test value'
              when: ara_record

    Where `<int>` is a random integer generated each time this
    function is called.

    Set the `complete` parameter to `False` to simulate an
    aborted Ansible run.
    Set the `gathered_facts` parameter to `False` to simulate a run with no
    facts gathered.
    Set the `ara_record` parameter to `True` to simulate a run with an
    ara_record task.
    '''

    playbook = m.Playbook(path='testing.yml')
    play = m.Play(playbook=playbook, name='test play')
    host = m.Host(name='host-%04d' % random.randint(0, 9999),
                  playbook=playbook)

    if ara_record:
        task = m.Task(play=play, playbook=playbook, action='ara_record')
        msg = 'Data recorded in ARA for this playbook.'
    else:
        task = m.Task(play=play, playbook=playbook, action='test-action')
        msg = 'This is a test'

    result = m.TaskResult(task=task, status='ok', host=host, result=msg)

    ctx = dict(playbook=playbook,
               play=play,
               task=task,
               host=host,
               result=result)

    if gather_facts:
        facts = m.HostFacts(host=host, values='{"fact": "value"}')
        ctx['facts'] = facts

    if ara_record:
        data = m.Data(playbook=playbook, key='test key', value='test value')
        ctx['data'] = data

    for obj in ctx.values():
        if hasattr(obj, 'start'):
            obj.start()
        db.session.add(obj)

    db.session.commit()

    if complete:
        stats = m.Stats(playbook=playbook, host=host)
        ctx['stats'] = stats
        db.session.add(stats)
        ctx['playbook'].complete = True

        for obj in ctx.values():
            if hasattr(obj, 'stop'):
                obj.stop()

    db.session.commit()

    return ctx
コード例 #12
0
    def take_action(self, args):
        # Setup where the output stream must go
        if args.output_file == '-':
            output_stream = sys.stdout
        else:
            output_stream = open(args.output_file, 'wb')

        # Create the output stream
        output = StreamResultToBytes(output_stream)

        # Create the test run
        output.startTestRun()

        if args.playbook is not None:
            playbooks = args.playbook
            results = (models.TaskResult().query.join(models.Task).filter(
                models.TaskResult.task_id == models.Task.id).filter(
                    models.Task.playbook_id.in_(playbooks)))
        else:
            results = models.TaskResult().query.all()

        for result in results:
            # Generate a fixed length identifier for the task
            test_id = utils.generate_identifier(result)

            # Assign the test_status value
            if result.status in ('failed', 'unreachable'):
                if result.ignore_errors is False:
                    test_status = 'xfail'
                else:
                    test_status = 'fail'
            elif result.status == 'skipped':
                test_status = 'skip'
            else:
                test_status = 'success'

            # Determine the play file path
            if result.task.playbook and result.task.playbook.path:
                playbook_path = result.task.playbook.path
            else:
                playbook_path = ''

            # Determine the task file path
            if result.task.file and result.task.file.path:
                task_path = result.task.file.path
            else:
                task_path = ''

            # Assign the file_bytes value
            test_data = {
                'host': result.host.name,
                'playbook_id': result.task.playbook.id,
                'playbook_path': playbook_path,
                'play_name': result.task.play.name,
                'task_action': result.task.action,
                'task_action_lineno': result.task.lineno,
                'task_id': result.task.id,
                'task_name': result.task.name,
                'task_path': task_path
            }
            file_bytes = encodeutils.safe_encode(jsonutils.dumps(test_data))

            # Assign the start_time and stop_time value
            # The timestamp needs to be an epoch, so we need
            # to convert it.
            start_time = datetime.datetime.fromtimestamp(
                float(result.time_start.strftime('%s'))).replace(
                    tzinfo=iso8601.UTC)
            end_time = datetime.datetime.fromtimestamp(
                float(result.time_end.strftime('%s'))).replace(
                    tzinfo=iso8601.UTC)

            # Output the start of the event
            output.status(test_id=test_id, timestamp=start_time)

            # Output the end of the event
            output.status(test_id=test_id,
                          test_status=test_status,
                          test_tags=None,
                          runnable=False,
                          file_name=test_id,
                          file_bytes=file_bytes,
                          timestamp=end_time,
                          eof=True,
                          mime_type='text/plain; charset=UTF8')

        output.stopTestRun()
コード例 #13
0
    def log_task(self, result, status, **kwargs):
        """
        'log_task' is called when an individual task instance on a single
        host completes. It is responsible for logging a single
        'TaskResult' record to the database.
        """
        log.debug('Logging task result for task %s (%s), host %s',
                  self.task.name, self.task.id, result._host.get_name())

        # An include_role task might end up putting an IncludeRole object
        # inside the result object which we don't need
        # https://github.com/ansible/ansible/issues/30385
        if 'include_role' in result._result:
            del result._result['include_role']

        result.task_start = self.task.time_start
        result.task_end = datetime.now()
        host = self.get_or_create_host(result._host.get_name())

        # Use Ansible's CallbackBase._dump_results in order to strip internal
        # keys, respect no_log directive, etc.
        if self.loop_items:
            # NOTE (dmsimard): There is a known issue in which Ansible can send
            # callback hooks out of order and "exit" the task before all items
            # have returned, this can cause one of the items to be missing
            # from the task result in ARA.
            # https://github.com/ansible/ansible/issues/24207
            results = [self._dump_results(result._result)]
            for item in self.loop_items:
                results.append(self._dump_results(item._result))
            results = jsonutils.loads(jsonutils.dumps(results))
        else:
            results = jsonutils.loads(self._dump_results(result._result))

        # Ignore errors can be "yes" instead of a proper boolean in <2.3
        # for some reason
        ignore_errors = kwargs.get('ignore_errors', False)
        if LooseVersion(ansible_version) < LooseVersion('2.3.0'):
            if not isinstance(ignore_errors, bool):
                ignore_errors = True if ignore_errors == "yes" else False

        if self.task.action == 'setup' and 'ansible_facts' in results:
            # Potentially sanitize some Ansible facts to prevent them from
            # being saved both in the host facts and in the task results.
            for fact in app.config['ARA_IGNORE_FACTS']:
                if fact in results['ansible_facts']:
                    msg = "Not saved by ARA as configured by ARA_IGNORE_FACTS"
                    results['ansible_facts'][fact] = msg

            values = jsonutils.dumps(results['ansible_facts'])
            facts = models.HostFacts(values=values)
            host.facts = facts

            db.session.add(facts)
            db.session.commit()

        self.taskresult = models.TaskResult(
            task=self.task,
            host=host,
            time_start=result.task_start,
            time_end=result.task_end,
            result=jsonutils.dumps(results),
            status=status,
            changed=result._result.get('changed', False),
            failed=result._result.get('failed', False),
            skipped=result._result.get('skipped', False),
            unreachable=result._result.get('unreachable', False),
            ignore_errors=ignore_errors,
        )

        db.session.add(self.taskresult)
        db.session.commit()