From 5895b3a3431a434afd388e7216d56bda281adea1 Mon Sep 17 00:00:00 2001 From: Matthew Jones Date: Thu, 5 May 2016 13:53:46 -0400 Subject: [PATCH] Refactor Notification's naming Notifier -> NotificationTemplate notifier -> notification_template --- awx/api/metadata.py | 4 +- awx/api/serializers.py | 52 +++--- awx/api/urls.py | 44 ++--- awx/api/views.py | 154 +++++++++--------- awx/main/access.py | 14 +- .../0003_v300_notification_changes.py | 40 ++--- awx/main/migrations/_cleanup_deleted.py | 2 +- awx/main/models/__init__.py | 2 +- awx/main/models/activity_stream.py | 2 +- awx/main/models/base.py | 18 +- awx/main/models/inventory.py | 19 ++- awx/main/models/jobs.py | 43 ++--- awx/main/models/notifications.py | 20 +-- awx/main/models/projects.py | 33 ++-- awx/main/models/unified_jobs.py | 6 +- awx/main/signals.py | 2 +- awx/main/tasks.py | 26 +-- awx/main/tests/functional/conftest.py | 20 +-- .../tests/functional/test_notifications.py | 54 +++--- .../functional/test_rbac_notifications.py | 64 ++++---- awx/main/tests/unit/api/test_serializers.py | 6 +- awx/main/tests/unit/api/test_views.py | 2 +- 22 files changed, 324 insertions(+), 303 deletions(-) diff --git a/awx/api/metadata.py b/awx/api/metadata.py index b121d74863..c326a4a875 100644 --- a/awx/api/metadata.py +++ b/awx/api/metadata.py @@ -16,7 +16,7 @@ from rest_framework.relations import RelatedField from rest_framework.request import clone_request # Ansible Tower -from awx.main.models import InventorySource, Notifier +from awx.main.models import InventorySource, NotificationTemplate class Metadata(metadata.SimpleMetadata): @@ -91,7 +91,7 @@ class Metadata(metadata.SimpleMetadata): # Special handling of notification configuration where the required properties # are conditional on the type selected. if field.field_name == 'notification_configuration': - for (notification_type_name, notification_tr_name, notification_type_class) in Notifier.NOTIFICATION_TYPES: + for (notification_type_name, notification_tr_name, notification_type_class) in NotificationTemplate.NOTIFICATION_TYPES: field_info[notification_type_name] = notification_type_class.init_parameters # Update type of fields returned... diff --git a/awx/api/serializers.py b/awx/api/serializers.py index d679029057..badfb619ae 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -800,10 +800,10 @@ class OrganizationSerializer(BaseSerializer): teams = reverse('api:organization_teams_list', args=(obj.pk,)), credentials = reverse('api:organization_credential_list', args=(obj.pk,)), activity_stream = reverse('api:organization_activity_stream_list', args=(obj.pk,)), - notifiers = reverse('api:organization_notifiers_list', args=(obj.pk,)), - notifiers_any = reverse('api:organization_notifiers_any_list', args=(obj.pk,)), - notifiers_success = reverse('api:organization_notifiers_success_list', args=(obj.pk,)), - notifiers_error = reverse('api:organization_notifiers_error_list', args=(obj.pk,)), + notification_templates = reverse('api:organization_notification_templates_list', args=(obj.pk,)), + notification_templates_any = reverse('api:organization_notification_templates_any_list', args=(obj.pk,)), + notification_templates_success = reverse('api:organization_notification_templates_success_list', args=(obj.pk,)), + notification_templates_error = reverse('api:organization_notification_templates_error_list', args=(obj.pk,)), access_list = reverse('api:organization_access_list', args=(obj.pk,)), )) return res @@ -885,9 +885,9 @@ class ProjectSerializer(UnifiedJobTemplateSerializer, ProjectOptionsSerializer): project_updates = reverse('api:project_updates_list', args=(obj.pk,)), schedules = reverse('api:project_schedules_list', args=(obj.pk,)), activity_stream = reverse('api:project_activity_stream_list', args=(obj.pk,)), - notifiers_any = reverse('api:project_notifiers_any_list', args=(obj.pk,)), - notifiers_success = reverse('api:project_notifiers_success_list', args=(obj.pk,)), - notifiers_error = reverse('api:project_notifiers_error_list', args=(obj.pk,)), + notification_templates_any = reverse('api:project_notification_templates_any_list', args=(obj.pk,)), + notification_templates_success = reverse('api:project_notification_templates_success_list', args=(obj.pk,)), + notification_templates_error = reverse('api:project_notification_templates_error_list', args=(obj.pk,)), access_list = reverse('api:project_access_list', args=(obj.pk,)), )) if obj.organization: @@ -1347,9 +1347,9 @@ class InventorySourceSerializer(UnifiedJobTemplateSerializer, InventorySourceOpt activity_stream = reverse('api:inventory_activity_stream_list', args=(obj.pk,)), hosts = reverse('api:inventory_source_hosts_list', args=(obj.pk,)), groups = reverse('api:inventory_source_groups_list', args=(obj.pk,)), - notifiers_any = reverse('api:inventory_source_notifiers_any_list', args=(obj.pk,)), - notifiers_success = reverse('api:inventory_source_notifiers_success_list', args=(obj.pk,)), - notifiers_error = reverse('api:inventory_source_notifiers_error_list', args=(obj.pk,)), + notification_templates_any = reverse('api:inventory_source_notification_templates_any_list', args=(obj.pk,)), + notification_templates_success = reverse('api:inventory_source_notification_templates_success_list', args=(obj.pk,)), + notification_templates_error = reverse('api:inventory_source_notification_templates_error_list', args=(obj.pk,)), )) if obj.inventory: res['inventory'] = reverse('api:inventory_detail', args=(obj.inventory.pk,)) @@ -1730,9 +1730,9 @@ class JobTemplateSerializer(UnifiedJobTemplateSerializer, JobOptionsSerializer): schedules = reverse('api:job_template_schedules_list', args=(obj.pk,)), activity_stream = reverse('api:job_template_activity_stream_list', args=(obj.pk,)), launch = reverse('api:job_template_launch', args=(obj.pk,)), - notifiers_any = reverse('api:job_template_notifiers_any_list', args=(obj.pk,)), - notifiers_success = reverse('api:job_template_notifiers_success_list', args=(obj.pk,)), - notifiers_error = reverse('api:job_template_notifiers_error_list', args=(obj.pk,)), + notification_templates_any = reverse('api:job_template_notification_templates_any_list', args=(obj.pk,)), + notification_templates_success = reverse('api:job_template_notification_templates_success_list', args=(obj.pk,)), + notification_templates_error = reverse('api:job_template_notification_templates_error_list', args=(obj.pk,)), access_list = reverse('api:job_template_access_list', args=(obj.pk,)), survey_spec = reverse('api:job_template_survey_spec', args=(obj.pk,)), labels = reverse('api:job_template_label_list', args=(obj.pk,)), @@ -2028,9 +2028,9 @@ class SystemJobTemplateSerializer(UnifiedJobTemplateSerializer): jobs = reverse('api:system_job_template_jobs_list', args=(obj.pk,)), schedules = reverse('api:system_job_template_schedules_list', args=(obj.pk,)), launch = reverse('api:system_job_template_launch', args=(obj.pk,)), - notifiers_any = reverse('api:system_job_template_notifiers_any_list', args=(obj.pk,)), - notifiers_success = reverse('api:system_job_template_notifiers_success_list', args=(obj.pk,)), - notifiers_error = reverse('api:system_job_template_notifiers_error_list', args=(obj.pk,)), + notification_templates_any = reverse('api:system_job_template_notification_templates_any_list', args=(obj.pk,)), + notification_templates_success = reverse('api:system_job_template_notification_templates_success_list', args=(obj.pk,)), + notification_templates_error = reverse('api:system_job_template_notification_templates_error_list', args=(obj.pk,)), )) return res @@ -2286,10 +2286,10 @@ class JobLaunchSerializer(BaseSerializer): obj.credential = JT_credential return attrs -class NotifierSerializer(BaseSerializer): +class NotificationTemplateSerializer(BaseSerializer): class Meta: - model = Notifier + model = NotificationTemplate fields = ('*', 'organization', 'notification_type', 'notification_configuration') type_map = {"string": (str, unicode), @@ -2300,7 +2300,7 @@ class NotifierSerializer(BaseSerializer): "object": (dict, OrderedDict)} def to_representation(self, obj): - ret = super(NotifierSerializer, self).to_representation(obj) + ret = super(NotificationTemplateSerializer, self).to_representation(obj) for field in obj.notification_class.init_parameters: if field in ret['notification_configuration'] and \ force_text(ret['notification_configuration'][field]).startswith('$encrypted$'): @@ -2308,10 +2308,10 @@ class NotifierSerializer(BaseSerializer): return ret def get_related(self, obj): - res = super(NotifierSerializer, self).get_related(obj) + res = super(NotificationTemplateSerializer, self).get_related(obj) res.update(dict( - test = reverse('api:notifier_test', args=(obj.pk,)), - notifications = reverse('api:notifier_notification_list', args=(obj.pk,)), + test = reverse('api:notification_template_test', args=(obj.pk,)), + notifications = reverse('api:notification_template_notification_list', args=(obj.pk,)), )) if obj.organization: res['organization'] = reverse('api:organization_detail', args=(obj.organization.pk,)) @@ -2321,12 +2321,12 @@ class NotifierSerializer(BaseSerializer): return [{'id': x.id, 'status': x.status, 'created': x.created} for x in obj.notifications.all().order_by('-created')[:5]] def get_summary_fields(self, obj): - d = super(NotifierSerializer, self).get_summary_fields(obj) + d = super(NotificationTemplateSerializer, self).get_summary_fields(obj) d['recent_notifications'] = self._recent_notifications(obj) return d def validate(self, attrs): - notification_class = Notifier.CLASS_FOR_NOTIFICATION_TYPE[attrs['notification_type']] + notification_class = NotificationTemplate.CLASS_FOR_NOTIFICATION_TYPE[attrs['notification_type']] missing_fields = [] incorrect_type_fields = [] if 'notification_configuration' not in attrs: @@ -2362,13 +2362,13 @@ class NotificationSerializer(BaseSerializer): class Meta: model = Notification - fields = ('*', '-name', '-description', 'notifier', 'error', 'status', 'notifications_sent', + fields = ('*', '-name', '-description', 'notification_template', 'error', 'status', 'notifications_sent', 'notification_type', 'recipients', 'subject') def get_related(self, obj): res = super(NotificationSerializer, self).get_related(obj) res.update(dict( - notifier = reverse('api:notifier_detail', args=(obj.notifier.pk,)), + notification_template = reverse('api:notification_template_detail', args=(obj.notification_template.pk,)), )) return res diff --git a/awx/api/urls.py b/awx/api/urls.py index 5d496188d1..9d54a0a0fe 100644 --- a/awx/api/urls.py +++ b/awx/api/urls.py @@ -21,10 +21,10 @@ organization_urls = patterns('awx.api.views', url(r'^(?P[0-9]+)/teams/$', 'organization_teams_list'), url(r'^(?P[0-9]+)/credentials/$', 'organization_credential_list'), url(r'^(?P[0-9]+)/activity_stream/$', 'organization_activity_stream_list'), - url(r'^(?P[0-9]+)/notifiers/$', 'organization_notifiers_list'), - url(r'^(?P[0-9]+)/notifiers_any/$', 'organization_notifiers_any_list'), - url(r'^(?P[0-9]+)/notifiers_error/$', 'organization_notifiers_error_list'), - url(r'^(?P[0-9]+)/notifiers_success/$', 'organization_notifiers_success_list'), + url(r'^(?P[0-9]+)/notification_templates/$', 'organization_notification_templates_list'), + url(r'^(?P[0-9]+)/notification_templates_any/$', 'organization_notification_templates_any_list'), + url(r'^(?P[0-9]+)/notification_templates_error/$', 'organization_notification_templates_error_list'), + url(r'^(?P[0-9]+)/notification_templates_success/$', 'organization_notification_templates_success_list'), url(r'^(?P[0-9]+)/access_list/$', 'organization_access_list'), ) @@ -50,9 +50,9 @@ project_urls = patterns('awx.api.views', url(r'^(?P[0-9]+)/project_updates/$', 'project_updates_list'), url(r'^(?P[0-9]+)/activity_stream/$', 'project_activity_stream_list'), url(r'^(?P[0-9]+)/schedules/$', 'project_schedules_list'), - url(r'^(?P[0-9]+)/notifiers_any/$', 'project_notifiers_any_list'), - url(r'^(?P[0-9]+)/notifiers_error/$', 'project_notifiers_error_list'), - url(r'^(?P[0-9]+)/notifiers_success/$', 'project_notifiers_success_list'), + url(r'^(?P[0-9]+)/notification_templates_any/$', 'project_notification_templates_any_list'), + url(r'^(?P[0-9]+)/notification_templates_error/$', 'project_notification_templates_error_list'), + url(r'^(?P[0-9]+)/notification_templates_success/$', 'project_notification_templates_success_list'), url(r'^(?P[0-9]+)/access_list/$', 'project_access_list'), ) @@ -135,9 +135,9 @@ inventory_source_urls = patterns('awx.api.views', url(r'^(?P[0-9]+)/schedules/$', 'inventory_source_schedules_list'), url(r'^(?P[0-9]+)/groups/$', 'inventory_source_groups_list'), url(r'^(?P[0-9]+)/hosts/$', 'inventory_source_hosts_list'), - url(r'^(?P[0-9]+)/notifiers_any/$', 'inventory_source_notifiers_any_list'), - url(r'^(?P[0-9]+)/notifiers_error/$', 'inventory_source_notifiers_error_list'), - url(r'^(?P[0-9]+)/notifiers_success/$', 'inventory_source_notifiers_success_list'), + url(r'^(?P[0-9]+)/notification_templates_any/$', 'inventory_source_notification_templates_any_list'), + url(r'^(?P[0-9]+)/notification_templates_error/$', 'inventory_source_notification_templates_error_list'), + url(r'^(?P[0-9]+)/notification_templates_success/$', 'inventory_source_notification_templates_success_list'), ) inventory_update_urls = patterns('awx.api.views', @@ -178,9 +178,9 @@ job_template_urls = patterns('awx.api.views', url(r'^(?P[0-9]+)/schedules/$', 'job_template_schedules_list'), url(r'^(?P[0-9]+)/survey_spec/$', 'job_template_survey_spec'), url(r'^(?P[0-9]+)/activity_stream/$', 'job_template_activity_stream_list'), - url(r'^(?P[0-9]+)/notifiers_any/$', 'job_template_notifiers_any_list'), - url(r'^(?P[0-9]+)/notifiers_error/$', 'job_template_notifiers_error_list'), - url(r'^(?P[0-9]+)/notifiers_success/$', 'job_template_notifiers_success_list'), + url(r'^(?P[0-9]+)/notification_templates_any/$', 'job_template_notification_templates_any_list'), + url(r'^(?P[0-9]+)/notification_templates_error/$', 'job_template_notification_templates_error_list'), + url(r'^(?P[0-9]+)/notification_templates_success/$', 'job_template_notification_templates_success_list'), url(r'^(?P[0-9]+)/access_list/$', 'job_template_access_list'), url(r'^(?P[0-9]+)/labels/$', 'job_template_label_list'), ) @@ -233,9 +233,9 @@ system_job_template_urls = patterns('awx.api.views', url(r'^(?P[0-9]+)/launch/$', 'system_job_template_launch'), url(r'^(?P[0-9]+)/jobs/$', 'system_job_template_jobs_list'), url(r'^(?P[0-9]+)/schedules/$', 'system_job_template_schedules_list'), - url(r'^(?P[0-9]+)/notifiers_any/$', 'system_job_template_notifiers_any_list'), - url(r'^(?P[0-9]+)/notifiers_error/$', 'system_job_template_notifiers_error_list'), - url(r'^(?P[0-9]+)/notifiers_success/$', 'system_job_template_notifiers_success_list'), + url(r'^(?P[0-9]+)/notification_templates_any/$', 'system_job_template_notification_templates_any_list'), + url(r'^(?P[0-9]+)/notification_templates_error/$', 'system_job_template_notification_templates_error_list'), + url(r'^(?P[0-9]+)/notification_templates_success/$', 'system_job_template_notification_templates_success_list'), ) system_job_urls = patterns('awx.api.views', @@ -245,11 +245,11 @@ system_job_urls = patterns('awx.api.views', url(r'^(?P[0-9]+)/notifications/$', 'system_job_notifications_list'), ) -notifier_urls = patterns('awx.api.views', - url(r'^$', 'notifier_list'), - url(r'^(?P[0-9]+)/$', 'notifier_detail'), - url(r'^(?P[0-9]+)/test/$', 'notifier_test'), - url(r'^(?P[0-9]+)/notifications/$', 'notifier_notification_list'), +notification_template_urls = patterns('awx.api.views', + url(r'^$', 'notification_template_list'), + url(r'^(?P[0-9]+)/$', 'notification_template_detail'), + url(r'^(?P[0-9]+)/test/$', 'notification_template_test'), + url(r'^(?P[0-9]+)/notifications/$', 'notification_template_notification_list'), ) notification_urls = patterns('awx.api.views', @@ -310,7 +310,7 @@ v1_urls = patterns('awx.api.views', url(r'^ad_hoc_command_events/', include(ad_hoc_command_event_urls)), url(r'^system_job_templates/', include(system_job_template_urls)), url(r'^system_jobs/', include(system_job_urls)), - url(r'^notifiers/', include(notifier_urls)), + url(r'^notification_templates/', include(notification_template_urls)), url(r'^notifications/', include(notification_urls)), url(r'^labels/', include(label_urls)), url(r'^unified_job_templates/$','unified_job_template_list'), diff --git a/awx/api/views.py b/awx/api/views.py index aa476f18c6..ff64bdbb1b 100644 --- a/awx/api/views.py +++ b/awx/api/views.py @@ -140,7 +140,7 @@ class ApiV1RootView(APIView): data['system_jobs'] = reverse('api:system_job_list') data['schedules'] = reverse('api:schedule_list') data['roles'] = reverse('api:role_list') - data['notifiers'] = reverse('api:notifier_list') + data['notification_templates'] = reverse('api:notification_template_list') data['notifications'] = reverse('api:notification_list') data['labels'] = reverse('api:label_list') data['unified_job_templates'] = reverse('api:unified_job_template_list') @@ -764,34 +764,34 @@ class OrganizationActivityStreamList(SubListAPIView): # Okay, let it through. return super(OrganizationActivityStreamList, self).get(request, *args, **kwargs) -class OrganizationNotifiersList(SubListCreateAttachDetachAPIView): +class OrganizationNotificationTemplatesList(SubListCreateAttachDetachAPIView): - model = Notifier - serializer_class = NotifierSerializer + model = NotificationTemplate + serializer_class = NotificationTemplateSerializer parent_model = Organization - relationship = 'notifiers' + relationship = 'notification_templates' parent_key = 'organization' -class OrganizationNotifiersAnyList(SubListCreateAttachDetachAPIView): +class OrganizationNotificationTemplatesAnyList(SubListCreateAttachDetachAPIView): - model = Notifier - serializer_class = NotifierSerializer + model = NotificationTemplate + serializer_class = NotificationTemplateSerializer parent_model = Organization - relationship = 'notifiers_any' + relationship = 'notification_templates_any' -class OrganizationNotifiersErrorList(SubListCreateAttachDetachAPIView): +class OrganizationNotificationTemplatesErrorList(SubListCreateAttachDetachAPIView): - model = Notifier - serializer_class = NotifierSerializer + model = NotificationTemplate + serializer_class = NotificationTemplateSerializer parent_model = Organization - relationship = 'notifiers_error' + relationship = 'notification_templates_error' -class OrganizationNotifiersSuccessList(SubListCreateAttachDetachAPIView): +class OrganizationNotificationTemplatesSuccessList(SubListCreateAttachDetachAPIView): - model = Notifier - serializer_class = NotifierSerializer + model = NotificationTemplate + serializer_class = NotificationTemplateSerializer parent_model = Organization - relationship = 'notifiers_success' + relationship = 'notification_templates_success' class OrganizationAccessList(ResourceAccessList): @@ -981,26 +981,26 @@ class ProjectActivityStreamList(SubListAPIView): return qs.filter(project=parent) return qs.filter(Q(project=parent) | Q(credential__in=parent.credential)) -class ProjectNotifiersAnyList(SubListCreateAttachDetachAPIView): +class ProjectNotificationTemplatesAnyList(SubListCreateAttachDetachAPIView): - model = Notifier - serializer_class = NotifierSerializer + model = NotificationTemplate + serializer_class = NotificationTemplateSerializer parent_model = Project - relationship = 'notifiers_any' + relationship = 'notification_templates_any' -class ProjectNotifiersErrorList(SubListCreateAttachDetachAPIView): +class ProjectNotificationTemplatesErrorList(SubListCreateAttachDetachAPIView): - model = Notifier - serializer_class = NotifierSerializer + model = NotificationTemplate + serializer_class = NotificationTemplateSerializer parent_model = Project - relationship = 'notifiers_error' + relationship = 'notification_templates_error' -class ProjectNotifiersSuccessList(SubListCreateAttachDetachAPIView): +class ProjectNotificationTemplatesSuccessList(SubListCreateAttachDetachAPIView): - model = Notifier - serializer_class = NotifierSerializer + model = NotificationTemplate + serializer_class = NotificationTemplateSerializer parent_model = Project - relationship = 'notifiers_success' + relationship = 'notification_templates_success' class ProjectUpdatesList(SubListAPIView): @@ -1991,26 +1991,26 @@ class InventorySourceActivityStreamList(SubListAPIView): # Okay, let it through. return super(InventorySourceActivityStreamList, self).get(request, *args, **kwargs) -class InventorySourceNotifiersAnyList(SubListCreateAttachDetachAPIView): +class InventorySourceNotificationTemplatesAnyList(SubListCreateAttachDetachAPIView): - model = Notifier - serializer_class = NotifierSerializer + model = NotificationTemplate + serializer_class = NotificationTemplateSerializer parent_model = InventorySource - relationship = 'notifiers_any' + relationship = 'notification_templates_any' -class InventorySourceNotifiersErrorList(SubListCreateAttachDetachAPIView): +class InventorySourceNotificationTemplatesErrorList(SubListCreateAttachDetachAPIView): - model = Notifier - serializer_class = NotifierSerializer + model = NotificationTemplate + serializer_class = NotificationTemplateSerializer parent_model = InventorySource - relationship = 'notifiers_error' + relationship = 'notification_templates_error' -class InventorySourceNotifiersSuccessList(SubListCreateAttachDetachAPIView): +class InventorySourceNotificationTemplatesSuccessList(SubListCreateAttachDetachAPIView): - model = Notifier - serializer_class = NotifierSerializer + model = NotificationTemplate + serializer_class = NotificationTemplateSerializer parent_model = InventorySource - relationship = 'notifiers_success' + relationship = 'notification_templates_success' class InventorySourceHostsList(SubListAPIView): @@ -2270,26 +2270,26 @@ class JobTemplateActivityStreamList(SubListAPIView): # Okay, let it through. return super(JobTemplateActivityStreamList, self).get(request, *args, **kwargs) -class JobTemplateNotifiersAnyList(SubListCreateAttachDetachAPIView): +class JobTemplateNotificationTemplatesAnyList(SubListCreateAttachDetachAPIView): - model = Notifier - serializer_class = NotifierSerializer + model = NotificationTemplate + serializer_class = NotificationTemplateSerializer parent_model = JobTemplate - relationship = 'notifiers_any' + relationship = 'notification_templates_any' -class JobTemplateNotifiersErrorList(SubListCreateAttachDetachAPIView): +class JobTemplateNotificationTemplatesErrorList(SubListCreateAttachDetachAPIView): - model = Notifier - serializer_class = NotifierSerializer + model = NotificationTemplate + serializer_class = NotificationTemplateSerializer parent_model = JobTemplate - relationship = 'notifiers_error' + relationship = 'notification_templates_error' -class JobTemplateNotifiersSuccessList(SubListCreateAttachDetachAPIView): +class JobTemplateNotificationTemplatesSuccessList(SubListCreateAttachDetachAPIView): - model = Notifier - serializer_class = NotifierSerializer + model = NotificationTemplate + serializer_class = NotificationTemplateSerializer parent_model = JobTemplate - relationship = 'notifiers_success' + relationship = 'notification_templates_success' class JobTemplateLabelList(SubListCreateAttachDetachAPIView, DeleteLastUnattachLabelMixin): @@ -2526,26 +2526,26 @@ class SystemJobTemplateJobsList(SubListAPIView): relationship = 'jobs' parent_key = 'system_job_template' -class SystemJobTemplateNotifiersAnyList(SubListCreateAttachDetachAPIView): +class SystemJobTemplateNotificationTemplatesAnyList(SubListCreateAttachDetachAPIView): - model = Notifier - serializer_class = NotifierSerializer + model = NotificationTemplate + serializer_class = NotificationTemplateSerializer parent_model = SystemJobTemplate - relationship = 'notifiers_any' + relationship = 'notification_templates_any' -class SystemJobTemplateNotifiersErrorList(SubListCreateAttachDetachAPIView): +class SystemJobTemplateNotificationTemplatesErrorList(SubListCreateAttachDetachAPIView): - model = Notifier - serializer_class = NotifierSerializer + model = NotificationTemplate + serializer_class = NotificationTemplateSerializer parent_model = SystemJobTemplate - relationship = 'notifiers_error' + relationship = 'notification_templates_error' -class SystemJobTemplateNotifiersSuccessList(SubListCreateAttachDetachAPIView): +class SystemJobTemplateNotificationTemplatesSuccessList(SubListCreateAttachDetachAPIView): - model = Notifier - serializer_class = NotifierSerializer + model = NotificationTemplate + serializer_class = NotificationTemplateSerializer parent_model = SystemJobTemplate - relationship = 'notifiers_success' + relationship = 'notification_templates_success' class JobList(ListCreateAPIView): @@ -3335,22 +3335,22 @@ class AdHocCommandStdout(UnifiedJobStdout): model = AdHocCommand new_in_220 = True -class NotifierList(ListCreateAPIView): +class NotificationTemplateList(ListCreateAPIView): - model = Notifier - serializer_class = NotifierSerializer + model = NotificationTemplate + serializer_class = NotificationTemplateSerializer new_in_300 = True -class NotifierDetail(RetrieveUpdateDestroyAPIView): +class NotificationTemplateDetail(RetrieveUpdateDestroyAPIView): - model = Notifier - serializer_class = NotifierSerializer + model = NotificationTemplate + serializer_class = NotificationTemplateSerializer new_in_300 = True -class NotifierTest(GenericAPIView): +class NotificationTemplateTest(GenericAPIView): - view_name = 'Notifier Test' - model = Notifier + view_name = 'NotificationTemplate Test' + model = NotificationTemplate serializer_class = EmptySerializer new_in_300 = True @@ -3367,13 +3367,13 @@ class NotifierTest(GenericAPIView): headers=headers, status=status.HTTP_202_ACCEPTED) -class NotifierNotificationList(SubListAPIView): +class NotificationTemplateNotificationList(SubListAPIView): model = Notification serializer_class = NotificationSerializer - parent_model = Notifier + parent_model = NotificationTemplate relationship = 'notifications' - parent_key = 'notifier' + parent_key = 'notification_template' class NotificationList(ListAPIView): diff --git a/awx/main/access.py b/awx/main/access.py index 2130997130..64b7adfcb6 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -1204,11 +1204,11 @@ class ScheduleAccess(BaseAccess): else: return False -class NotifierAccess(BaseAccess): +class NotificationTemplateAccess(BaseAccess): ''' - I can see/use a notifier if I have permission to + I can see/use a notification_template if I have permission to ''' - model = Notifier + model = NotificationTemplate def get_queryset(self): qs = self.model.objects.all() @@ -1257,13 +1257,13 @@ class NotificationAccess(BaseAccess): qs = self.model.objects.all() if self.user.is_superuser: return qs - return self.model.objects.filter(notifier__organization__in=Organization.accessible_objects(self.user, 'admin_role')) + return self.model.objects.filter(notification_template__organization__in=Organization.accessible_objects(self.user, 'admin_role')) def can_read(self, obj): - return self.user.can_access(Notifier, 'read', obj.notifier) + return self.user.can_access(NotificationTemplate, 'read', obj.notification_template) def can_delete(self, obj): - return self.user.can_access(Notifier, 'delete', obj.notifier) + return self.user.can_access(NotificationTemplate, 'delete', obj.notification_template) class LabelAccess(BaseAccess): ''' @@ -1483,6 +1483,6 @@ register_access(ActivityStream, ActivityStreamAccess) register_access(CustomInventoryScript, CustomInventoryScriptAccess) register_access(TowerSettings, TowerSettingsAccess) register_access(Role, RoleAccess) -register_access(Notifier, NotifierAccess) +register_access(NotificationTemplate, NotificationTemplateAccess) register_access(Notification, NotificationAccess) register_access(Label, LabelAccess) diff --git a/awx/main/migrations/0003_v300_notification_changes.py b/awx/main/migrations/0003_v300_notification_changes.py index d76ebef50d..7889009865 100644 --- a/awx/main/migrations/0003_v300_notification_changes.py +++ b/awx/main/migrations/0003_v300_notification_changes.py @@ -36,7 +36,7 @@ class Migration(migrations.Migration): }, ), migrations.CreateModel( - name='Notifier', + name='NotificationTemplate', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('created', models.DateTimeField(default=None, editable=False)), @@ -46,16 +46,16 @@ class Migration(migrations.Migration): ('name', models.CharField(unique=True, max_length=512)), ('notification_type', models.CharField(max_length=32, choices=[(b'email', 'Email'), (b'slack', 'Slack'), (b'twilio', 'Twilio'), (b'pagerduty', 'Pagerduty'), (b'hipchat', 'HipChat'), (b'webhook', 'Webhook'), (b'irc', 'IRC')])), ('notification_configuration', jsonfield.fields.JSONField(default=dict)), - ('created_by', models.ForeignKey(related_name="{u'class': 'notifier', u'app_label': 'main'}(class)s_created+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)), - ('modified_by', models.ForeignKey(related_name="{u'class': 'notifier', u'app_label': 'main'}(class)s_modified+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)), - ('organization', models.ForeignKey(related_name='notifiers', on_delete=django.db.models.deletion.SET_NULL, to='main.Organization', null=True)), + ('created_by', models.ForeignKey(related_name="{u'class': 'notification_template', u'app_label': 'main'}(class)s_created+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)), + ('modified_by', models.ForeignKey(related_name="{u'class': 'notification_template', u'app_label': 'main'}(class)s_modified+", on_delete=django.db.models.deletion.SET_NULL, default=None, editable=False, to=settings.AUTH_USER_MODEL, null=True)), + ('organization', models.ForeignKey(related_name='notification_templates', on_delete=django.db.models.deletion.SET_NULL, to='main.Organization', null=True)), ('tags', taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Tags')), ], ), migrations.AddField( model_name='notification', - name='notifier', - field=models.ForeignKey(related_name='notifications', editable=False, to='main.Notifier'), + name='notification_template', + field=models.ForeignKey(related_name='notifications', editable=False, to='main.NotificationTemplate'), ), migrations.AddField( model_name='activitystream', @@ -64,23 +64,23 @@ class Migration(migrations.Migration): ), migrations.AddField( model_name='activitystream', - name='notifier', - field=models.ManyToManyField(to='main.Notifier', blank=True), + name='notification_template', + field=models.ManyToManyField(to='main.NotificationTemplate', blank=True), ), migrations.AddField( model_name='organization', - name='notifiers_any', - field=models.ManyToManyField(related_name='organization_notifiers_for_any', to='main.Notifier', blank=True), + name='notification_templates_any', + field=models.ManyToManyField(related_name='organization_notification_templates_for_any', to='main.NotificationTemplate', blank=True), ), migrations.AddField( model_name='organization', - name='notifiers_error', - field=models.ManyToManyField(related_name='organization_notifiers_for_errors', to='main.Notifier', blank=True), + name='notification_templates_error', + field=models.ManyToManyField(related_name='organization_notification_templates_for_errors', to='main.NotificationTemplate', blank=True), ), migrations.AddField( model_name='organization', - name='notifiers_success', - field=models.ManyToManyField(related_name='organization_notifiers_for_success', to='main.Notifier', blank=True), + name='notification_templates_success', + field=models.ManyToManyField(related_name='organization_notification_templates_for_success', to='main.NotificationTemplate', blank=True), ), migrations.AddField( model_name='unifiedjob', @@ -89,17 +89,17 @@ class Migration(migrations.Migration): ), migrations.AddField( model_name='unifiedjobtemplate', - name='notifiers_any', - field=models.ManyToManyField(related_name='unifiedjobtemplate_notifiers_for_any', to='main.Notifier', blank=True), + name='notification_templates_any', + field=models.ManyToManyField(related_name='unifiedjobtemplate_notification_templates_for_any', to='main.NotificationTemplate', blank=True), ), migrations.AddField( model_name='unifiedjobtemplate', - name='notifiers_error', - field=models.ManyToManyField(related_name='unifiedjobtemplate_notifiers_for_errors', to='main.Notifier', blank=True), + name='notification_templates_error', + field=models.ManyToManyField(related_name='unifiedjobtemplate_notification_templates_for_errors', to='main.NotificationTemplate', blank=True), ), migrations.AddField( model_name='unifiedjobtemplate', - name='notifiers_success', - field=models.ManyToManyField(related_name='unifiedjobtemplate_notifiers_for_success', to='main.Notifier', blank=True), + name='notification_templates_success', + field=models.ManyToManyField(related_name='unifiedjobtemplate_notification_templates_for_success', to='main.NotificationTemplate', blank=True), ), ] diff --git a/awx/main/migrations/_cleanup_deleted.py b/awx/main/migrations/_cleanup_deleted.py index db187efeb4..1a7e3cbb87 100644 --- a/awx/main/migrations/_cleanup_deleted.py +++ b/awx/main/migrations/_cleanup_deleted.py @@ -71,7 +71,7 @@ def cleanup_deleted(apps, schema_editor): apps.get_model('main', 'Group'), apps.get_model('main', 'Host'), apps.get_model('main', 'Inventory'), - apps.get_model('main', 'Notifier'), + apps.get_model('main', 'NotificationTemplate'), apps.get_model('main', 'Organization'), apps.get_model('main', 'Permission'), apps.get_model('main', 'Schedule'), diff --git a/awx/main/models/__init__.py b/awx/main/models/__init__.py index f6c9702d4b..ed13b4a30c 100644 --- a/awx/main/models/__init__.py +++ b/awx/main/models/__init__.py @@ -79,7 +79,7 @@ activity_stream_registrar.connect(AdHocCommand) activity_stream_registrar.connect(Schedule) activity_stream_registrar.connect(CustomInventoryScript) activity_stream_registrar.connect(TowerSettings) -activity_stream_registrar.connect(Notifier) +activity_stream_registrar.connect(NotificationTemplate) activity_stream_registrar.connect(Notification) activity_stream_registrar.connect(Label) activity_stream_registrar.connect(User) diff --git a/awx/main/models/activity_stream.py b/awx/main/models/activity_stream.py index ae07acd79c..007c29f258 100644 --- a/awx/main/models/activity_stream.py +++ b/awx/main/models/activity_stream.py @@ -53,7 +53,7 @@ class ActivityStream(models.Model): ad_hoc_command = models.ManyToManyField("AdHocCommand", blank=True) schedule = models.ManyToManyField("Schedule", blank=True) custom_inventory_script = models.ManyToManyField("CustomInventoryScript", blank=True) - notifier = models.ManyToManyField("Notifier", blank=True) + notification_template = models.ManyToManyField("NotificationTemplate", blank=True) notification = models.ManyToManyField("Notification", blank=True) label = models.ManyToManyField("Label", blank=True) role = models.ManyToManyField("Role", blank=True) diff --git a/awx/main/models/base.py b/awx/main/models/base.py index 4234f95d8f..8062a855fe 100644 --- a/awx/main/models/base.py +++ b/awx/main/models/base.py @@ -319,20 +319,20 @@ class NotificationFieldsModel(BaseModel): class Meta: abstract = True - notifiers_error = models.ManyToManyField( - "Notifier", + notification_templates_error = models.ManyToManyField( + "NotificationTemplate", blank=True, - related_name='%(class)s_notifiers_for_errors' + related_name='%(class)s_notification_templates_for_errors' ) - notifiers_success = models.ManyToManyField( - "Notifier", + notification_templates_success = models.ManyToManyField( + "NotificationTemplate", blank=True, - related_name='%(class)s_notifiers_for_success' + related_name='%(class)s_notification_templates_for_success' ) - notifiers_any = models.ManyToManyField( - "Notifier", + notification_templates_any = models.ManyToManyField( + "NotificationTemplate", blank=True, - related_name='%(class)s_notifiers_for_any' + related_name='%(class)s_notification_templates_for_any' ) diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 0eaf35c471..451a757670 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -25,7 +25,7 @@ from awx.main.models.base import * # noqa from awx.main.models.jobs import Job from awx.main.models.unified_jobs import * # noqa from awx.main.models.mixins import ResourceMixin -from awx.main.models.notifications import Notifier +from awx.main.models.notifications import NotificationTemplate from awx.main.utils import _inventory_updates from awx.main.conf import tower_settings @@ -1183,12 +1183,17 @@ class InventorySource(UnifiedJobTemplate, InventorySourceOptions): return False @property - def notifiers(self): - base_notifiers = Notifier.objects - error_notifiers = list(base_notifiers.filter(organization_notifiers_for_errors=self.inventory.organization)) - success_notifiers = list(base_notifiers.filter(organization_notifiers_for_success=self.inventory.organization)) - any_notifiers = list(base_notifiers.filter(organization_notifiers_for_any=self.inventory.organization)) - return dict(error=error_notifiers, success=success_notifiers, any=any_notifiers) + def notification_templates(self): + base_notification_templates = NotificationTemplate.objects + error_notification_templates = list(base_notification_templates + .filter(organization_notification_templates_for_errors=self.inventory.organization)) + success_notification_templates = list(base_notification_templates + .filter(organization_notification_templates_for_success=self.inventory.organization)) + any_notification_templates = list(base_notification_templates + .filter(organization_notification_templates_for_any=self.inventory.organization)) + return dict(error=error_notification_templates, + success=success_notification_templates, + any=any_notification_templates) def clean_source(self): source = self.source diff --git a/awx/main/models/jobs.py b/awx/main/models/jobs.py index 2d5c176604..5fa332ac20 100644 --- a/awx/main/models/jobs.py +++ b/awx/main/models/jobs.py @@ -23,7 +23,7 @@ from jsonfield import JSONField from awx.main.constants import CLOUD_PROVIDERS from awx.main.models.base import * # noqa from awx.main.models.unified_jobs import * # noqa -from awx.main.models.notifications import Notifier +from awx.main.models.notifications import NotificationTemplate from awx.main.utils import decrypt_field, ignore_inventory_computed_fields from awx.main.utils import emit_websocket_notification from awx.main.redact import PlainTextCleaner @@ -441,20 +441,20 @@ class JobTemplate(UnifiedJobTemplate, JobOptions, ResourceMixin): return self.can_start_without_user_input() @property - def notifiers(self): - # Return all notifiers defined on the Job Template, on the Project, and on the Organization for each trigger type + def notification_templates(self): + # Return all notification_templates defined on the Job Template, on the Project, and on the Organization for each trigger type # TODO: Currently there is no org fk on project so this will need to be added once that is # available after the rbac pr - base_notifiers = Notifier.objects - error_notifiers = list(base_notifiers.filter(unifiedjobtemplate_notifiers_for_errors__in=[self, self.project])) - success_notifiers = list(base_notifiers.filter(unifiedjobtemplate_notifiers_for_success__in=[self, self.project])) - any_notifiers = list(base_notifiers.filter(unifiedjobtemplate_notifiers_for_any__in=[self, self.project])) - # Get Organization Notifiers + base_notification_templates = NotificationTemplate.objects + error_notification_templates = list(base_notification_templates.filter(unifiedjobtemplate_notification_templates_for_errors__in=[self, self.project])) + success_notification_templates = list(base_notification_templates.filter(unifiedjobtemplate_notification_templates_for_success__in=[self, self.project])) + any_notification_templates = list(base_notification_templates.filter(unifiedjobtemplate_notification_templates_for_any__in=[self, self.project])) + # Get Organization NotificationTemplates if self.project is not None and self.project.organization is not None: - error_notifiers = set(error_notifiers + list(base_notifiers.filter(organization_notifiers_for_errors=self.project.organization))) - success_notifiers = set(success_notifiers + list(base_notifiers.filter(organization_notifiers_for_success=self.project.organization))) - any_notifiers = set(any_notifiers + list(base_notifiers.filter(organization_notifiers_for_any=self.project.organization))) - return dict(error=list(error_notifiers), success=list(success_notifiers), any=list(any_notifiers)) + error_notification_templates = set(error_notification_templates + list(base_notification_templates.filter(organization_notification_templates_for_errors=self.project.organization))) + success_notification_templates = set(success_notification_templates + list(base_notification_templates.filter(organization_notification_templates_for_success=self.project.organization))) + any_notification_templates = set(any_notification_templates + list(base_notification_templates.filter(organization_notification_templates_for_any=self.project.organization))) + return dict(error=list(error_notification_templates), success=list(success_notification_templates), any=list(any_notification_templates)) class Job(UnifiedJob, JobOptions): ''' @@ -1204,13 +1204,18 @@ class SystemJobTemplate(UnifiedJobTemplate, SystemJobOptions): return False @property - def notifiers(self): - # TODO: Go through RBAC instead of calling all(). Need to account for orphaned Notifiers - base_notifiers = Notifier.objects.all() - error_notifiers = list(base_notifiers.filter(unifiedjobtemplate_notifiers_for_errors__in=[self])) - success_notifiers = list(base_notifiers.filter(unifiedjobtemplate_notifiers_for_success__in=[self])) - any_notifiers = list(base_notifiers.filter(unifiedjobtemplate_notifiers_for_any__in=[self])) - return dict(error=list(error_notifiers), success=list(success_notifiers), any=list(any_notifiers)) + def notification_templates(self): + # TODO: Go through RBAC instead of calling all(). Need to account for orphaned NotificationTemplates + base_notification_templates = NotificationTemplate.objects.all() + error_notification_templates = list(base_notification_templates + .filter(unifiedjobtemplate_notification_templates_for_errors__in=[self])) + success_notification_templates = list(base_notification_templates + .filter(unifiedjobtemplate_notification_templates_for_success__in=[self])) + any_notification_templates = list(base_notification_templates + .filter(unifiedjobtemplate_notification_templates_for_any__in=[self])) + return dict(error=list(error_notification_templates), + success=list(success_notification_templates), + any=list(any_notification_templates)) class SystemJob(UnifiedJob, SystemJobOptions): diff --git a/awx/main/models/notifications.py b/awx/main/models/notifications.py index 40dcba67ac..75fffea642 100644 --- a/awx/main/models/notifications.py +++ b/awx/main/models/notifications.py @@ -24,9 +24,9 @@ from jsonfield import JSONField logger = logging.getLogger('awx.main.models.notifications') -__all__ = ['Notifier', 'Notification'] +__all__ = ['NotificationTemplate', 'Notification'] -class Notifier(CommonModel): +class NotificationTemplate(CommonModel): NOTIFICATION_TYPES = [('email', _('Email'), CustomEmailBackend), ('slack', _('Slack'), SlackBackend), @@ -46,7 +46,7 @@ class Notifier(CommonModel): blank=False, null=True, on_delete=models.SET_NULL, - related_name='notifiers', + related_name='notification_templates', ) notification_type = models.CharField( @@ -57,7 +57,7 @@ class Notifier(CommonModel): notification_configuration = JSONField(blank=False) def get_absolute_url(self): - return reverse('api:notifier_detail', args=(self.pk,)) + return reverse('api:notification_template_detail', args=(self.pk,)) @property def notification_class(self): @@ -79,7 +79,7 @@ class Notifier(CommonModel): self.notification_configuration[field] = encrypted if 'notification_configuration' not in update_fields: update_fields.append('notification_configuration') - super(Notifier, self).save(*args, **kwargs) + super(NotificationTemplate, self).save(*args, **kwargs) if new_instance: update_fields = [] for field in filter(lambda x: self.notification_class.init_parameters[x]['type'] == "password", @@ -95,7 +95,7 @@ class Notifier(CommonModel): return self.notification_configuration[self.notification_class.recipient_parameter] def generate_notification(self, subject, message): - notification = Notification(notifier=self, + notification = Notification(notification_template=self, notification_type=self.notification_type, recipients=smart_str(self.recipients), subject=subject, @@ -119,7 +119,7 @@ class Notifier(CommonModel): class Notification(CreatedModifiedModel): ''' - A notification event emitted when a Notifier is run + A notification event emitted when a NotificationTemplate is run ''' NOTIFICATION_STATE_CHOICES = [ @@ -132,8 +132,8 @@ class Notification(CreatedModifiedModel): app_label = 'main' ordering = ('pk',) - notifier = models.ForeignKey( - 'Notifier', + notification_template = models.ForeignKey( + 'NotificationTemplate', related_name='notifications', on_delete=models.CASCADE, editable=False @@ -155,7 +155,7 @@ class Notification(CreatedModifiedModel): ) notification_type = models.CharField( max_length = 32, - choices=Notifier.NOTIFICATION_TYPE_CHOICES, + choices=NotificationTemplate.NOTIFICATION_TYPE_CHOICES, ) recipients = models.TextField( blank=True, diff --git a/awx/main/models/projects.py b/awx/main/models/projects.py index 41145821f4..f987bd6af0 100644 --- a/awx/main/models/projects.py +++ b/awx/main/models/projects.py @@ -20,7 +20,7 @@ from django.utils.timezone import now, make_aware, get_default_timezone from awx.lib.compat import slugify from awx.main.models.base import * # noqa from awx.main.models.jobs import Job -from awx.main.models.notifications import Notifier +from awx.main.models.notifications import NotificationTemplate from awx.main.models.unified_jobs import * # noqa from awx.main.models.mixins import ResourceMixin from awx.main.utils import update_scm_url @@ -346,17 +346,28 @@ class Project(UnifiedJobTemplate, ProjectOptions, ResourceMixin): return False @property - def notifiers(self): - base_notifiers = Notifier.objects - error_notifiers = list(base_notifiers.filter(unifiedjobtemplate_notifiers_for_errors=self)) - success_notifiers = list(base_notifiers.filter(unifiedjobtemplate_notifiers_for_success=self)) - any_notifiers = list(base_notifiers.filter(unifiedjobtemplate_notifiers_for_any=self)) - # Get Organization Notifiers + def notification_templates(self): + base_notification_templates = NotificationTemplate.objects + error_notification_templates = list(base_notification_templates + .filter(unifiedjobtemplate_notification_templates_for_errors=self)) + success_notification_templates = list(base_notification_templates + .filter(unifiedjobtemplate_notification_templates_for_success=self)) + any_notification_templates = list(base_notification_templates + .filter(unifiedjobtemplate_notification_templates_for_any=self)) + # Get Organization NotificationTemplates if self.organization is not None: - error_notifiers = set(error_notifiers + list(base_notifiers.filter(organization_notifiers_for_errors=self.organization))) - success_notifiers = set(success_notifiers + list(base_notifiers.filter(organization_notifiers_for_success=self.organization))) - any_notifiers = set(any_notifiers + list(base_notifiers.filter(organization_notifiers_for_any=self.organization))) - return dict(error=list(error_notifiers), success=list(success_notifiers), any=list(any_notifiers)) + error_notification_templates = set(error_notification_templates + + list(base_notification_templates + .filter(organization_notification_templates_for_errors=self.organization))) + success_notification_templates = set(success_notification_templates + + list(base_notification_templates + .filter(organization_notification_templates_for_success=self.organization))) + any_notification_templates = set(any_notification_templates + + list(base_notification_templates + .filter(organization_notification_templates_for_any=self.organization))) + return dict(error=list(error_notification_templates), + success=list(success_notification_templates), + any=list(any_notification_templates)) def get_absolute_url(self): return reverse('api:project_detail', args=(self.pk,)) diff --git a/awx/main/models/unified_jobs.py b/awx/main/models/unified_jobs.py index d4920a1357..752dbff5a6 100644 --- a/awx/main/models/unified_jobs.py +++ b/awx/main/models/unified_jobs.py @@ -293,12 +293,12 @@ class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique, Notificatio return kwargs # Override if needed in subclass. @property - def notifiers(self): + def notification_templates(self): ''' - Return notifiers relevant to this Unified Job Template + Return notification_templates relevant to this Unified Job Template ''' # NOTE: Derived classes should implement - return Notifier.objects.none() + return NotificationTemplate.objects.none() def create_unified_job(self, **kwargs): ''' diff --git a/awx/main/signals.py b/awx/main/signals.py index 799a70f372..64402953a0 100644 --- a/awx/main/signals.py +++ b/awx/main/signals.py @@ -307,7 +307,7 @@ model_serializer_mapping = { Job: JobSerializer, AdHocCommand: AdHocCommandSerializer, TowerSettings: TowerSettingsSerializer, - Notifier: NotifierSerializer, + NotificationTemplate: NotificationTemplateSerializer, Notification: NotificationSerializer, } diff --git a/awx/main/tasks.py b/awx/main/tasks.py index a8ad070705..0ddb670c2b 100644 --- a/awx/main/tasks.py +++ b/awx/main/tasks.py @@ -77,7 +77,7 @@ def send_notifications(notification_list, job_id=None): for notification_id in notification_list: notification = Notification.objects.get(id=notification_id) try: - sent = notification.notifier.send(notification.subject, notification.body) + sent = notification.notification_template.send(notification.subject, notification.body) notification.status = "successful" notification.notifications_sent = sent except Exception as e: @@ -181,27 +181,27 @@ def handle_work_success(self, result, task_actual): if task_actual['type'] == 'project_update': instance = ProjectUpdate.objects.get(id=task_actual['id']) instance_name = instance.name - notifiers = instance.project.notifiers + notification_templates = instance.project.notification_templates friendly_name = "Project Update" elif task_actual['type'] == 'inventory_update': instance = InventoryUpdate.objects.get(id=task_actual['id']) instance_name = instance.name - notifiers = instance.inventory_source.notifiers + notification_templates = instance.inventory_source.notification_templates friendly_name = "Inventory Update" elif task_actual['type'] == 'job': instance = Job.objects.get(id=task_actual['id']) instance_name = instance.job_template.name - notifiers = instance.job_template.notifiers + notification_templates = instance.job_template.notification_templates friendly_name = "Job" elif task_actual['type'] == 'ad_hoc_command': instance = AdHocCommand.objects.get(id=task_actual['id']) instance_name = instance.module_name - notifiers = [] # TODO: Ad-hoc commands need to notify someone + notification_templates = [] # TODO: Ad-hoc commands need to notify someone friendly_name = "AdHoc Command" elif task_actual['type'] == 'system_job': instance = SystemJob.objects.get(id=task_actual['id']) instance_name = instance.system_job_template.name - notifiers = instance.system_job_template.notifiers + notification_templates = instance.system_job_template.notification_templates friendly_name = "System Job" else: return @@ -212,7 +212,7 @@ def handle_work_success(self, result, task_actual): notification_body['url']) notification_body['friendly_name'] = friendly_name send_notifications.delay([n.generate_notification(notification_subject, notification_body).id - for n in set(notifiers.get('success', []) + notifiers.get('any', []))], + for n in set(notification_templates.get('success', []) + notification_templates.get('any', []))], job_id=task_actual['id']) @task(bind=True) @@ -229,27 +229,27 @@ def handle_work_error(self, task_id, subtasks=None): if each_task['type'] == 'project_update': instance = ProjectUpdate.objects.get(id=each_task['id']) instance_name = instance.name - notifiers = instance.project.notifiers + notification_templates = instance.project.notification_templates friendly_name = "Project Update" elif each_task['type'] == 'inventory_update': instance = InventoryUpdate.objects.get(id=each_task['id']) instance_name = instance.name - notifiers = instance.inventory_source.notifiers + notification_templates = instance.inventory_source.notification_templates friendly_name = "Inventory Update" elif each_task['type'] == 'job': instance = Job.objects.get(id=each_task['id']) instance_name = instance.job_template.name - notifiers = instance.job_template.notifiers + notification_templates = instance.job_template.notification_templates friendly_name = "Job" elif each_task['type'] == 'ad_hoc_command': instance = AdHocCommand.objects.get(id=each_task['id']) instance_name = instance.module_name - notifiers = [] + notification_templates = [] friendly_name = "AdHoc Command" elif each_task['type'] == 'system_job': instance = SystemJob.objects.get(id=each_task['id']) instance_name = instance.system_job_template.name - notifiers = instance.system_job_template.notifiers + notification_templates = instance.system_job_template.notification_templates friendly_name = "System Job" else: # Unknown task type @@ -274,7 +274,7 @@ def handle_work_error(self, task_id, subtasks=None): notification_body['url']) notification_body['friendly_name'] = first_task_friendly_name send_notifications.delay([n.generate_notification(notification_subject, notification_body).id - for n in set(notifiers.get('error', []) + notifiers.get('any', []))], + for n in set(notification_templates.get('error', []) + notification_templates.get('any', []))], job_id=first_task_id) diff --git a/awx/main/tests/functional/conftest.py b/awx/main/tests/functional/conftest.py index 33c24f3cc6..f239e5d2a5 100644 --- a/awx/main/tests/functional/conftest.py +++ b/awx/main/tests/functional/conftest.py @@ -36,7 +36,7 @@ from awx.main.models.organization import ( Team, ) -from awx.main.models.notifications import Notifier +from awx.main.models.notifications import NotificationTemplate ''' Disable all django model signals. @@ -186,8 +186,8 @@ def label(organization): return organization.labels.create(name="test-label", description="test-label-desc") @pytest.fixture -def notifier(organization): - return Notifier.objects.create(name='test-notifier', +def notification_template(organization): + return NotificationTemplate.objects.create(name='test-notification_template', organization=organization, notification_type="webhook", notification_configuration=dict(url="http://localhost", @@ -270,18 +270,18 @@ def permissions(): } @pytest.fixture -def notifier_factory(organization): - def n(name="test-notifier"): +def notification_template_factory(organization): + def n(name="test-notification_template"): try: - notifier = Notifier.objects.get(name=name) - except Notifier.DoesNotExist: - notifier = Notifier(name=name, + notification_template = NotificationTemplate.objects.get(name=name) + except NotificationTemplate.DoesNotExist: + notification_template = NotificationTemplate(name=name, organization=organization, notification_type="webhook", notification_configuration=dict(url="http://localhost", headers={"Test": "Header"})) - notifier.save() - return notifier + notification_template.save() + return notification_template return n @pytest.fixture diff --git a/awx/main/tests/functional/test_notifications.py b/awx/main/tests/functional/test_notifications.py index 37fb394538..d6db3e608c 100644 --- a/awx/main/tests/functional/test_notifications.py +++ b/awx/main/tests/functional/test_notifications.py @@ -1,15 +1,15 @@ import mock import pytest -from awx.main.models.notifications import Notifier +from awx.main.models.notifications import NotificationTemplate from awx.main.models.inventory import Inventory, Group from awx.main.models.jobs import JobTemplate from django.core.urlresolvers import reverse @pytest.mark.django_db -def test_get_notifier_list(get, user, notifier): - url = reverse('api:notifier_list') +def test_get_notification_template_list(get, user, notification_template): + url = reverse('api:notification_template_list') response = get(url, user('admin', True)) assert response.status_code == 200 assert len(response.data['results']) == 1 @@ -17,7 +17,7 @@ def test_get_notifier_list(get, user, notifier): @pytest.mark.django_db def test_basic_parameterization(get, post, user, organization): u = user('admin-poster', True) - url = reverse('api:notifier_list') + url = reverse('api:notification_template_list') response = post(url, dict(name="test-webhook", description="test webhook", @@ -27,7 +27,7 @@ def test_basic_parameterization(get, post, user, organization): headers={"Test": "Header"})), u) assert response.status_code == 201 - url = reverse('api:notifier_detail', args=(response.data['id'],)) + url = reverse('api:notification_template_detail', args=(response.data['id'],)) response = get(url, u) assert 'related' in response.data assert 'organization' in response.data['related'] @@ -44,7 +44,7 @@ def test_encrypted_subfields(get, post, user, organization): assert self.account_token == "shouldhide" return 1 u = user('admin-poster', True) - url = reverse('api:notifier_list') + url = reverse('api:notification_template_list') response = post(url, dict(name="test-twilio", description="test twilio", @@ -56,18 +56,18 @@ def test_encrypted_subfields(get, post, user, organization): to_numbers=["9998887777"])), u) assert response.status_code == 201 - notifier_actual = Notifier.objects.get(id=response.data['id']) - url = reverse('api:notifier_detail', args=(response.data['id'],)) + notification_template_actual = NotificationTemplate.objects.get(id=response.data['id']) + url = reverse('api:notification_template_detail', args=(response.data['id'],)) response = get(url, u) assert response.data['notification_configuration']['account_token'] == "$encrypted$" - with mock.patch.object(notifier_actual.notification_class, "send_messages", assert_send): - notifier_actual.send("Test", {'body': "Test"}) + with mock.patch.object(notification_template_actual.notification_class, "send_messages", assert_send): + notification_template_actual.send("Test", {'body': "Test"}) @pytest.mark.django_db -def test_inherited_notifiers(get, post, user, organization, project): +def test_inherited_notification_templates(get, post, user, organization, project): u = user('admin-poster', True) - url = reverse('api:notifier_list') - notifiers = [] + url = reverse('api:notification_template_list') + notification_templates = [] for nfiers in xrange(3): response = post(url, dict(name="test-webhook-{}".format(nfiers), @@ -78,29 +78,29 @@ def test_inherited_notifiers(get, post, user, organization, project): headers={"Test": "Header"})), u) assert response.status_code == 201 - notifiers.append(response.data['id']) + notification_templates.append(response.data['id']) i = Inventory.objects.create(name='test', organization=organization) i.save() g = Group.objects.create(name='test', inventory=i) g.save() jt = JobTemplate.objects.create(name='test', inventory=i, project=project, playbook='debug.yml') jt.save() - url = reverse('api:organization_notifiers_any_list', args=(organization.id,)) - response = post(url, dict(id=notifiers[0]), u) + url = reverse('api:organization_notification_templates_any_list', args=(organization.id,)) + response = post(url, dict(id=notification_templates[0]), u) assert response.status_code == 204 - url = reverse('api:project_notifiers_any_list', args=(project.id,)) - response = post(url, dict(id=notifiers[1]), u) + url = reverse('api:project_notification_templates_any_list', args=(project.id,)) + response = post(url, dict(id=notification_templates[1]), u) assert response.status_code == 204 - url = reverse('api:job_template_notifiers_any_list', args=(jt.id,)) - response = post(url, dict(id=notifiers[2]), u) + url = reverse('api:job_template_notification_templates_any_list', args=(jt.id,)) + response = post(url, dict(id=notification_templates[2]), u) assert response.status_code == 204 - assert len(jt.notifiers['any']) == 3 - assert len(project.notifiers['any']) == 2 - assert len(g.inventory_source.notifiers['any']) == 1 + assert len(jt.notification_templates['any']) == 3 + assert len(project.notification_templates['any']) == 2 + assert len(g.inventory_source.notification_templates['any']) == 1 @pytest.mark.django_db -def test_notifier_merging(get, post, user, organization, project, notifier): +def test_notification_template_merging(get, post, user, organization, project, notification_template): user('admin-poster', True) - organization.notifiers_any.add(notifier) - project.notifiers_any.add(notifier) - assert len(project.notifiers['any']) == 1 + organization.notification_templates_any.add(notification_template) + project.notification_templates_any.add(notification_template) + assert len(project.notification_templates['any']) == 1 diff --git a/awx/main/tests/functional/test_rbac_notifications.py b/awx/main/tests/functional/test_rbac_notifications.py index 6d767ada4f..467ae8038a 100644 --- a/awx/main/tests/functional/test_rbac_notifications.py +++ b/awx/main/tests/functional/test_rbac_notifications.py @@ -1,36 +1,36 @@ import pytest -from awx.main.access import NotifierAccess +from awx.main.access import NotificationTemplateAccess @pytest.mark.django_db -def test_notifier_get_queryset_orgmember(notifier, user): - access = NotifierAccess(user('user', False)) - notifier.organization.member_role.members.add(user('user', False)) +def test_notification_template_get_queryset_orgmember(notification_template, user): + access = NotificationTemplateAccess(user('user', False)) + notification_template.organization.member_role.members.add(user('user', False)) assert access.get_queryset().count() == 0 @pytest.mark.django_db -def test_notifier_get_queryset_nonorgmember(notifier, user): - access = NotifierAccess(user('user', False)) +def test_notification_template_get_queryset_nonorgmember(notification_template, user): + access = NotificationTemplateAccess(user('user', False)) assert access.get_queryset().count() == 0 @pytest.mark.django_db -def test_notifier_get_queryset_su(notifier, user): - access = NotifierAccess(user('user', True)) +def test_notification_template_get_queryset_su(notification_template, user): + access = NotificationTemplateAccess(user('user', True)) assert access.get_queryset().count() == 1 @pytest.mark.django_db -def test_notifier_get_queryset_orgadmin(notifier, user): - access = NotifierAccess(user('admin', False)) - notifier.organization.admin_role.members.add(user('admin', False)) +def test_notification_template_get_queryset_orgadmin(notification_template, user): + access = NotificationTemplateAccess(user('admin', False)) + notification_template.organization.admin_role.members.add(user('admin', False)) assert access.get_queryset().count() == 1 @pytest.mark.django_db -def test_notifier_access_superuser(notifier, user, notifier_factory): - access = NotifierAccess(user('admin', True)) - assert access.can_read(notifier) - assert access.can_change(notifier, None) - assert access.can_delete(notifier) - nf = notifier_factory("test-orphaned") +def test_notification_template_access_superuser(notification_template, user, notification_template_factory): + access = NotificationTemplateAccess(user('admin', True)) + assert access.can_read(notification_template) + assert access.can_change(notification_template, None) + assert access.can_delete(notification_template) + nf = notification_template_factory("test-orphaned") nf.organization = None nf.save() assert access.can_read(nf) @@ -38,20 +38,20 @@ def test_notifier_access_superuser(notifier, user, notifier_factory): assert access.can_delete(nf) @pytest.mark.django_db -def test_notifier_access_admin(notifier, user, organization_factory, notifier_factory): +def test_notification_template_access_admin(notification_template, user, organization_factory, notification_template_factory): adm = user('admin', False) other_org = organization_factory('other') present_org = organization_factory('present') - notifier.organization.admin_role.members.add(adm) + notification_template.organization.admin_role.members.add(adm) present_org.admin_role.members.add(adm) - access = NotifierAccess(user('admin', False)) - assert not access.can_change(notifier, {'organization': other_org.id}) - assert access.can_read(notifier) - assert access.can_change(notifier, None) - assert access.can_change(notifier, {'organization': present_org.id}) - assert access.can_delete(notifier) - nf = notifier_factory("test-orphaned") + access = NotificationTemplateAccess(user('admin', False)) + assert not access.can_change(notification_template, {'organization': other_org.id}) + assert access.can_read(notification_template) + assert access.can_change(notification_template, None) + assert access.can_change(notification_template, {'organization': present_org.id}) + assert access.can_delete(notification_template) + nf = notification_template_factory("test-orphaned") nf.organization = None nf.save() assert not access.can_read(nf) @@ -59,10 +59,10 @@ def test_notifier_access_admin(notifier, user, organization_factory, notifier_fa assert not access.can_delete(nf) @pytest.mark.django_db -def test_notifier_access_org_user(notifier, user): +def test_notification_template_access_org_user(notification_template, user): u = user('normal', False) - notifier.organization.member_role.members.add(u) - access = NotifierAccess(user('normal', False)) - assert not access.can_read(notifier) - assert not access.can_change(notifier, None) - assert not access.can_delete(notifier) + notification_template.organization.member_role.members.add(u) + access = NotificationTemplateAccess(user('normal', False)) + assert not access.can_read(notification_template) + assert not access.can_change(notification_template, None) + assert not access.can_delete(notification_template) diff --git a/awx/main/tests/unit/api/test_serializers.py b/awx/main/tests/unit/api/test_serializers.py index 19f736a49e..f538f954ba 100644 --- a/awx/main/tests/unit/api/test_serializers.py +++ b/awx/main/tests/unit/api/test_serializers.py @@ -61,9 +61,9 @@ class TestJobTemplateSerializerGetRelated(GetRelatedMixin): 'schedules', 'activity_stream', 'launch', - 'notifiers_any', - 'notifiers_success', - 'notifiers_error', + 'notification_templates_any', + 'notification_templates_success', + 'notification_templates_error', 'survey_spec', 'labels', 'callback', diff --git a/awx/main/tests/unit/api/test_views.py b/awx/main/tests/unit/api/test_views.py index 6b886513bd..0200518078 100644 --- a/awx/main/tests/unit/api/test_views.py +++ b/awx/main/tests/unit/api/test_views.py @@ -37,7 +37,7 @@ class TestApiV1RootView: 'system_job_templates', 'system_jobs', 'schedules', - 'notifiers', + 'notification_templates', 'notifications', 'labels', 'unified_job_templates',