Merge pull request #3982 from beeankha/notify_on_start

Notification On Job Start

Reviewed-by: Bianca Henderson <beeankha@gmail.com>
             https://github.com/beeankha
This commit is contained in:
softwarefactory-project-zuul[bot]
2019-06-18 14:23:58 +00:00
committed by GitHub
27 changed files with 308 additions and 148 deletions

View File

@@ -1246,7 +1246,7 @@ class OrganizationSerializer(BaseSerializer):
applications = self.reverse('api:organization_applications_list', kwargs={'pk': obj.pk}), applications = self.reverse('api:organization_applications_list', kwargs={'pk': obj.pk}),
activity_stream = self.reverse('api:organization_activity_stream_list', kwargs={'pk': obj.pk}), activity_stream = self.reverse('api:organization_activity_stream_list', kwargs={'pk': obj.pk}),
notification_templates = self.reverse('api:organization_notification_templates_list', kwargs={'pk': obj.pk}), notification_templates = self.reverse('api:organization_notification_templates_list', kwargs={'pk': obj.pk}),
notification_templates_any = self.reverse('api:organization_notification_templates_any_list', kwargs={'pk': obj.pk}), notification_templates_started = self.reverse('api:organization_notification_templates_started_list', kwargs={'pk': obj.pk}),
notification_templates_success = self.reverse('api:organization_notification_templates_success_list', kwargs={'pk': obj.pk}), notification_templates_success = self.reverse('api:organization_notification_templates_success_list', kwargs={'pk': obj.pk}),
notification_templates_error = self.reverse('api:organization_notification_templates_error_list', kwargs={'pk': obj.pk}), notification_templates_error = self.reverse('api:organization_notification_templates_error_list', kwargs={'pk': obj.pk}),
object_roles = self.reverse('api:organization_object_roles_list', kwargs={'pk': obj.pk}), object_roles = self.reverse('api:organization_object_roles_list', kwargs={'pk': obj.pk}),
@@ -1352,7 +1352,7 @@ class ProjectSerializer(UnifiedJobTemplateSerializer, ProjectOptionsSerializer):
scm_inventory_sources = self.reverse('api:project_scm_inventory_sources', kwargs={'pk': obj.pk}), scm_inventory_sources = self.reverse('api:project_scm_inventory_sources', kwargs={'pk': obj.pk}),
schedules = self.reverse('api:project_schedules_list', kwargs={'pk': obj.pk}), schedules = self.reverse('api:project_schedules_list', kwargs={'pk': obj.pk}),
activity_stream = self.reverse('api:project_activity_stream_list', kwargs={'pk': obj.pk}), activity_stream = self.reverse('api:project_activity_stream_list', kwargs={'pk': obj.pk}),
notification_templates_any = self.reverse('api:project_notification_templates_any_list', kwargs={'pk': obj.pk}), notification_templates_started = self.reverse('api:project_notification_templates_started_list', kwargs={'pk': obj.pk}),
notification_templates_success = self.reverse('api:project_notification_templates_success_list', kwargs={'pk': obj.pk}), notification_templates_success = self.reverse('api:project_notification_templates_success_list', kwargs={'pk': obj.pk}),
notification_templates_error = self.reverse('api:project_notification_templates_error_list', kwargs={'pk': obj.pk}), notification_templates_error = self.reverse('api:project_notification_templates_error_list', kwargs={'pk': obj.pk}),
access_list = self.reverse('api:project_access_list', kwargs={'pk': obj.pk}), access_list = self.reverse('api:project_access_list', kwargs={'pk': obj.pk}),
@@ -1970,7 +1970,7 @@ class InventorySourceSerializer(UnifiedJobTemplateSerializer, InventorySourceOpt
activity_stream = self.reverse('api:inventory_source_activity_stream_list', kwargs={'pk': obj.pk}), activity_stream = self.reverse('api:inventory_source_activity_stream_list', kwargs={'pk': obj.pk}),
hosts = self.reverse('api:inventory_source_hosts_list', kwargs={'pk': obj.pk}), hosts = self.reverse('api:inventory_source_hosts_list', kwargs={'pk': obj.pk}),
groups = self.reverse('api:inventory_source_groups_list', kwargs={'pk': obj.pk}), groups = self.reverse('api:inventory_source_groups_list', kwargs={'pk': obj.pk}),
notification_templates_any = self.reverse('api:inventory_source_notification_templates_any_list', kwargs={'pk': obj.pk}), notification_templates_started = self.reverse('api:inventory_source_notification_templates_started_list', kwargs={'pk': obj.pk}),
notification_templates_success = self.reverse('api:inventory_source_notification_templates_success_list', kwargs={'pk': obj.pk}), notification_templates_success = self.reverse('api:inventory_source_notification_templates_success_list', kwargs={'pk': obj.pk}),
notification_templates_error = self.reverse('api:inventory_source_notification_templates_error_list', kwargs={'pk': obj.pk}), notification_templates_error = self.reverse('api:inventory_source_notification_templates_error_list', kwargs={'pk': obj.pk}),
)) ))
@@ -2792,7 +2792,7 @@ class JobTemplateSerializer(JobTemplateMixin, UnifiedJobTemplateSerializer, JobO
schedules = self.reverse('api:job_template_schedules_list', kwargs={'pk': obj.pk}), schedules = self.reverse('api:job_template_schedules_list', kwargs={'pk': obj.pk}),
activity_stream = self.reverse('api:job_template_activity_stream_list', kwargs={'pk': obj.pk}), activity_stream = self.reverse('api:job_template_activity_stream_list', kwargs={'pk': obj.pk}),
launch = self.reverse('api:job_template_launch', kwargs={'pk': obj.pk}), launch = self.reverse('api:job_template_launch', kwargs={'pk': obj.pk}),
notification_templates_any = self.reverse('api:job_template_notification_templates_any_list', kwargs={'pk': obj.pk}), notification_templates_started = self.reverse('api:job_template_notification_templates_started_list', kwargs={'pk': obj.pk}),
notification_templates_success = self.reverse('api:job_template_notification_templates_success_list', kwargs={'pk': obj.pk}), notification_templates_success = self.reverse('api:job_template_notification_templates_success_list', kwargs={'pk': obj.pk}),
notification_templates_error = self.reverse('api:job_template_notification_templates_error_list', kwargs={'pk': obj.pk}), notification_templates_error = self.reverse('api:job_template_notification_templates_error_list', kwargs={'pk': obj.pk}),
access_list = self.reverse('api:job_template_access_list', kwargs={'pk': obj.pk}), access_list = self.reverse('api:job_template_access_list', kwargs={'pk': obj.pk}),
@@ -3204,7 +3204,7 @@ class SystemJobTemplateSerializer(UnifiedJobTemplateSerializer):
jobs = self.reverse('api:system_job_template_jobs_list', kwargs={'pk': obj.pk}), jobs = self.reverse('api:system_job_template_jobs_list', kwargs={'pk': obj.pk}),
schedules = self.reverse('api:system_job_template_schedules_list', kwargs={'pk': obj.pk}), schedules = self.reverse('api:system_job_template_schedules_list', kwargs={'pk': obj.pk}),
launch = self.reverse('api:system_job_template_launch', kwargs={'pk': obj.pk}), launch = self.reverse('api:system_job_template_launch', kwargs={'pk': obj.pk}),
notification_templates_any = self.reverse('api:system_job_template_notification_templates_any_list', kwargs={'pk': obj.pk}), notification_templates_started = self.reverse('api:system_job_template_notification_templates_started_list', kwargs={'pk': obj.pk}),
notification_templates_success = self.reverse('api:system_job_template_notification_templates_success_list', kwargs={'pk': obj.pk}), notification_templates_success = self.reverse('api:system_job_template_notification_templates_success_list', kwargs={'pk': obj.pk}),
notification_templates_error = self.reverse('api:system_job_template_notification_templates_error_list', kwargs={'pk': obj.pk}), notification_templates_error = self.reverse('api:system_job_template_notification_templates_error_list', kwargs={'pk': obj.pk}),
@@ -3271,7 +3271,7 @@ class WorkflowJobTemplateSerializer(JobTemplateMixin, LabelsListMixin, UnifiedJo
workflow_nodes = self.reverse('api:workflow_job_template_workflow_nodes_list', kwargs={'pk': obj.pk}), workflow_nodes = self.reverse('api:workflow_job_template_workflow_nodes_list', kwargs={'pk': obj.pk}),
labels = self.reverse('api:workflow_job_template_label_list', kwargs={'pk': obj.pk}), labels = self.reverse('api:workflow_job_template_label_list', kwargs={'pk': obj.pk}),
activity_stream = self.reverse('api:workflow_job_template_activity_stream_list', kwargs={'pk': obj.pk}), activity_stream = self.reverse('api:workflow_job_template_activity_stream_list', kwargs={'pk': obj.pk}),
notification_templates_any = self.reverse('api:workflow_job_template_notification_templates_any_list', kwargs={'pk': obj.pk}), notification_templates_started = self.reverse('api:workflow_job_template_notification_templates_started_list', kwargs={'pk': obj.pk}),
notification_templates_success = self.reverse('api:workflow_job_template_notification_templates_success_list', kwargs={'pk': obj.pk}), notification_templates_success = self.reverse('api:workflow_job_template_notification_templates_success_list', kwargs={'pk': obj.pk}),
notification_templates_error = self.reverse('api:workflow_job_template_notification_templates_error_list', kwargs={'pk': obj.pk}), notification_templates_error = self.reverse('api:workflow_job_template_notification_templates_error_list', kwargs={'pk': obj.pk}),
access_list = self.reverse('api:workflow_job_template_access_list', kwargs={'pk': obj.pk}), access_list = self.reverse('api:workflow_job_template_access_list', kwargs={'pk': obj.pk}),

View File

@@ -13,8 +13,8 @@ from awx.api.views import (
InventorySourceCredentialsList, InventorySourceCredentialsList,
InventorySourceGroupsList, InventorySourceGroupsList,
InventorySourceHostsList, InventorySourceHostsList,
InventorySourceNotificationTemplatesAnyList,
InventorySourceNotificationTemplatesErrorList, InventorySourceNotificationTemplatesErrorList,
InventorySourceNotificationTemplatesStartedList,
InventorySourceNotificationTemplatesSuccessList, InventorySourceNotificationTemplatesSuccessList,
) )
@@ -29,8 +29,8 @@ urls = [
url(r'^(?P<pk>[0-9]+)/credentials/$', InventorySourceCredentialsList.as_view(), name='inventory_source_credentials_list'), url(r'^(?P<pk>[0-9]+)/credentials/$', InventorySourceCredentialsList.as_view(), name='inventory_source_credentials_list'),
url(r'^(?P<pk>[0-9]+)/groups/$', InventorySourceGroupsList.as_view(), name='inventory_source_groups_list'), url(r'^(?P<pk>[0-9]+)/groups/$', InventorySourceGroupsList.as_view(), name='inventory_source_groups_list'),
url(r'^(?P<pk>[0-9]+)/hosts/$', InventorySourceHostsList.as_view(), name='inventory_source_hosts_list'), url(r'^(?P<pk>[0-9]+)/hosts/$', InventorySourceHostsList.as_view(), name='inventory_source_hosts_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_any/$', InventorySourceNotificationTemplatesAnyList.as_view(), url(r'^(?P<pk>[0-9]+)/notification_templates_started/$', InventorySourceNotificationTemplatesStartedList.as_view(),
name='inventory_source_notification_templates_any_list'), name='inventory_source_notification_templates_started_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_error/$', InventorySourceNotificationTemplatesErrorList.as_view(), url(r'^(?P<pk>[0-9]+)/notification_templates_error/$', InventorySourceNotificationTemplatesErrorList.as_view(),
name='inventory_source_notification_templates_error_list'), name='inventory_source_notification_templates_error_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_success/$', InventorySourceNotificationTemplatesSuccessList.as_view(), url(r'^(?P<pk>[0-9]+)/notification_templates_success/$', InventorySourceNotificationTemplatesSuccessList.as_view(),

View File

@@ -13,8 +13,8 @@ from awx.api.views import (
JobTemplateSchedulesList, JobTemplateSchedulesList,
JobTemplateSurveySpec, JobTemplateSurveySpec,
JobTemplateActivityStreamList, JobTemplateActivityStreamList,
JobTemplateNotificationTemplatesAnyList,
JobTemplateNotificationTemplatesErrorList, JobTemplateNotificationTemplatesErrorList,
JobTemplateNotificationTemplatesStartedList,
JobTemplateNotificationTemplatesSuccessList, JobTemplateNotificationTemplatesSuccessList,
JobTemplateInstanceGroupsList, JobTemplateInstanceGroupsList,
JobTemplateAccessList, JobTemplateAccessList,
@@ -34,8 +34,8 @@ urls = [
url(r'^(?P<pk>[0-9]+)/schedules/$', JobTemplateSchedulesList.as_view(), name='job_template_schedules_list'), url(r'^(?P<pk>[0-9]+)/schedules/$', JobTemplateSchedulesList.as_view(), name='job_template_schedules_list'),
url(r'^(?P<pk>[0-9]+)/survey_spec/$', JobTemplateSurveySpec.as_view(), name='job_template_survey_spec'), url(r'^(?P<pk>[0-9]+)/survey_spec/$', JobTemplateSurveySpec.as_view(), name='job_template_survey_spec'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', JobTemplateActivityStreamList.as_view(), name='job_template_activity_stream_list'), url(r'^(?P<pk>[0-9]+)/activity_stream/$', JobTemplateActivityStreamList.as_view(), name='job_template_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_any/$', JobTemplateNotificationTemplatesAnyList.as_view(), url(r'^(?P<pk>[0-9]+)/notification_templates_started/$', JobTemplateNotificationTemplatesStartedList.as_view(),
name='job_template_notification_templates_any_list'), name='job_template_notification_templates_started_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_error/$', JobTemplateNotificationTemplatesErrorList.as_view(), url(r'^(?P<pk>[0-9]+)/notification_templates_error/$', JobTemplateNotificationTemplatesErrorList.as_view(),
name='job_template_notification_templates_error_list'), name='job_template_notification_templates_error_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_success/$', JobTemplateNotificationTemplatesSuccessList.as_view(), url(r'^(?P<pk>[0-9]+)/notification_templates_success/$', JobTemplateNotificationTemplatesSuccessList.as_view(),

View File

@@ -15,8 +15,8 @@ from awx.api.views import (
OrganizationCredentialList, OrganizationCredentialList,
OrganizationActivityStreamList, OrganizationActivityStreamList,
OrganizationNotificationTemplatesList, OrganizationNotificationTemplatesList,
OrganizationNotificationTemplatesAnyList,
OrganizationNotificationTemplatesErrorList, OrganizationNotificationTemplatesErrorList,
OrganizationNotificationTemplatesStartedList,
OrganizationNotificationTemplatesSuccessList, OrganizationNotificationTemplatesSuccessList,
OrganizationInstanceGroupsList, OrganizationInstanceGroupsList,
OrganizationObjectRolesList, OrganizationObjectRolesList,
@@ -37,8 +37,8 @@ urls = [
url(r'^(?P<pk>[0-9]+)/credentials/$', OrganizationCredentialList.as_view(), name='organization_credential_list'), url(r'^(?P<pk>[0-9]+)/credentials/$', OrganizationCredentialList.as_view(), name='organization_credential_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', OrganizationActivityStreamList.as_view(), name='organization_activity_stream_list'), url(r'^(?P<pk>[0-9]+)/activity_stream/$', OrganizationActivityStreamList.as_view(), name='organization_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates/$', OrganizationNotificationTemplatesList.as_view(), name='organization_notification_templates_list'), url(r'^(?P<pk>[0-9]+)/notification_templates/$', OrganizationNotificationTemplatesList.as_view(), name='organization_notification_templates_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_any/$', OrganizationNotificationTemplatesAnyList.as_view(), url(r'^(?P<pk>[0-9]+)/notification_templates_started/$', OrganizationNotificationTemplatesStartedList.as_view(),
name='organization_notification_templates_any_list'), name='organization_notification_templates_started_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_error/$', OrganizationNotificationTemplatesErrorList.as_view(), url(r'^(?P<pk>[0-9]+)/notification_templates_error/$', OrganizationNotificationTemplatesErrorList.as_view(),
name='organization_notification_templates_error_list'), name='organization_notification_templates_error_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_success/$', OrganizationNotificationTemplatesSuccessList.as_view(), url(r'^(?P<pk>[0-9]+)/notification_templates_success/$', OrganizationNotificationTemplatesSuccessList.as_view(),

View File

@@ -14,8 +14,8 @@ from awx.api.views import (
ProjectUpdatesList, ProjectUpdatesList,
ProjectActivityStreamList, ProjectActivityStreamList,
ProjectSchedulesList, ProjectSchedulesList,
ProjectNotificationTemplatesAnyList,
ProjectNotificationTemplatesErrorList, ProjectNotificationTemplatesErrorList,
ProjectNotificationTemplatesStartedList,
ProjectNotificationTemplatesSuccessList, ProjectNotificationTemplatesSuccessList,
ProjectObjectRolesList, ProjectObjectRolesList,
ProjectAccessList, ProjectAccessList,
@@ -34,10 +34,11 @@ urls = [
url(r'^(?P<pk>[0-9]+)/project_updates/$', ProjectUpdatesList.as_view(), name='project_updates_list'), url(r'^(?P<pk>[0-9]+)/project_updates/$', ProjectUpdatesList.as_view(), name='project_updates_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', ProjectActivityStreamList.as_view(), name='project_activity_stream_list'), url(r'^(?P<pk>[0-9]+)/activity_stream/$', ProjectActivityStreamList.as_view(), name='project_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/schedules/$', ProjectSchedulesList.as_view(), name='project_schedules_list'), url(r'^(?P<pk>[0-9]+)/schedules/$', ProjectSchedulesList.as_view(), name='project_schedules_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_any/$', ProjectNotificationTemplatesAnyList.as_view(), name='project_notification_templates_any_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_error/$', ProjectNotificationTemplatesErrorList.as_view(), name='project_notification_templates_error_list'), url(r'^(?P<pk>[0-9]+)/notification_templates_error/$', ProjectNotificationTemplatesErrorList.as_view(), name='project_notification_templates_error_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_success/$', ProjectNotificationTemplatesSuccessList.as_view(), url(r'^(?P<pk>[0-9]+)/notification_templates_success/$', ProjectNotificationTemplatesSuccessList.as_view(),
name='project_notification_templates_success_list'), name='project_notification_templates_success_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_started/$', ProjectNotificationTemplatesStartedList.as_view(),
name='project_notification_templates_started_list'),
url(r'^(?P<pk>[0-9]+)/object_roles/$', ProjectObjectRolesList.as_view(), name='project_object_roles_list'), url(r'^(?P<pk>[0-9]+)/object_roles/$', ProjectObjectRolesList.as_view(), name='project_object_roles_list'),
url(r'^(?P<pk>[0-9]+)/access_list/$', ProjectAccessList.as_view(), name='project_access_list'), url(r'^(?P<pk>[0-9]+)/access_list/$', ProjectAccessList.as_view(), name='project_access_list'),
url(r'^(?P<pk>[0-9]+)/copy/$', ProjectCopy.as_view(), name='project_copy'), url(r'^(?P<pk>[0-9]+)/copy/$', ProjectCopy.as_view(), name='project_copy'),

View File

@@ -9,8 +9,8 @@ from awx.api.views import (
SystemJobTemplateLaunch, SystemJobTemplateLaunch,
SystemJobTemplateJobsList, SystemJobTemplateJobsList,
SystemJobTemplateSchedulesList, SystemJobTemplateSchedulesList,
SystemJobTemplateNotificationTemplatesAnyList,
SystemJobTemplateNotificationTemplatesErrorList, SystemJobTemplateNotificationTemplatesErrorList,
SystemJobTemplateNotificationTemplatesStartedList,
SystemJobTemplateNotificationTemplatesSuccessList, SystemJobTemplateNotificationTemplatesSuccessList,
) )
@@ -21,8 +21,8 @@ urls = [
url(r'^(?P<pk>[0-9]+)/launch/$', SystemJobTemplateLaunch.as_view(), name='system_job_template_launch'), url(r'^(?P<pk>[0-9]+)/launch/$', SystemJobTemplateLaunch.as_view(), name='system_job_template_launch'),
url(r'^(?P<pk>[0-9]+)/jobs/$', SystemJobTemplateJobsList.as_view(), name='system_job_template_jobs_list'), url(r'^(?P<pk>[0-9]+)/jobs/$', SystemJobTemplateJobsList.as_view(), name='system_job_template_jobs_list'),
url(r'^(?P<pk>[0-9]+)/schedules/$', SystemJobTemplateSchedulesList.as_view(), name='system_job_template_schedules_list'), url(r'^(?P<pk>[0-9]+)/schedules/$', SystemJobTemplateSchedulesList.as_view(), name='system_job_template_schedules_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_any/$', SystemJobTemplateNotificationTemplatesAnyList.as_view(), url(r'^(?P<pk>[0-9]+)/notification_templates_started/$', SystemJobTemplateNotificationTemplatesStartedList.as_view(),
name='system_job_template_notification_templates_any_list'), name='system_job_template_notification_templates_started_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_error/$', SystemJobTemplateNotificationTemplatesErrorList.as_view(), url(r'^(?P<pk>[0-9]+)/notification_templates_error/$', SystemJobTemplateNotificationTemplatesErrorList.as_view(),
name='system_job_template_notification_templates_error_list'), name='system_job_template_notification_templates_error_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_success/$', SystemJobTemplateNotificationTemplatesSuccessList.as_view(), url(r'^(?P<pk>[0-9]+)/notification_templates_success/$', SystemJobTemplateNotificationTemplatesSuccessList.as_view(),

View File

@@ -13,8 +13,8 @@ from awx.api.views import (
WorkflowJobTemplateSurveySpec, WorkflowJobTemplateSurveySpec,
WorkflowJobTemplateWorkflowNodesList, WorkflowJobTemplateWorkflowNodesList,
WorkflowJobTemplateActivityStreamList, WorkflowJobTemplateActivityStreamList,
WorkflowJobTemplateNotificationTemplatesAnyList,
WorkflowJobTemplateNotificationTemplatesErrorList, WorkflowJobTemplateNotificationTemplatesErrorList,
WorkflowJobTemplateNotificationTemplatesStartedList,
WorkflowJobTemplateNotificationTemplatesSuccessList, WorkflowJobTemplateNotificationTemplatesSuccessList,
WorkflowJobTemplateAccessList, WorkflowJobTemplateAccessList,
WorkflowJobTemplateObjectRolesList, WorkflowJobTemplateObjectRolesList,
@@ -32,8 +32,8 @@ urls = [
url(r'^(?P<pk>[0-9]+)/survey_spec/$', WorkflowJobTemplateSurveySpec.as_view(), name='workflow_job_template_survey_spec'), url(r'^(?P<pk>[0-9]+)/survey_spec/$', WorkflowJobTemplateSurveySpec.as_view(), name='workflow_job_template_survey_spec'),
url(r'^(?P<pk>[0-9]+)/workflow_nodes/$', WorkflowJobTemplateWorkflowNodesList.as_view(), name='workflow_job_template_workflow_nodes_list'), url(r'^(?P<pk>[0-9]+)/workflow_nodes/$', WorkflowJobTemplateWorkflowNodesList.as_view(), name='workflow_job_template_workflow_nodes_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', WorkflowJobTemplateActivityStreamList.as_view(), name='workflow_job_template_activity_stream_list'), url(r'^(?P<pk>[0-9]+)/activity_stream/$', WorkflowJobTemplateActivityStreamList.as_view(), name='workflow_job_template_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_any/$', WorkflowJobTemplateNotificationTemplatesAnyList.as_view(), url(r'^(?P<pk>[0-9]+)/notification_templates_started/$', WorkflowJobTemplateNotificationTemplatesStartedList.as_view(),
name='workflow_job_template_notification_templates_any_list'), name='workflow_job_template_notification_templates_started_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_error/$', WorkflowJobTemplateNotificationTemplatesErrorList.as_view(), url(r'^(?P<pk>[0-9]+)/notification_templates_error/$', WorkflowJobTemplateNotificationTemplatesErrorList.as_view(),
name='workflow_job_template_notification_templates_error_list'), name='workflow_job_template_notification_templates_error_list'),
url(r'^(?P<pk>[0-9]+)/notification_templates_success/$', WorkflowJobTemplateNotificationTemplatesSuccessList.as_view(), url(r'^(?P<pk>[0-9]+)/notification_templates_success/$', WorkflowJobTemplateNotificationTemplatesSuccessList.as_view(),

View File

@@ -116,6 +116,7 @@ from awx.api.views.organization import ( # noqa
OrganizationNotificationTemplatesList, OrganizationNotificationTemplatesList,
OrganizationNotificationTemplatesAnyList, OrganizationNotificationTemplatesAnyList,
OrganizationNotificationTemplatesErrorList, OrganizationNotificationTemplatesErrorList,
OrganizationNotificationTemplatesStartedList,
OrganizationNotificationTemplatesSuccessList, OrganizationNotificationTemplatesSuccessList,
OrganizationInstanceGroupsList, OrganizationInstanceGroupsList,
OrganizationAccessList, OrganizationAccessList,
@@ -747,22 +748,20 @@ class ProjectNotificationTemplatesAnyList(SubListCreateAttachDetachAPIView):
model = models.NotificationTemplate model = models.NotificationTemplate
serializer_class = serializers.NotificationTemplateSerializer serializer_class = serializers.NotificationTemplateSerializer
parent_model = models.Project parent_model = models.Project
relationship = 'notification_templates_any'
class ProjectNotificationTemplatesErrorList(SubListCreateAttachDetachAPIView): class ProjectNotificationTemplatesStartedList(ProjectNotificationTemplatesAnyList):
relationship = 'notification_templates_started'
class ProjectNotificationTemplatesErrorList(ProjectNotificationTemplatesAnyList):
model = models.NotificationTemplate
serializer_class = serializers.NotificationTemplateSerializer
parent_model = models.Project
relationship = 'notification_templates_error' relationship = 'notification_templates_error'
class ProjectNotificationTemplatesSuccessList(SubListCreateAttachDetachAPIView): class ProjectNotificationTemplatesSuccessList(ProjectNotificationTemplatesAnyList):
model = models.NotificationTemplate
serializer_class = serializers.NotificationTemplateSerializer
parent_model = models.Project
relationship = 'notification_templates_success' relationship = 'notification_templates_success'
@@ -2102,7 +2101,6 @@ class InventorySourceNotificationTemplatesAnyList(SubListCreateAttachDetachAPIVi
model = models.NotificationTemplate model = models.NotificationTemplate
serializer_class = serializers.NotificationTemplateSerializer serializer_class = serializers.NotificationTemplateSerializer
parent_model = models.InventorySource parent_model = models.InventorySource
relationship = 'notification_templates_any'
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
parent = self.get_parent_object() parent = self.get_parent_object()
@@ -2113,6 +2111,11 @@ class InventorySourceNotificationTemplatesAnyList(SubListCreateAttachDetachAPIVi
return super(InventorySourceNotificationTemplatesAnyList, self).post(request, *args, **kwargs) return super(InventorySourceNotificationTemplatesAnyList, self).post(request, *args, **kwargs)
class InventorySourceNotificationTemplatesStartedList(InventorySourceNotificationTemplatesAnyList):
relationship = 'notification_templates_started'
class InventorySourceNotificationTemplatesErrorList(InventorySourceNotificationTemplatesAnyList): class InventorySourceNotificationTemplatesErrorList(InventorySourceNotificationTemplatesAnyList):
relationship = 'notification_templates_error' relationship = 'notification_templates_error'
@@ -2626,22 +2629,20 @@ class JobTemplateNotificationTemplatesAnyList(SubListCreateAttachDetachAPIView):
model = models.NotificationTemplate model = models.NotificationTemplate
serializer_class = serializers.NotificationTemplateSerializer serializer_class = serializers.NotificationTemplateSerializer
parent_model = models.JobTemplate parent_model = models.JobTemplate
relationship = 'notification_templates_any'
class JobTemplateNotificationTemplatesErrorList(SubListCreateAttachDetachAPIView): class JobTemplateNotificationTemplatesStartedList(JobTemplateNotificationTemplatesAnyList):
relationship = 'notification_templates_started'
class JobTemplateNotificationTemplatesErrorList(JobTemplateNotificationTemplatesAnyList):
model = models.NotificationTemplate
serializer_class = serializers.NotificationTemplateSerializer
parent_model = models.JobTemplate
relationship = 'notification_templates_error' relationship = 'notification_templates_error'
class JobTemplateNotificationTemplatesSuccessList(SubListCreateAttachDetachAPIView): class JobTemplateNotificationTemplatesSuccessList(JobTemplateNotificationTemplatesAnyList):
model = models.NotificationTemplate
serializer_class = serializers.NotificationTemplateSerializer
parent_model = models.JobTemplate
relationship = 'notification_templates_success' relationship = 'notification_templates_success'
@@ -3234,22 +3235,20 @@ class WorkflowJobTemplateNotificationTemplatesAnyList(SubListCreateAttachDetachA
model = models.NotificationTemplate model = models.NotificationTemplate
serializer_class = serializers.NotificationTemplateSerializer serializer_class = serializers.NotificationTemplateSerializer
parent_model = models.WorkflowJobTemplate parent_model = models.WorkflowJobTemplate
relationship = 'notification_templates_any'
class WorkflowJobTemplateNotificationTemplatesErrorList(SubListCreateAttachDetachAPIView): class WorkflowJobTemplateNotificationTemplatesStartedList(WorkflowJobTemplateNotificationTemplatesAnyList):
relationship = 'notification_templates_started'
class WorkflowJobTemplateNotificationTemplatesErrorList(WorkflowJobTemplateNotificationTemplatesAnyList):
model = models.NotificationTemplate
serializer_class = serializers.NotificationTemplateSerializer
parent_model = models.WorkflowJobTemplate
relationship = 'notification_templates_error' relationship = 'notification_templates_error'
class WorkflowJobTemplateNotificationTemplatesSuccessList(SubListCreateAttachDetachAPIView): class WorkflowJobTemplateNotificationTemplatesSuccessList(WorkflowJobTemplateNotificationTemplatesAnyList):
model = models.NotificationTemplate
serializer_class = serializers.NotificationTemplateSerializer
parent_model = models.WorkflowJobTemplate
relationship = 'notification_templates_success' relationship = 'notification_templates_success'
@@ -3411,22 +3410,20 @@ class SystemJobTemplateNotificationTemplatesAnyList(SubListCreateAttachDetachAPI
model = models.NotificationTemplate model = models.NotificationTemplate
serializer_class = serializers.NotificationTemplateSerializer serializer_class = serializers.NotificationTemplateSerializer
parent_model = models.SystemJobTemplate parent_model = models.SystemJobTemplate
relationship = 'notification_templates_any'
class SystemJobTemplateNotificationTemplatesErrorList(SubListCreateAttachDetachAPIView): class SystemJobTemplateNotificationTemplatesStartedList(SystemJobTemplateNotificationTemplatesAnyList):
relationship = 'notification_templates_started'
class SystemJobTemplateNotificationTemplatesErrorList(SystemJobTemplateNotificationTemplatesAnyList):
model = models.NotificationTemplate
serializer_class = serializers.NotificationTemplateSerializer
parent_model = models.SystemJobTemplate
relationship = 'notification_templates_error' relationship = 'notification_templates_error'
class SystemJobTemplateNotificationTemplatesSuccessList(SubListCreateAttachDetachAPIView): class SystemJobTemplateNotificationTemplatesSuccessList(SystemJobTemplateNotificationTemplatesAnyList):
model = models.NotificationTemplate
serializer_class = serializers.NotificationTemplateSerializer
parent_model = models.SystemJobTemplate
relationship = 'notification_templates_success' relationship = 'notification_templates_success'

View File

@@ -178,22 +178,20 @@ class OrganizationNotificationTemplatesAnyList(SubListCreateAttachDetachAPIView)
model = NotificationTemplate model = NotificationTemplate
serializer_class = NotificationTemplateSerializer serializer_class = NotificationTemplateSerializer
parent_model = Organization parent_model = Organization
relationship = 'notification_templates_any'
class OrganizationNotificationTemplatesErrorList(SubListCreateAttachDetachAPIView): class OrganizationNotificationTemplatesStartedList(OrganizationNotificationTemplatesAnyList):
relationship = 'notification_templates_started'
class OrganizationNotificationTemplatesErrorList(OrganizationNotificationTemplatesAnyList):
model = NotificationTemplate
serializer_class = NotificationTemplateSerializer
parent_model = Organization
relationship = 'notification_templates_error' relationship = 'notification_templates_error'
class OrganizationNotificationTemplatesSuccessList(SubListCreateAttachDetachAPIView): class OrganizationNotificationTemplatesSuccessList(OrganizationNotificationTemplatesAnyList):
model = NotificationTemplate
serializer_class = NotificationTemplateSerializer
parent_model = Organization
relationship = 'notification_templates_success' relationship = 'notification_templates_success'

View File

@@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.20 on 2019-05-30 20:35
from __future__ import unicode_literals
from django.db import migrations, models
def forwards_split_unified_job_template_any(apps, schema_editor):
UnifiedJobTemplate = apps.get_model('main', 'unifiedjobtemplate')
for ujt in UnifiedJobTemplate.objects.all():
for ujt_notification in ujt.notification_templates_any.all():
ujt.notification_templates_success.add(ujt_notification)
ujt.notification_templates_error.add(ujt_notification)
def forwards_split_organization_any(apps, schema_editor):
Organization = apps.get_model('main', 'organization')
for org in Organization.objects.all():
for org_notification in org.notification_templates_any.all():
org.notification_templates_success.add(org_notification)
org.notification_templates_error.add(org_notification)
class Migration(migrations.Migration):
dependencies = [
('main', '0080_v360_replace_job_origin'),
]
operations = [
migrations.AddField(
model_name='organization',
name='notification_templates_started',
field=models.ManyToManyField(blank=True, related_name='organization_notification_templates_for_started', to='main.NotificationTemplate'),
),
migrations.AddField(
model_name='unifiedjobtemplate',
name='notification_templates_started',
field=models.ManyToManyField(blank=True, related_name='unifiedjobtemplate_notification_templates_for_started', to='main.NotificationTemplate'),
),
# Separate out "any" notifications into "success" and "error" before the "any" state gets deleted.
migrations.RunPython(forwards_split_unified_job_template_any, forwards_split_organization_any),
migrations.RemoveField(
model_name='organization',
name='notification_templates_any',
),
migrations.RemoveField(
model_name='unifiedjobtemplate',
name='notification_templates_any',
),
]

View File

@@ -163,18 +163,18 @@ class AdHocCommand(UnifiedJob, JobNotificationMixin):
all_orgs.add(h.inventory.organization) all_orgs.add(h.inventory.organization)
active_templates = dict(error=set(), active_templates = dict(error=set(),
success=set(), success=set(),
any=set()) started=set())
base_notification_templates = NotificationTemplate.objects base_notification_templates = NotificationTemplate.objects
for org in all_orgs: for org in all_orgs:
for templ in base_notification_templates.filter(organization_notification_templates_for_errors=org): for templ in base_notification_templates.filter(organization_notification_templates_for_errors=org):
active_templates['error'].add(templ) active_templates['error'].add(templ)
for templ in base_notification_templates.filter(organization_notification_templates_for_success=org): for templ in base_notification_templates.filter(organization_notification_templates_for_success=org):
active_templates['success'].add(templ) active_templates['success'].add(templ)
for templ in base_notification_templates.filter(organization_notification_templates_for_any=org): for templ in base_notification_templates.filter(organization_notification_templates_for_started=org):
active_templates['any'].add(templ) active_templates['started'].add(templ)
active_templates['error'] = list(active_templates['error']) active_templates['error'] = list(active_templates['error'])
active_templates['any'] = list(active_templates['any'])
active_templates['success'] = list(active_templates['success']) active_templates['success'] = list(active_templates['success'])
active_templates['started'] = list(active_templates['started'])
return active_templates return active_templates
def get_passwords_needed_to_start(self): def get_passwords_needed_to_start(self):

View File

@@ -386,14 +386,13 @@ class NotificationFieldsModel(BaseModel):
related_name='%(class)s_notification_templates_for_success' related_name='%(class)s_notification_templates_for_success'
) )
notification_templates_any = models.ManyToManyField( notification_templates_started = models.ManyToManyField(
"NotificationTemplate", "NotificationTemplate",
blank=True, blank=True,
related_name='%(class)s_notification_templates_for_any' related_name='%(class)s_notification_templates_for_started'
) )
def prevent_search(relation): def prevent_search(relation):
""" """
Used to mark a model field or relation as "restricted from filtering" Used to mark a model field or relation as "restricted from filtering"

View File

@@ -1619,20 +1619,20 @@ class InventorySource(UnifiedJobTemplate, InventorySourceOptions, CustomVirtualE
base_notification_templates = NotificationTemplate.objects base_notification_templates = NotificationTemplate.objects
error_notification_templates = list(base_notification_templates error_notification_templates = list(base_notification_templates
.filter(unifiedjobtemplate_notification_templates_for_errors__in=[self])) .filter(unifiedjobtemplate_notification_templates_for_errors__in=[self]))
started_notification_templates = list(base_notification_templates
.filter(unifiedjobtemplate_notification_templates_for_started__in=[self]))
success_notification_templates = list(base_notification_templates success_notification_templates = list(base_notification_templates
.filter(unifiedjobtemplate_notification_templates_for_success__in=[self])) .filter(unifiedjobtemplate_notification_templates_for_success__in=[self]))
any_notification_templates = list(base_notification_templates
.filter(unifiedjobtemplate_notification_templates_for_any__in=[self]))
if self.inventory.organization is not None: if self.inventory.organization is not None:
error_notification_templates = set(error_notification_templates + list(base_notification_templates error_notification_templates = set(error_notification_templates + list(base_notification_templates
.filter(organization_notification_templates_for_errors=self.inventory.organization))) .filter(organization_notification_templates_for_errors=self.inventory.organization)))
started_notification_templates = set(started_notification_templates + list(base_notification_templates
.filter(organization_notification_templates_for_started=self.inventory.organization)))
success_notification_templates = set(success_notification_templates + list(base_notification_templates success_notification_templates = set(success_notification_templates + list(base_notification_templates
.filter(organization_notification_templates_for_success=self.inventory.organization))) .filter(organization_notification_templates_for_success=self.inventory.organization)))
any_notification_templates = set(any_notification_templates + list(base_notification_templates
.filter(organization_notification_templates_for_any=self.inventory.organization)))
return dict(error=list(error_notification_templates), return dict(error=list(error_notification_templates),
success=list(success_notification_templates), started=list(started_notification_templates),
any=list(any_notification_templates)) success=list(success_notification_templates))
def clean_source(self): # TODO: remove in 3.3 def clean_source(self): # TODO: remove in 3.3
source = self.source source = self.source

View File

@@ -435,19 +435,21 @@ class JobTemplate(UnifiedJobTemplate, JobOptions, SurveyJobTemplateMixin, Resour
base_notification_templates = NotificationTemplate.objects base_notification_templates = NotificationTemplate.objects
error_notification_templates = list(base_notification_templates.filter( error_notification_templates = list(base_notification_templates.filter(
unifiedjobtemplate_notification_templates_for_errors__in=[self, self.project])) unifiedjobtemplate_notification_templates_for_errors__in=[self, self.project]))
started_notification_templates = list(base_notification_templates.filter(
unifiedjobtemplate_notification_templates_for_started__in=[self, self.project]))
success_notification_templates = list(base_notification_templates.filter( success_notification_templates = list(base_notification_templates.filter(
unifiedjobtemplate_notification_templates_for_success__in=[self, self.project])) 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 # Get Organization NotificationTemplates
if self.project is not None and self.project.organization is not None: if self.project is not None and self.project.organization is not None:
error_notification_templates = set(error_notification_templates + list(base_notification_templates.filter( error_notification_templates = set(error_notification_templates + list(base_notification_templates.filter(
organization_notification_templates_for_errors=self.project.organization))) organization_notification_templates_for_errors=self.project.organization)))
started_notification_templates = set(started_notification_templates + list(base_notification_templates.filter(
organization_notification_templates_for_started=self.project.organization)))
success_notification_templates = set(success_notification_templates + list(base_notification_templates.filter( success_notification_templates = set(success_notification_templates + list(base_notification_templates.filter(
organization_notification_templates_for_success=self.project.organization))) organization_notification_templates_for_success=self.project.organization)))
any_notification_templates = set(any_notification_templates + list(base_notification_templates.filter( return dict(error=list(error_notification_templates),
organization_notification_templates_for_any=self.project.organization))) started=list(started_notification_templates),
return dict(error=list(error_notification_templates), success=list(success_notification_templates), any=list(any_notification_templates)) success=list(success_notification_templates))
''' '''
RelatedJobsMixin RelatedJobsMixin
@@ -1133,13 +1135,13 @@ class SystemJobTemplate(UnifiedJobTemplate, SystemJobOptions):
base_notification_templates = NotificationTemplate.objects.all() base_notification_templates = NotificationTemplate.objects.all()
error_notification_templates = list(base_notification_templates error_notification_templates = list(base_notification_templates
.filter(unifiedjobtemplate_notification_templates_for_errors__in=[self])) .filter(unifiedjobtemplate_notification_templates_for_errors__in=[self]))
started_notification_templates = list(base_notification_templates
.filter(unifiedjobtemplate_notification_templates_for_started__in=[self]))
success_notification_templates = list(base_notification_templates success_notification_templates = list(base_notification_templates
.filter(unifiedjobtemplate_notification_templates_for_success__in=[self])) .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), return dict(error=list(error_notification_templates),
success=list(success_notification_templates), started=list(started_notification_templates),
any=list(any_notification_templates)) success=list(success_notification_templates))
def _accept_or_ignore_job_kwargs(self, _exclude_errors=None, **kwargs): def _accept_or_ignore_job_kwargs(self, _exclude_errors=None, **kwargs):
extra_data = kwargs.pop('extra_vars', {}) extra_data = kwargs.pop('extra_vars', {})

View File

@@ -7,6 +7,7 @@ import logging
from django.db import models from django.db import models
from django.conf import settings from django.conf import settings
from django.core.mail.message import EmailMessage from django.core.mail.message import EmailMessage
from django.db import connection
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import smart_str, force_text from django.utils.encoding import smart_str, force_text
@@ -221,10 +222,13 @@ class JobNotificationMixin(object):
def build_notification_failed_message(self): def build_notification_failed_message(self):
return self._build_notification_message('failed') return self._build_notification_message('failed')
def build_notification_running_message(self):
return self._build_notification_message('running')
def send_notification_templates(self, status_str): def send_notification_templates(self, status_str):
from awx.main.tasks import send_notifications # avoid circular import from awx.main.tasks import send_notifications # avoid circular import
if status_str not in ['succeeded', 'failed']: if status_str not in ['succeeded', 'failed', 'running']:
raise ValueError(_("status_str must be either succeeded or failed")) raise ValueError(_("status_str must be either running, succeeded or failed"))
try: try:
notification_templates = self.get_notification_templates() notification_templates = self.get_notification_templates()
except Exception: except Exception:
@@ -233,14 +237,19 @@ class JobNotificationMixin(object):
if notification_templates: if notification_templates:
if status_str == 'succeeded': if status_str == 'succeeded':
notification_template_type = 'success' notification_template_type = 'success'
elif status_str == 'running':
notification_template_type = 'started'
else: else:
notification_template_type = 'error' notification_template_type = 'error'
all_notification_templates = set(notification_templates.get(notification_template_type, []) + notification_templates.get('any', [])) all_notification_templates = set(notification_templates.get(notification_template_type, []))
if len(all_notification_templates): if len(all_notification_templates):
try: try:
(notification_subject, notification_body) = getattr(self, 'build_notification_%s_message' % status_str)() (notification_subject, notification_body) = getattr(self, 'build_notification_%s_message' % status_str)()
except AttributeError: except AttributeError:
raise NotImplementedError("build_notification_%s_message() does not exist" % status_str) raise NotImplementedError("build_notification_%s_message() does not exist" % status_str)
send_notifications.delay([n.generate_notification(notification_subject, notification_body).id
for n in all_notification_templates], def send_it():
job_id=self.id) send_notifications.delay([n.generate_notification(notification_subject, notification_body).id
for n in all_notification_templates],
job_id=self.id)
connection.on_commit(send_it)

View File

@@ -411,24 +411,24 @@ class Project(UnifiedJobTemplate, ProjectOptions, ResourceMixin, CustomVirtualEn
base_notification_templates = NotificationTemplate.objects base_notification_templates = NotificationTemplate.objects
error_notification_templates = list(base_notification_templates error_notification_templates = list(base_notification_templates
.filter(unifiedjobtemplate_notification_templates_for_errors=self)) .filter(unifiedjobtemplate_notification_templates_for_errors=self))
started_notification_templates = list(base_notification_templates
.filter(unifiedjobtemplate_notification_templates_for_started=self))
success_notification_templates = list(base_notification_templates success_notification_templates = list(base_notification_templates
.filter(unifiedjobtemplate_notification_templates_for_success=self)) .filter(unifiedjobtemplate_notification_templates_for_success=self))
any_notification_templates = list(base_notification_templates
.filter(unifiedjobtemplate_notification_templates_for_any=self))
# Get Organization NotificationTemplates # Get Organization NotificationTemplates
if self.organization is not None: if self.organization is not None:
error_notification_templates = set(error_notification_templates + error_notification_templates = set(error_notification_templates +
list(base_notification_templates list(base_notification_templates
.filter(organization_notification_templates_for_errors=self.organization))) .filter(organization_notification_templates_for_errors=self.organization)))
started_notification_templates = set(started_notification_templates +
list(base_notification_templates
.filter(organization_notification_templates_for_started=self.organization)))
success_notification_templates = set(success_notification_templates + success_notification_templates = set(success_notification_templates +
list(base_notification_templates list(base_notification_templates
.filter(organization_notification_templates_for_success=self.organization))) .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), return dict(error=list(error_notification_templates),
success=list(success_notification_templates), started=list(started_notification_templates),
any=list(any_notification_templates)) success=list(success_notification_templates))
def get_absolute_url(self, request=None): def get_absolute_url(self, request=None):
return reverse('api:project_detail', kwargs={'pk': self.pk}, request=request) return reverse('api:project_detail', kwargs={'pk': self.pk}, request=request)
@@ -567,5 +567,3 @@ class ProjectUpdate(UnifiedJob, ProjectOptions, JobNotificationMixin, TaskManage
if not selected_groups: if not selected_groups:
return self.global_instance_groups return self.global_instance_groups
return selected_groups return selected_groups

View File

@@ -419,13 +419,13 @@ class WorkflowJobTemplate(UnifiedJobTemplate, WorkflowJobOptions, SurveyJobTempl
base_notification_templates = NotificationTemplate.objects.all() base_notification_templates = NotificationTemplate.objects.all()
error_notification_templates = list(base_notification_templates error_notification_templates = list(base_notification_templates
.filter(unifiedjobtemplate_notification_templates_for_errors__in=[self])) .filter(unifiedjobtemplate_notification_templates_for_errors__in=[self]))
started_notification_templates = list(base_notification_templates
.filter(unifiedjobtemplate_notification_templates_for_started__in=[self]))
success_notification_templates = list(base_notification_templates success_notification_templates = list(base_notification_templates
.filter(unifiedjobtemplate_notification_templates_for_success__in=[self])) .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), return dict(error=list(error_notification_templates),
success=list(success_notification_templates), started=list(started_notification_templates),
any=list(any_notification_templates)) success=list(success_notification_templates))
def create_unified_job(self, **kwargs): def create_unified_job(self, **kwargs):
workflow_job = super(WorkflowJobTemplate, self).create_unified_job(**kwargs) workflow_job = super(WorkflowJobTemplate, self).create_unified_job(**kwargs)

View File

@@ -193,6 +193,8 @@ class TaskManager():
status_changed = True status_changed = True
if status_changed: if status_changed:
workflow_job.websocket_emit_status(workflow_job.status) workflow_job.websocket_emit_status(workflow_job.status)
# Operations whose queries rely on modifications made during the atomic scheduling session
workflow_job.send_notification_templates('succeeded' if workflow_job.status == 'successful' else 'failed')
if workflow_job.spawned_by_workflow: if workflow_job.spawned_by_workflow:
schedule_task_manager() schedule_task_manager()
return result return result
@@ -233,6 +235,7 @@ class TaskManager():
else: else:
if type(task) is WorkflowJob: if type(task) is WorkflowJob:
task.status = 'running' task.status = 'running'
task.send_notification_templates('running')
logger.debug('Transitioning %s to running status.', task.log_format) logger.debug('Transitioning %s to running status.', task.log_format)
schedule_task_manager() schedule_task_manager()
elif not task.supports_isolation() and rampart_group.controller_id: elif not task.supports_isolation() and rampart_group.controller_id:
@@ -581,10 +584,5 @@ class TaskManager():
logger.debug("Not running scheduler, another task holds lock") logger.debug("Not running scheduler, another task holds lock")
return return
logger.debug("Starting Scheduler") logger.debug("Starting Scheduler")
with task_manager_bulk_reschedule(): with task_manager_bulk_reschedule():
finished_wfjs = self._schedule() self._schedule()
# Operations whose queries rely on modifications made during the atomic scheduling session
for wfj in WorkflowJob.objects.filter(id__in=finished_wfjs):
wfj.send_notification_templates('succeeded' if wfj.status == 'successful' else 'failed')

View File

@@ -1131,6 +1131,7 @@ class BaseTask(object):
try: try:
isolated = self.instance.is_isolated() isolated = self.instance.is_isolated()
self.instance.send_notification_templates("running")
self.pre_run_hook(self.instance) self.pre_run_hook(self.instance)
if self.instance.cancel_flag: if self.instance.cancel_flag:
self.instance = self.update_model(self.instance.pk, status='canceled') self.instance = self.update_model(self.instance.pk, status='canceled')

View File

@@ -91,7 +91,7 @@ class TestSwaggerGeneration():
# The number of API endpoints changes over time, but let's just check # The number of API endpoints changes over time, but let's just check
# for a reasonable number here; if this test starts failing, raise/lower the bounds # for a reasonable number here; if this test starts failing, raise/lower the bounds
paths = JSON['paths'] paths = JSON['paths']
assert 250 < len(paths) < 300 assert 250 < len(paths) < 350
assert list(paths['/api/'].keys()) == ['get'] assert list(paths['/api/'].keys()) == ['get']
assert list(paths['/api/v2/'].keys()) == ['get'] assert list(paths['/api/v2/'].keys()) == ['get']
assert list(sorted( assert list(sorted(

View File

@@ -42,10 +42,6 @@ def test_inventory_source_notification_on_cloud_only(get, post, inventory_source
not_is = inventory_source_factory("not_ec2") not_is = inventory_source_factory("not_ec2")
url = reverse('api:inventory_source_notification_templates_any_list', kwargs={'pk': cloud_is.id})
response = post(url, dict(id=notification_template.id), u)
assert response.status_code == 204
url = reverse('api:inventory_source_notification_templates_success_list', kwargs={'pk': not_is.id}) url = reverse('api:inventory_source_notification_templates_success_list', kwargs={'pk': not_is.id})
response = post(url, dict(id=notification_template.id), u) response = post(url, dict(id=notification_template.id), u)
assert response.status_code == 400 assert response.status_code == 400

View File

@@ -0,0 +1,129 @@
import pytest
from awx.api.versioning import reverse
@pytest.mark.django_db
def test_get_org_running_notification(get, admin, organization):
url = reverse('api:organization_notification_templates_started_list', kwargs={'pk': organization.pk})
response = get(url, admin)
assert response.status_code == 200
assert len(response.data['results']) == 0
@pytest.mark.django_db
def test_post_org_running_notification(get, post, admin, notification_template, organization):
url = reverse('api:organization_notification_templates_started_list', kwargs={'pk': organization.pk})
response = post(url,
dict(id=notification_template.id,
associate=True),
admin)
assert response.status_code == 204
response = get(url, admin)
assert response.status_code == 200
assert len(response.data['results']) == 1
@pytest.mark.django_db
def test_get_project_running_notification(get, admin, project):
url = reverse('api:project_notification_templates_started_list', kwargs={'pk': project.pk})
response = get(url, admin)
assert response.status_code == 200
assert len(response.data['results']) == 0
@pytest.mark.django_db
def test_post_project_running_notification(get, post, admin, notification_template, project):
url = reverse('api:project_notification_templates_started_list', kwargs={'pk': project.pk})
response = post(url,
dict(id=notification_template.id,
associate=True),
admin)
assert response.status_code == 204
response = get(url, admin)
assert response.status_code == 200
assert len(response.data['results']) == 1
@pytest.mark.django_db
def test_get_inv_src_running_notification(get, admin, inventory_source):
url = reverse('api:inventory_source_notification_templates_started_list', kwargs={'pk': inventory_source.pk})
response = get(url, admin)
assert response.status_code == 200
assert len(response.data['results']) == 0
@pytest.mark.django_db
def test_post_inv_src_running_notification(get, post, admin, notification_template, inventory_source):
url = reverse('api:inventory_source_notification_templates_started_list', kwargs={'pk': inventory_source.pk})
response = post(url,
dict(id=notification_template.id,
associate=True),
admin)
assert response.status_code == 204
response = get(url, admin)
assert response.status_code == 200
assert len(response.data['results']) == 1
@pytest.mark.django_db
def test_get_jt_running_notification(get, admin, job_template):
url = reverse('api:job_template_notification_templates_started_list', kwargs={'pk': job_template.pk})
response = get(url, admin)
assert response.status_code == 200
assert len(response.data['results']) == 0
@pytest.mark.django_db
def test_post_jt_running_notification(get, post, admin, notification_template, job_template):
url = reverse('api:job_template_notification_templates_started_list', kwargs={'pk': job_template.pk})
response = post(url,
dict(id=notification_template.id,
associate=True),
admin)
assert response.status_code == 204
response = get(url, admin)
assert response.status_code == 200
assert len(response.data['results']) == 1
@pytest.mark.django_db
def test_get_sys_jt_running_notification(get, admin, system_job_template):
url = reverse('api:system_job_template_notification_templates_started_list', kwargs={'pk': system_job_template.pk})
response = get(url, admin)
assert response.status_code == 200
assert len(response.data['results']) == 0
@pytest.mark.django_db
def test_post_sys_jt_running_notification(get, post, admin, notification_template, system_job_template):
url = reverse('api:system_job_template_notification_templates_started_list', kwargs={'pk': system_job_template.pk})
response = post(url,
dict(id=notification_template.id,
associate=True),
admin)
assert response.status_code == 204
response = get(url, admin)
assert response.status_code == 200
assert len(response.data['results']) == 1
@pytest.mark.django_db
def test_get_wfjt_running_notification(get, admin, workflow_job_template):
url = reverse('api:workflow_job_template_notification_templates_started_list', kwargs={'pk': workflow_job_template.pk})
response = get(url, admin)
assert response.status_code == 200
assert len(response.data['results']) == 0
@pytest.mark.django_db
def test_post_wfjt_running_notification(get, post, admin, notification_template, workflow_job_template):
url = reverse('api:workflow_job_template_notification_templates_started_list', kwargs={'pk': workflow_job_template.pk})
response = post(url,
dict(id=notification_template.id,
associate=True),
admin)
assert response.status_code == 204
response = get(url, admin)
assert response.status_code == 200
assert len(response.data['results']) == 1

View File

@@ -92,26 +92,6 @@ def test_inherited_notification_templates(get, post, user, organization, project
isrc.save() isrc.save()
jt = JobTemplate.objects.create(name='test', inventory=i, project=project, playbook='debug.yml') jt = JobTemplate.objects.create(name='test', inventory=i, project=project, playbook='debug.yml')
jt.save() jt.save()
url = reverse('api:organization_notification_templates_any_list', kwargs={'pk': organization.id})
response = post(url, dict(id=notification_templates[0]), u)
assert response.status_code == 204
url = reverse('api:project_notification_templates_any_list', kwargs={'pk': project.id})
response = post(url, dict(id=notification_templates[1]), u)
assert response.status_code == 204
url = reverse('api:job_template_notification_templates_any_list', kwargs={'pk': jt.id})
response = post(url, dict(id=notification_templates[2]), u)
assert response.status_code == 204
assert len(jt.notification_templates['any']) == 3
assert len(project.notification_templates['any']) == 2
assert len(isrc.notification_templates['any']) == 1
@pytest.mark.django_db
def test_notification_template_merging(get, post, user, organization, project, notification_template):
user('admin-poster', True)
organization.notification_templates_any.add(notification_template)
project.notification_templates_any.add(notification_template)
assert len(project.notification_templates['any']) == 1
@pytest.mark.django_db @pytest.mark.django_db

View File

@@ -71,7 +71,7 @@ class TestInventorySourceSerializerGetRelated(object):
'activity_stream', 'activity_stream',
'notification_templates_error', 'notification_templates_error',
'notification_templates_success', 'notification_templates_success',
'notification_templates_any', 'notification_templates_started',
'inventory_updates', 'inventory_updates',
'update', 'update',
'hosts', 'hosts',

View File

@@ -50,7 +50,7 @@ class TestJobTemplateSerializerGetRelated():
'schedules', 'schedules',
'activity_stream', 'activity_stream',
'launch', 'launch',
'notification_templates_any', 'notification_templates_started',
'notification_templates_success', 'notification_templates_success',
'notification_templates_error', 'notification_templates_error',
'survey_spec', 'survey_spec',

View File

@@ -378,6 +378,7 @@ class TestGenericRun():
job.status = 'running' job.status = 'running'
job.cancel_flag = True job.cancel_flag = True
job.websocket_emit_status = mock.Mock() job.websocket_emit_status = mock.Mock()
job.send_notification_templates = mock.Mock()
task = tasks.RunJob() task = tasks.RunJob()
task.update_model = mock.Mock(wraps=update_model_wrapper) task.update_model = mock.Mock(wraps=update_model_wrapper)
@@ -536,6 +537,7 @@ class TestAdhocRun(TestJobExecution):
def test_options_jinja_usage(self, adhoc_job, adhoc_update_model_wrapper): def test_options_jinja_usage(self, adhoc_job, adhoc_update_model_wrapper):
adhoc_job.module_args = '{{ ansible_ssh_pass }}' adhoc_job.module_args = '{{ ansible_ssh_pass }}'
adhoc_job.websocket_emit_status = mock.Mock() adhoc_job.websocket_emit_status = mock.Mock()
adhoc_job.send_notification_templates = mock.Mock()
task = tasks.RunAdHocCommand() task = tasks.RunAdHocCommand()
task.update_model = mock.Mock(wraps=adhoc_update_model_wrapper) task.update_model = mock.Mock(wraps=adhoc_update_model_wrapper)

View File

@@ -22,9 +22,9 @@ Notification templates assigned at certain levels will inherit notifications def
## Workflow ## Workflow
When a job succeeds or fails, the error or success handler will pull a list of relevant notifications using the procedure defined above. It will then create a Notification object for each one containing relevant details about the job and then **sends** it to the destination (email addresses, slack channel(s), SMS numbers, etc.). These Notification objects are available as related resources on job types (Jobs, Inventory Updates, Project Updates), and also at `/api/v2/notifications`. You may also see what notifications have been sent from a notifications by examining its related resources. When a job starts, succeeds or fails, the running, success or error handler, respectively, will pull a list of relevant notifications using the procedure defined above. It then creates a Notification Object for each one containing relevant details about the job and then **sends** it to the destination (email addresses, Slack channel(s), SMS numbers, etc.). These Notification objects are available as related resources on job types (Jobs, Inventory Updates, Project Updates), and also at `/api/v2/notifications`. You may also see what notifications have been sent by examining its related resources.
Notifications can succeed or fail but that will not cause its associated job to succeed or fail. The status of the notification can be viewed at its detail endpoint: `/api/v2/notifications/<n>` Notifications can succeed or fail but that will _not_ cause its associated job to succeed or fail. The status of the notification can be viewed at its detail endpoint: `/api/v2/notifications/<n>`
## Testing Notifications Before Using Them ## Testing Notifications Before Using Them