mirror of
https://github.com/ansible/awx.git
synced 2026-03-21 10:57:36 -02:30
AC-504 Capture role when available for job events.
This commit is contained in:
@@ -1328,7 +1328,7 @@ class JobEventSerializer(BaseSerializer):
|
|||||||
model = JobEvent
|
model = JobEvent
|
||||||
fields = ('*', '-name', '-description', 'job', 'event',
|
fields = ('*', '-name', '-description', 'job', 'event',
|
||||||
'event_display', 'event_data', 'event_level', 'failed',
|
'event_display', 'event_data', 'event_level', 'failed',
|
||||||
'changed', 'host', 'parent', 'play', 'task')
|
'changed', 'host', 'parent', 'play', 'task', 'role')
|
||||||
|
|
||||||
def get_related(self, obj):
|
def get_related(self, obj):
|
||||||
res = super(JobEventSerializer, self).get_related(obj)
|
res = super(JobEventSerializer, self).get_related(obj)
|
||||||
|
|||||||
@@ -512,7 +512,7 @@ class JobEvent(CreatedModifiedModel):
|
|||||||
return reverse('api:job_event_detail', args=(self.pk,))
|
return reverse('api:job_event_detail', args=(self.pk,))
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return u'%s @ %s' % (self.get_event_display(), self.created.isoformat())
|
return u'%s @ %s' % (self.get_event_display2(), self.created.isoformat())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def event_level(self):
|
def event_level(self):
|
||||||
@@ -521,11 +521,14 @@ class JobEvent(CreatedModifiedModel):
|
|||||||
def get_event_display2(self):
|
def get_event_display2(self):
|
||||||
msg = self.get_event_display()
|
msg = self.get_event_display()
|
||||||
if self.event == 'playbook_on_play_start':
|
if self.event == 'playbook_on_play_start':
|
||||||
if self.play is not None:
|
if self.play:
|
||||||
msg = "%s (%s)" % (msg, self.play)
|
msg = "%s (%s)" % (msg, self.play)
|
||||||
elif self.event == 'playbook_on_task_start':
|
elif self.event == 'playbook_on_task_start':
|
||||||
if self.task is not None:
|
if self.task:
|
||||||
msg = "%s (%s)" % (msg, self.task)
|
if self.role:
|
||||||
|
msg = '%s (%s | %s)' % (msg, self.role, self.task)
|
||||||
|
else:
|
||||||
|
msg = "%s (%s)" % (msg, self.task)
|
||||||
|
|
||||||
# Change display for runner events trigged by async polling. Some of
|
# Change display for runner events trigged by async polling. Some of
|
||||||
# these events may not show in most cases, due to filterting them out
|
# these events may not show in most cases, due to filterting them out
|
||||||
@@ -637,6 +640,9 @@ class JobEvent(CreatedModifiedModel):
|
|||||||
self.task = self.event_data.get('task', '').strip()
|
self.task = self.event_data.get('task', '').strip()
|
||||||
if 'task' not in update_fields:
|
if 'task' not in update_fields:
|
||||||
update_fields.append('task')
|
update_fields.append('task')
|
||||||
|
self.role = self.event_data.get('role', '').strip()
|
||||||
|
if 'role' not in update_fields:
|
||||||
|
update_fields.append('role')
|
||||||
# Only update job event hierarchy and related models during post
|
# Only update job event hierarchy and related models during post
|
||||||
# processing (after running job).
|
# processing (after running job).
|
||||||
post_process = kwargs.pop('post_process', False)
|
post_process = kwargs.pop('post_process', False)
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ class BaseTestMixin(object):
|
|||||||
return results
|
return results
|
||||||
|
|
||||||
def make_project(self, name, description='', created_by=None,
|
def make_project(self, name, description='', created_by=None,
|
||||||
playbook_content=''):
|
playbook_content='', role_playbooks=None):
|
||||||
if not os.path.exists(settings.PROJECTS_ROOT):
|
if not os.path.exists(settings.PROJECTS_ROOT):
|
||||||
os.makedirs(settings.PROJECTS_ROOT)
|
os.makedirs(settings.PROJECTS_ROOT)
|
||||||
# Create temp project directory.
|
# Create temp project directory.
|
||||||
@@ -139,13 +139,24 @@ class BaseTestMixin(object):
|
|||||||
test_playbook_file = os.fdopen(handle, 'w')
|
test_playbook_file = os.fdopen(handle, 'w')
|
||||||
test_playbook_file.write(playbook_content)
|
test_playbook_file.write(playbook_content)
|
||||||
test_playbook_file.close()
|
test_playbook_file.close()
|
||||||
|
# Role playbooks are specified as a dict of role name and the
|
||||||
|
# content of tasks/main.yml playbook.
|
||||||
|
role_playbooks = role_playbooks or {}
|
||||||
|
for role_name, role_playbook_content in role_playbooks.items():
|
||||||
|
role_tasks_dir = os.path.join(project_dir, 'roles', role_name, 'tasks')
|
||||||
|
if not os.path.exists(role_tasks_dir):
|
||||||
|
os.makedirs(role_tasks_dir)
|
||||||
|
role_tasks_playbook_path = os.path.join(role_tasks_dir, 'main.yml')
|
||||||
|
with open(role_tasks_playbook_path, 'w') as f:
|
||||||
|
f.write(role_playbook_content)
|
||||||
return Project.objects.create(
|
return Project.objects.create(
|
||||||
name=name, description=description,
|
name=name, description=description,
|
||||||
local_path=os.path.basename(project_dir), created_by=created_by,
|
local_path=os.path.basename(project_dir), created_by=created_by,
|
||||||
#scm_type='git', default_playbook='foo.yml',
|
#scm_type='git', default_playbook='foo.yml',
|
||||||
)
|
)
|
||||||
|
|
||||||
def make_projects(self, created_by, count=1, playbook_content=''):
|
def make_projects(self, created_by, count=1, playbook_content='',
|
||||||
|
role_playbooks=None):
|
||||||
results = []
|
results = []
|
||||||
for x in range(0, count):
|
for x in range(0, count):
|
||||||
self.object_ctr = self.object_ctr + 1
|
self.object_ctr = self.object_ctr + 1
|
||||||
@@ -154,6 +165,7 @@ class BaseTestMixin(object):
|
|||||||
description="proj%s" % x,
|
description="proj%s" % x,
|
||||||
created_by=created_by,
|
created_by=created_by,
|
||||||
playbook_content=playbook_content,
|
playbook_content=playbook_content,
|
||||||
|
role_playbooks=role_playbooks,
|
||||||
))
|
))
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|||||||
@@ -88,6 +88,26 @@ TEST_ASYNC_NOWAIT_PLAYBOOK = '''
|
|||||||
poll: 0
|
poll: 0
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
TEST_PLAYBOOK_WITH_ROLES = '''
|
||||||
|
- hosts: test-group
|
||||||
|
gather_facts: false
|
||||||
|
roles:
|
||||||
|
- some_stuff
|
||||||
|
- more_stuff
|
||||||
|
- {role: stuff, tags: stuff}
|
||||||
|
'''
|
||||||
|
|
||||||
|
TEST_ROLE_PLAYBOOK = '''
|
||||||
|
- name: some task in a role
|
||||||
|
command: test 1 = 1
|
||||||
|
'''
|
||||||
|
|
||||||
|
TEST_ROLE_PLAYBOOKS = {
|
||||||
|
'some_stuff': TEST_ROLE_PLAYBOOK,
|
||||||
|
'more_stuff': TEST_ROLE_PLAYBOOK,
|
||||||
|
'stuff': TEST_ROLE_PLAYBOOK,
|
||||||
|
}
|
||||||
|
|
||||||
TEST_VAULT_PLAYBOOK = '''$ANSIBLE_VAULT;1.1;AES256
|
TEST_VAULT_PLAYBOOK = '''$ANSIBLE_VAULT;1.1;AES256
|
||||||
35623233333035633365383330323835353564346534363762366465316263363463396162656432
|
35623233333035633365383330323835353564346534363762366465316263363463396162656432
|
||||||
6562643539396330616265616532656466353639303338650a313466333663646431646663333739
|
6562643539396330616265616532656466353639303338650a313466333663646431646663333739
|
||||||
@@ -230,8 +250,9 @@ class RunJobTest(BaseCeleryTest):
|
|||||||
self.cloud_credential = Credential.objects.create(**opts)
|
self.cloud_credential = Credential.objects.create(**opts)
|
||||||
return self.cloud_credential
|
return self.cloud_credential
|
||||||
|
|
||||||
def create_test_project(self, playbook_content):
|
def create_test_project(self, playbook_content, role_playbooks=None):
|
||||||
self.project = self.make_projects(self.normal_django_user, 1, playbook_content)[0]
|
self.project = self.make_projects(self.normal_django_user, 1,
|
||||||
|
playbook_content, role_playbooks)[0]
|
||||||
self.organization.projects.add(self.project)
|
self.organization.projects.add(self.project)
|
||||||
|
|
||||||
def create_test_job_template(self, **kwargs):
|
def create_test_job_template(self, **kwargs):
|
||||||
@@ -299,7 +320,7 @@ class RunJobTest(BaseCeleryTest):
|
|||||||
|
|
||||||
def check_job_events(self, job, runner_status='ok', plays=1, tasks=1,
|
def check_job_events(self, job, runner_status='ok', plays=1, tasks=1,
|
||||||
async=False, async_timeout=False, async_nowait=False,
|
async=False, async_timeout=False, async_nowait=False,
|
||||||
check_ignore_errors=False):
|
check_ignore_errors=False, has_roles=False):
|
||||||
job_events = job.job_events.all()
|
job_events = job.job_events.all()
|
||||||
if False and async:
|
if False and async:
|
||||||
print
|
print
|
||||||
@@ -323,6 +344,7 @@ class RunJobTest(BaseCeleryTest):
|
|||||||
self.assertFalse(evt.host, evt)
|
self.assertFalse(evt.host, evt)
|
||||||
self.assertFalse(evt.play, evt)
|
self.assertFalse(evt.play, evt)
|
||||||
self.assertFalse(evt.task, evt)
|
self.assertFalse(evt.task, evt)
|
||||||
|
self.assertFalse(evt.role, evt)
|
||||||
self.assertEqual(evt.failed, should_be_failed)
|
self.assertEqual(evt.failed, should_be_failed)
|
||||||
if not async:
|
if not async:
|
||||||
self.assertEqual(evt.changed, should_be_changed)
|
self.assertEqual(evt.changed, should_be_changed)
|
||||||
@@ -335,6 +357,7 @@ class RunJobTest(BaseCeleryTest):
|
|||||||
self.assertFalse(evt.host, evt)
|
self.assertFalse(evt.host, evt)
|
||||||
self.assertTrue(evt.play, evt)
|
self.assertTrue(evt.play, evt)
|
||||||
self.assertFalse(evt.task, evt)
|
self.assertFalse(evt.task, evt)
|
||||||
|
self.assertFalse(evt.role, evt)
|
||||||
self.assertEqual(evt.failed, should_be_failed)
|
self.assertEqual(evt.failed, should_be_failed)
|
||||||
if not async:
|
if not async:
|
||||||
self.assertEqual(evt.changed, should_be_changed)
|
self.assertEqual(evt.changed, should_be_changed)
|
||||||
@@ -347,6 +370,10 @@ class RunJobTest(BaseCeleryTest):
|
|||||||
self.assertFalse(evt.host, evt)
|
self.assertFalse(evt.host, evt)
|
||||||
self.assertTrue(evt.play, evt)
|
self.assertTrue(evt.play, evt)
|
||||||
self.assertTrue(evt.task, evt)
|
self.assertTrue(evt.task, evt)
|
||||||
|
if has_roles:
|
||||||
|
self.assertTrue(evt.role, evt)
|
||||||
|
else:
|
||||||
|
self.assertFalse(evt.role, evt)
|
||||||
self.assertEqual(evt.failed, should_be_failed)
|
self.assertEqual(evt.failed, should_be_failed)
|
||||||
if not async:
|
if not async:
|
||||||
self.assertEqual(evt.changed, should_be_changed)
|
self.assertEqual(evt.changed, should_be_changed)
|
||||||
@@ -367,6 +394,10 @@ class RunJobTest(BaseCeleryTest):
|
|||||||
self.assertEqual(evt.host, self.host)
|
self.assertEqual(evt.host, self.host)
|
||||||
self.assertTrue(evt.play, evt)
|
self.assertTrue(evt.play, evt)
|
||||||
self.assertTrue(evt.task, evt)
|
self.assertTrue(evt.task, evt)
|
||||||
|
if has_roles:
|
||||||
|
self.assertTrue(evt.role, evt)
|
||||||
|
else:
|
||||||
|
self.assertFalse(evt.role, evt)
|
||||||
self.assertEqual(evt.failed, should_be_failed)
|
self.assertEqual(evt.failed, should_be_failed)
|
||||||
if not async:
|
if not async:
|
||||||
self.assertEqual(evt.changed, should_be_changed)
|
self.assertEqual(evt.changed, should_be_changed)
|
||||||
@@ -1049,3 +1080,14 @@ class RunJobTest(BaseCeleryTest):
|
|||||||
self.assertEqual(job.unreachable_hosts.count(), 0)
|
self.assertEqual(job.unreachable_hosts.count(), 0)
|
||||||
self.assertEqual(job.skipped_hosts.count(), 0)
|
self.assertEqual(job.skipped_hosts.count(), 0)
|
||||||
self.assertEqual(job.processed_hosts.count(), 1)
|
self.assertEqual(job.processed_hosts.count(), 1)
|
||||||
|
|
||||||
|
def test_run_job_with_roles(self):
|
||||||
|
self.create_test_project(TEST_PLAYBOOK_WITH_ROLES, TEST_ROLE_PLAYBOOKS)
|
||||||
|
job_template = self.create_test_job_template()
|
||||||
|
job = self.create_test_job(job_template=job_template)
|
||||||
|
self.assertEqual(job.status, 'new')
|
||||||
|
self.assertFalse(job.passwords_needed_to_start)
|
||||||
|
self.assertTrue(job.signal_start())
|
||||||
|
job = Job.objects.get(pk=job.pk)
|
||||||
|
self.check_job_result(job, 'successful')
|
||||||
|
self.check_job_events(job, 'ok', 1, 3, has_roles=True)
|
||||||
|
|||||||
@@ -167,12 +167,17 @@ class CallbackModule(object):
|
|||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
|
||||||
def _log_event(self, event, **event_data):
|
def _log_event(self, event, **event_data):
|
||||||
play = getattr(getattr(self, 'play', None), 'name', '')
|
play = getattr(self, 'play', None)
|
||||||
if play and event not in self.EVENTS_WITHOUT_PLAY:
|
play_name = getattr(play, 'name', '')
|
||||||
event_data['play'] = play
|
if play_name and event not in self.EVENTS_WITHOUT_PLAY:
|
||||||
task = getattr(getattr(self, 'task', None), 'name', '')
|
event_data['play'] = play_name
|
||||||
if task and event not in self.EVENTS_WITHOUT_TASK:
|
task = getattr(self, 'task', None)
|
||||||
event_data['task'] = task
|
task_name = getattr(task, 'name', '')
|
||||||
|
role_name = getattr(task, 'role_name', '')
|
||||||
|
if task_name and event not in self.EVENTS_WITHOUT_TASK:
|
||||||
|
event_data['task'] = task_name
|
||||||
|
if role_name and event not in self.EVENTS_WITHOUT_TASK:
|
||||||
|
event_data['role'] = role_name
|
||||||
if self.callback_consumer_port:
|
if self.callback_consumer_port:
|
||||||
self._post_job_event_queue_msg(event, event_data)
|
self._post_job_event_queue_msg(event, event_data)
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user