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)
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
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()
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()
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)
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
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()
def model(self): return m.HostFacts(host=self.host, values=self.values)