mirror of
https://github.com/ansible/awx.git
synced 2026-01-15 03:40:42 -03:30
add new API endpoints and websocket emit for new job event types
see: https://github.com/ansible/awx/issues/200
This commit is contained in:
parent
0b30e7907b
commit
1369f72885
@ -1105,6 +1105,7 @@ class ProjectUpdateSerializer(UnifiedJobSerializer, ProjectOptionsSerializer):
|
||||
cancel = self.reverse('api:project_update_cancel', kwargs={'pk': obj.pk}),
|
||||
scm_inventory_updates = self.reverse('api:project_update_scm_inventory_updates', kwargs={'pk': obj.pk}),
|
||||
notifications = self.reverse('api:project_update_notifications_list', kwargs={'pk': obj.pk}),
|
||||
events = self.reverse('api:project_update_events_list', kwargs={'pk': obj.pk}),
|
||||
))
|
||||
return res
|
||||
|
||||
@ -1726,6 +1727,7 @@ class InventoryUpdateSerializer(UnifiedJobSerializer, InventorySourceOptionsSeri
|
||||
res.update(dict(
|
||||
cancel = self.reverse('api:inventory_update_cancel', kwargs={'pk': obj.pk}),
|
||||
notifications = self.reverse('api:inventory_update_notifications_list', kwargs={'pk': obj.pk}),
|
||||
events = self.reverse('api:inventory_update_events_list', kwargs={'pk': obj.pk}),
|
||||
))
|
||||
if obj.source_project_update_id:
|
||||
res['source_project_update'] = self.reverse('api:project_update_detail',
|
||||
@ -2962,6 +2964,7 @@ class SystemJobSerializer(UnifiedJobSerializer):
|
||||
res['notifications'] = self.reverse('api:system_job_notifications_list', kwargs={'pk': obj.pk})
|
||||
if obj.can_cancel or True:
|
||||
res['cancel'] = self.reverse('api:system_job_cancel', kwargs={'pk': obj.pk})
|
||||
res['events'] = self.reverse('api:system_job_events_list', kwargs={'pk': obj.pk})
|
||||
return res
|
||||
|
||||
def get_result_stdout(self, obj):
|
||||
@ -3415,6 +3418,41 @@ class JobEventWebSocketSerializer(JobEventSerializer):
|
||||
return 'job_events'
|
||||
|
||||
|
||||
class ProjectUpdateEventSerializer(JobEventSerializer):
|
||||
|
||||
class Meta:
|
||||
model = ProjectUpdateEvent
|
||||
fields = ('*', '-name', '-description', '-job', '-job_id',
|
||||
'-parent_uuid', '-parent', '-host', 'project_update')
|
||||
|
||||
def get_related(self, obj):
|
||||
res = super(JobEventSerializer, self).get_related(obj)
|
||||
res['project_update'] = self.reverse(
|
||||
'api:project_update_detail', kwargs={'pk': obj.project_update_id}
|
||||
)
|
||||
return res
|
||||
|
||||
|
||||
class ProjectUpdateEventWebSocketSerializer(ProjectUpdateEventSerializer):
|
||||
created = serializers.SerializerMethodField()
|
||||
modified = serializers.SerializerMethodField()
|
||||
event_name = serializers.CharField(source='event')
|
||||
group_name = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = ProjectUpdateEvent
|
||||
fields = ('*', 'event_name', 'group_name',)
|
||||
|
||||
def get_created(self, obj):
|
||||
return obj.created.isoformat()
|
||||
|
||||
def get_modified(self, obj):
|
||||
return obj.modified.isoformat()
|
||||
|
||||
def get_group_name(self, obj):
|
||||
return 'project_update_events'
|
||||
|
||||
|
||||
class AdHocCommandEventSerializer(BaseSerializer):
|
||||
|
||||
event_display = serializers.CharField(source='get_event_display', read_only=True)
|
||||
@ -3474,6 +3512,76 @@ class AdHocCommandEventWebSocketSerializer(AdHocCommandEventSerializer):
|
||||
return 'ad_hoc_command_events'
|
||||
|
||||
|
||||
class InventoryUpdateEventSerializer(AdHocCommandEventSerializer):
|
||||
|
||||
class Meta:
|
||||
model = InventoryUpdateEvent
|
||||
fields = ('*', '-name', '-description', '-ad_hoc_command', '-host',
|
||||
'-host_name', 'inventory_update')
|
||||
|
||||
def get_related(self, obj):
|
||||
res = super(AdHocCommandEventSerializer, self).get_related(obj)
|
||||
res['inventory_update'] = self.reverse(
|
||||
'api:inventory_update_detail', kwargs={'pk': obj.inventory_update_id}
|
||||
)
|
||||
return res
|
||||
|
||||
|
||||
class InventoryUpdateEventWebSocketSerializer(InventoryUpdateEventSerializer):
|
||||
created = serializers.SerializerMethodField()
|
||||
modified = serializers.SerializerMethodField()
|
||||
event_name = serializers.CharField(source='event')
|
||||
group_name = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = InventoryUpdateEvent
|
||||
fields = ('*', 'event_name', 'group_name',)
|
||||
|
||||
def get_created(self, obj):
|
||||
return obj.created.isoformat()
|
||||
|
||||
def get_modified(self, obj):
|
||||
return obj.modified.isoformat()
|
||||
|
||||
def get_group_name(self, obj):
|
||||
return 'inventory_update_events'
|
||||
|
||||
|
||||
class SystemJobEventSerializer(AdHocCommandEventSerializer):
|
||||
|
||||
class Meta:
|
||||
model = SystemJobEvent
|
||||
fields = ('*', '-name', '-description', '-ad_hoc_command', '-host',
|
||||
'-host_name', 'system_job')
|
||||
|
||||
def get_related(self, obj):
|
||||
res = super(AdHocCommandEventSerializer, self).get_related(obj)
|
||||
res['system_job'] = self.reverse(
|
||||
'api:system_job_detail', kwargs={'pk': obj.system_job_id}
|
||||
)
|
||||
return res
|
||||
|
||||
|
||||
class SystemJobEventWebSocketSerializer(SystemJobEventSerializer):
|
||||
created = serializers.SerializerMethodField()
|
||||
modified = serializers.SerializerMethodField()
|
||||
event_name = serializers.CharField(source='event')
|
||||
group_name = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = SystemJobEvent
|
||||
fields = ('*', 'event_name', 'group_name',)
|
||||
|
||||
def get_created(self, obj):
|
||||
return obj.created.isoformat()
|
||||
|
||||
def get_modified(self, obj):
|
||||
return obj.modified.isoformat()
|
||||
|
||||
def get_group_name(self, obj):
|
||||
return 'system_job_events'
|
||||
|
||||
|
||||
class JobLaunchSerializer(BaseSerializer):
|
||||
|
||||
# Representational fields
|
||||
|
||||
@ -9,6 +9,7 @@ from awx.api.views import (
|
||||
InventoryUpdateCancel,
|
||||
InventoryUpdateStdout,
|
||||
InventoryUpdateNotificationsList,
|
||||
InventoryUpdateEventsList,
|
||||
)
|
||||
|
||||
|
||||
@ -18,6 +19,7 @@ urls = [
|
||||
url(r'^(?P<pk>[0-9]+)/cancel/$', InventoryUpdateCancel.as_view(), name='inventory_update_cancel'),
|
||||
url(r'^(?P<pk>[0-9]+)/stdout/$', InventoryUpdateStdout.as_view(), name='inventory_update_stdout'),
|
||||
url(r'^(?P<pk>[0-9]+)/notifications/$', InventoryUpdateNotificationsList.as_view(), name='inventory_update_notifications_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/events/$', InventoryUpdateEventsList.as_view(), name='inventory_update_events_list'),
|
||||
]
|
||||
|
||||
__all__ = ['urls']
|
||||
|
||||
@ -10,6 +10,7 @@ from awx.api.views import (
|
||||
ProjectUpdateStdout,
|
||||
ProjectUpdateScmInventoryUpdates,
|
||||
ProjectUpdateNotificationsList,
|
||||
ProjectUpdateEventsList,
|
||||
)
|
||||
|
||||
|
||||
@ -20,6 +21,7 @@ urls = [
|
||||
url(r'^(?P<pk>[0-9]+)/stdout/$', ProjectUpdateStdout.as_view(), name='project_update_stdout'),
|
||||
url(r'^(?P<pk>[0-9]+)/scm_inventory_updates/$', ProjectUpdateScmInventoryUpdates.as_view(), name='project_update_scm_inventory_updates'),
|
||||
url(r'^(?P<pk>[0-9]+)/notifications/$', ProjectUpdateNotificationsList.as_view(), name='project_update_notifications_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/events/$', ProjectUpdateEventsList.as_view(), name='project_update_events_list'),
|
||||
]
|
||||
|
||||
__all__ = ['urls']
|
||||
|
||||
@ -8,6 +8,7 @@ from awx.api.views import (
|
||||
SystemJobDetail,
|
||||
SystemJobCancel,
|
||||
SystemJobNotificationsList,
|
||||
SystemJobEventsList
|
||||
)
|
||||
|
||||
|
||||
@ -16,6 +17,7 @@ urls = [
|
||||
url(r'^(?P<pk>[0-9]+)/$', SystemJobDetail.as_view(), name='system_job_detail'),
|
||||
url(r'^(?P<pk>[0-9]+)/cancel/$', SystemJobCancel.as_view(), name='system_job_cancel'),
|
||||
url(r'^(?P<pk>[0-9]+)/notifications/$', SystemJobNotificationsList.as_view(), name='system_job_notifications_list'),
|
||||
url(r'^(?P<pk>[0-9]+)/events/$', SystemJobEventsList.as_view(), name='system_job_events_list'),
|
||||
]
|
||||
|
||||
__all__ = ['urls']
|
||||
|
||||
@ -1366,6 +1366,45 @@ class ProjectUpdateDetail(UnifiedJobDeletionMixin, RetrieveDestroyAPIView):
|
||||
new_in_13 = True
|
||||
|
||||
|
||||
class ProjectUpdateEventsList(SubListAPIView):
|
||||
|
||||
model = ProjectUpdateEvent
|
||||
serializer_class = ProjectUpdateEventSerializer
|
||||
parent_model = ProjectUpdate
|
||||
relationship = 'project_update_events'
|
||||
view_name = _('Project Update Events List')
|
||||
|
||||
def finalize_response(self, request, response, *args, **kwargs):
|
||||
response['X-UI-Max-Events'] = settings.MAX_UI_JOB_EVENTS
|
||||
return super(ProjectUpdateEventsList, self).finalize_response(request, response, *args, **kwargs)
|
||||
|
||||
|
||||
class SystemJobEventsList(SubListAPIView):
|
||||
|
||||
model = SystemJobEvent
|
||||
serializer_class = SystemJobEventSerializer
|
||||
parent_model = SystemJob
|
||||
relationship = 'system_job_events'
|
||||
view_name = _('System Job Events List')
|
||||
|
||||
def finalize_response(self, request, response, *args, **kwargs):
|
||||
response['X-UI-Max-Events'] = settings.MAX_UI_JOB_EVENTS
|
||||
return super(SystemJobEventsList, self).finalize_response(request, response, *args, **kwargs)
|
||||
|
||||
|
||||
class InventoryUpdateEventsList(SubListAPIView):
|
||||
|
||||
model = InventoryUpdateEvent
|
||||
serializer_class = InventoryUpdateEventSerializer
|
||||
parent_model = InventoryUpdate
|
||||
relationship = 'inventory_update_events'
|
||||
view_name = _('Inventory Update Events List')
|
||||
|
||||
def finalize_response(self, request, response, *args, **kwargs):
|
||||
response['X-UI-Max-Events'] = settings.MAX_UI_JOB_EVENTS
|
||||
return super(InventoryUpdateEventsList, self).finalize_response(request, response, *args, **kwargs)
|
||||
|
||||
|
||||
class ProjectUpdateCancel(RetrieveAPIView):
|
||||
|
||||
model = ProjectUpdate
|
||||
|
||||
@ -1987,6 +1987,64 @@ class JobEventAccess(BaseAccess):
|
||||
return False
|
||||
|
||||
|
||||
class ProjectUpdateEventAccess(BaseAccess):
|
||||
'''
|
||||
I can see project update event records whenever I can access the project update
|
||||
'''
|
||||
|
||||
model = ProjectUpdateEvent
|
||||
|
||||
def filtered_queryset(self):
|
||||
return self.model.objects.filter(
|
||||
Q(project_update__in=ProjectUpdate.accessible_pk_qs(self.user, 'read_role')))
|
||||
|
||||
def can_add(self, data):
|
||||
return False
|
||||
|
||||
def can_change(self, obj, data):
|
||||
return False
|
||||
|
||||
def can_delete(self, obj):
|
||||
return False
|
||||
|
||||
|
||||
class InventoryUpdateEventAccess(BaseAccess):
|
||||
'''
|
||||
I can see inventory update event records whenever I can access the inventory update
|
||||
'''
|
||||
|
||||
model = InventoryUpdateEvent
|
||||
|
||||
def filtered_queryset(self):
|
||||
return self.model.objects.filter(
|
||||
Q(inventory_update__in=InventoryUpdate.accessible_pk_qs(self.user, 'read_role')))
|
||||
|
||||
def can_add(self, data):
|
||||
return False
|
||||
|
||||
def can_change(self, obj, data):
|
||||
return False
|
||||
|
||||
def can_delete(self, obj):
|
||||
return False
|
||||
|
||||
|
||||
class SystemJobEventAccess(BaseAccess):
|
||||
'''
|
||||
I can only see manage System Jobs events if I'm a super user
|
||||
'''
|
||||
model = SystemJobEvent
|
||||
|
||||
def can_add(self, data):
|
||||
return False
|
||||
|
||||
def can_change(self, obj, data):
|
||||
return False
|
||||
|
||||
def can_delete(self, obj):
|
||||
return False
|
||||
|
||||
|
||||
class UnifiedJobTemplateAccess(BaseAccess):
|
||||
'''
|
||||
I can see a unified job template whenever I can see the same project,
|
||||
|
||||
@ -12,11 +12,17 @@ from awx.main.models import (
|
||||
UnifiedJob,
|
||||
Job,
|
||||
AdHocCommand,
|
||||
ProjectUpdate,
|
||||
InventoryUpdate,
|
||||
SystemJob
|
||||
)
|
||||
from awx.main.consumers import emit_channel_notification
|
||||
from awx.api.serializers import (
|
||||
JobEventWebSocketSerializer,
|
||||
AdHocCommandEventWebSocketSerializer,
|
||||
ProjectUpdateEventWebSocketSerializer,
|
||||
InventoryUpdateEventWebSocketSerializer,
|
||||
SystemJobEventWebSocketSerializer
|
||||
)
|
||||
|
||||
|
||||
@ -60,7 +66,16 @@ class ReplayJobEvents():
|
||||
return self.replay_elapsed().total_seconds() - (self.recording_elapsed(created).total_seconds() * (1.0 / speed))
|
||||
|
||||
def get_job_events(self, job):
|
||||
job_events = job.job_events.order_by('created')
|
||||
if type(job) is Job:
|
||||
job_events = job.job_events.order_by('created')
|
||||
elif type(job) is AdHocCommand:
|
||||
job_events = job.ad_hoc_command_events.order_by('created')
|
||||
elif type(job) is ProjectUpdate:
|
||||
job_events = job.project_update_events.order_by('created')
|
||||
elif type(job) is InventoryUpdate:
|
||||
job_events = job.inventory_update_events.order_by('created')
|
||||
elif type(job) is SystemJob:
|
||||
job_events = job.system_job_events.order_by('created')
|
||||
if job_events.count() == 0:
|
||||
raise RuntimeError("No events for job id {}".format(job.id))
|
||||
return job_events
|
||||
@ -70,6 +85,12 @@ class ReplayJobEvents():
|
||||
return JobEventWebSocketSerializer
|
||||
elif type(job) is AdHocCommand:
|
||||
return AdHocCommandEventWebSocketSerializer
|
||||
elif type(job) is ProjectUpdate:
|
||||
return ProjectUpdateEventWebSocketSerializer
|
||||
elif type(job) is InventoryUpdate:
|
||||
return InventoryUpdateEventWebSocketSerializer
|
||||
elif type(job) is SystemJob:
|
||||
return SystemJobEventWebSocketSerializer
|
||||
else:
|
||||
raise RuntimeError("Job is of type {} and replay is not yet supported.".format(type(job)))
|
||||
sys.exit(1)
|
||||
|
||||
@ -24,7 +24,7 @@ from awx.main.utils import ignore_inventory_computed_fields, ignore_inventory_gr
|
||||
from awx.main.tasks import update_inventory_computed_fields
|
||||
from awx.main.fields import is_implicit_parent
|
||||
|
||||
from awx.main.consumers import emit_channel_notification
|
||||
from awx.main import consumers
|
||||
|
||||
from awx.conf.utils import conf_to_dict
|
||||
|
||||
@ -48,7 +48,7 @@ def emit_job_event_detail(sender, **kwargs):
|
||||
created = kwargs['created']
|
||||
if created:
|
||||
event_serialized = JobEventWebSocketSerializer(instance).data
|
||||
emit_channel_notification('job_events-' + str(instance.job.id), event_serialized)
|
||||
consumers.emit_channel_notification('job_events-' + str(instance.job.id), event_serialized)
|
||||
|
||||
|
||||
def emit_ad_hoc_command_event_detail(sender, **kwargs):
|
||||
@ -56,7 +56,31 @@ def emit_ad_hoc_command_event_detail(sender, **kwargs):
|
||||
created = kwargs['created']
|
||||
if created:
|
||||
event_serialized = AdHocCommandEventWebSocketSerializer(instance).data
|
||||
emit_channel_notification('ad_hoc_command_events-' + str(instance.ad_hoc_command_id), event_serialized)
|
||||
consumers.emit_channel_notification('ad_hoc_command_events-' + str(instance.ad_hoc_command_id), event_serialized)
|
||||
|
||||
|
||||
def emit_project_update_event_detail(sender, **kwargs):
|
||||
instance = kwargs['instance']
|
||||
created = kwargs['created']
|
||||
if created:
|
||||
event_serialized = ProjectUpdateEventWebSocketSerializer(instance).data
|
||||
consumers.emit_channel_notification('project_update_events-' + str(instance.project_update_id), event_serialized)
|
||||
|
||||
|
||||
def emit_inventory_update_event_detail(sender, **kwargs):
|
||||
instance = kwargs['instance']
|
||||
created = kwargs['created']
|
||||
if created:
|
||||
event_serialized = InventoryUpdateEventWebSocketSerializer(instance).data
|
||||
consumers.emit_channel_notification('inventory_update_events-' + str(instance.inventory_update_id), event_serialized)
|
||||
|
||||
|
||||
def emit_system_job_event_detail(sender, **kwargs):
|
||||
instance = kwargs['instance']
|
||||
created = kwargs['created']
|
||||
if created:
|
||||
event_serialized = SystemJobEventWebSocketSerializer(instance).data
|
||||
consumers.emit_channel_notification('system_job_events-' + str(instance.system_job_id), event_serialized)
|
||||
|
||||
|
||||
def emit_update_inventory_computed_fields(sender, **kwargs):
|
||||
@ -222,6 +246,9 @@ connect_computed_field_signals()
|
||||
|
||||
post_save.connect(emit_job_event_detail, sender=JobEvent)
|
||||
post_save.connect(emit_ad_hoc_command_event_detail, sender=AdHocCommandEvent)
|
||||
post_save.connect(emit_project_update_event_detail, sender=ProjectUpdateEvent)
|
||||
post_save.connect(emit_inventory_update_event_detail, sender=InventoryUpdateEvent)
|
||||
post_save.connect(emit_system_job_event_detail, sender=SystemJobEvent)
|
||||
m2m_changed.connect(rebuild_role_ancestor_list, Role.parents.through)
|
||||
m2m_changed.connect(org_admin_edit_members, Role.members.through)
|
||||
m2m_changed.connect(rbac_activity_stream, Role.members.through)
|
||||
|
||||
69
awx/main/tests/functional/models/test_events.py
Normal file
69
awx/main/tests/functional/models/test_events.py
Normal file
@ -0,0 +1,69 @@
|
||||
import mock
|
||||
import pytest
|
||||
|
||||
from awx.main.models import (Job, JobEvent, ProjectUpdate, ProjectUpdateEvent,
|
||||
AdHocCommand, AdHocCommandEvent, InventoryUpdate,
|
||||
InventorySource, InventoryUpdateEvent, SystemJob,
|
||||
SystemJobEvent)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@mock.patch('awx.main.consumers.emit_channel_notification')
|
||||
def test_job_event_websocket_notifications(emit):
|
||||
j = Job(id=123)
|
||||
j.save()
|
||||
JobEvent.create_from_data(job_id=j.pk)
|
||||
assert len(emit.call_args_list) == 1
|
||||
topic, payload = emit.call_args_list[0][0]
|
||||
assert topic == 'job_events-123'
|
||||
assert payload['job'] == 123
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@mock.patch('awx.main.consumers.emit_channel_notification')
|
||||
def test_ad_hoc_event_websocket_notifications(emit):
|
||||
ahc = AdHocCommand(id=123)
|
||||
ahc.save()
|
||||
AdHocCommandEvent.create_from_data(ad_hoc_command_id=ahc.pk)
|
||||
assert len(emit.call_args_list) == 1
|
||||
topic, payload = emit.call_args_list[0][0]
|
||||
assert topic == 'ad_hoc_command_events-123'
|
||||
assert payload['ad_hoc_command'] == 123
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@mock.patch('awx.main.consumers.emit_channel_notification')
|
||||
def test_project_update_event_websocket_notifications(emit, project):
|
||||
pu = ProjectUpdate(id=123, project=project)
|
||||
pu.save()
|
||||
ProjectUpdateEvent.create_from_data(project_update_id=pu.pk)
|
||||
assert len(emit.call_args_list) == 1
|
||||
topic, payload = emit.call_args_list[0][0]
|
||||
assert topic == 'project_update_events-123'
|
||||
assert payload['project_update'] == 123
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@mock.patch('awx.main.consumers.emit_channel_notification')
|
||||
def test_inventory_update_event_websocket_notifications(emit, inventory):
|
||||
source = InventorySource()
|
||||
source.save()
|
||||
iu = InventoryUpdate(id=123, inventory_source=source)
|
||||
iu.save()
|
||||
InventoryUpdateEvent.create_from_data(inventory_update_id=iu.pk)
|
||||
assert len(emit.call_args_list) == 1
|
||||
topic, payload = emit.call_args_list[0][0]
|
||||
assert topic == 'inventory_update_events-123'
|
||||
assert payload['inventory_update'] == 123
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@mock.patch('awx.main.consumers.emit_channel_notification')
|
||||
def test_system_job_event_websocket_notifications(emit, inventory):
|
||||
j = SystemJob(id=123)
|
||||
j.save()
|
||||
SystemJobEvent.create_from_data(system_job_id=j.pk)
|
||||
assert len(emit.call_args_list) == 1
|
||||
topic, payload = emit.call_args_list[0][0]
|
||||
assert topic == 'system_job_events-123'
|
||||
assert payload['system_job'] == 123
|
||||
46
awx/main/tests/unit/models/test_events.py
Normal file
46
awx/main/tests/unit/models/test_events.py
Normal file
@ -0,0 +1,46 @@
|
||||
from datetime import datetime
|
||||
from django.utils.timezone import utc
|
||||
import mock
|
||||
import pytest
|
||||
|
||||
from awx.main.models import (JobEvent, ProjectUpdateEvent, AdHocCommandEvent,
|
||||
InventoryUpdateEvent, SystemJobEvent)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('job_identifier, cls', [
|
||||
['job_id', JobEvent],
|
||||
['project_update_id', ProjectUpdateEvent],
|
||||
['ad_hoc_command_id', AdHocCommandEvent],
|
||||
['inventory_update_id', InventoryUpdateEvent],
|
||||
['system_job_id', SystemJobEvent],
|
||||
])
|
||||
@pytest.mark.parametrize('created', [
|
||||
datetime(2018, 1, 1).isoformat(), datetime(2018, 1, 1)
|
||||
])
|
||||
def test_event_parse_created(job_identifier, cls, created):
|
||||
with mock.patch.object(cls, 'objects') as manager:
|
||||
cls.create_from_data(**{
|
||||
job_identifier: 123,
|
||||
'created': created
|
||||
})
|
||||
expected_created = datetime(2018, 1, 1).replace(tzinfo=utc)
|
||||
manager.create.assert_called_with(**{
|
||||
job_identifier: 123,
|
||||
'created': expected_created
|
||||
})
|
||||
|
||||
|
||||
@pytest.mark.parametrize('job_identifier, cls', [
|
||||
['job_id', JobEvent],
|
||||
['project_update_id', ProjectUpdateEvent],
|
||||
['ad_hoc_command_id', AdHocCommandEvent],
|
||||
['inventory_update_id', InventoryUpdateEvent],
|
||||
['system_job_id', SystemJobEvent],
|
||||
])
|
||||
def test_playbook_event_strip_invalid_keys(job_identifier, cls):
|
||||
with mock.patch.object(cls, 'objects') as manager:
|
||||
cls.create_from_data(**{
|
||||
job_identifier: 123,
|
||||
'extra_key': 'extra_value'
|
||||
})
|
||||
manager.create.assert_called_with(**{job_identifier: 123})
|
||||
Loading…
x
Reference in New Issue
Block a user