1
0
mirror of https://github.com/ansible/awx.git synced 2024-11-01 16:51:11 +03:00

add workflow relaunch

This commit is contained in:
AlanCoding 2016-11-14 12:15:14 -05:00
parent 14ce50c845
commit 8cda12c020
7 changed files with 86 additions and 4 deletions

View File

@ -2252,6 +2252,7 @@ class WorkflowJobSerializer(LabelsListMixin, UnifiedJobSerializer):
res['workflow_nodes'] = reverse('api:workflow_job_workflow_nodes_list', args=(obj.pk,))
res['labels'] = reverse('api:workflow_job_label_list', args=(obj.pk,))
res['activity_stream'] = reverse('api:workflow_job_activity_stream_list', args=(obj.pk,))
res['relaunch'] = reverse('api:workflow_job_relaunch', args=(obj.pk,))
if obj.can_cancel or True:
res['cancel'] = reverse('api:workflow_job_cancel', args=(obj.pk,))
return res

View File

@ -272,7 +272,6 @@ workflow_job_template_urls = patterns('awx.api.views',
url(r'^(?P<pk>[0-9]+)/notification_templates_success/$', 'workflow_job_template_notification_templates_success_list'),
url(r'^(?P<pk>[0-9]+)/access_list/$', 'workflow_job_template_access_list'),
url(r'^(?P<pk>[0-9]+)/labels/$', 'workflow_job_template_label_list'),
# url(r'^(?P<pk>[0-9]+)/cancel/$', 'workflow_job_template_cancel'),
)
workflow_job_urls = patterns('awx.api.views',
@ -281,6 +280,7 @@ workflow_job_urls = patterns('awx.api.views',
url(r'^(?P<pk>[0-9]+)/workflow_nodes/$', 'workflow_job_workflow_nodes_list'),
url(r'^(?P<pk>[0-9]+)/labels/$', 'workflow_job_label_list'),
url(r'^(?P<pk>[0-9]+)/cancel/$', 'workflow_job_cancel'),
url(r'^(?P<pk>[0-9]+)/relaunch/$', 'workflow_job_relaunch'),
url(r'^(?P<pk>[0-9]+)/notifications/$', 'workflow_job_notifications_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'workflow_job_activity_stream_list'),
)

View File

@ -2987,6 +2987,25 @@ class WorkflowJobTemplateLaunch(RetrieveAPIView):
return Response(data, status=status.HTTP_201_CREATED)
class WorkflowJobRelaunch(GenericAPIView):
model = WorkflowJob
serializer_class = EmptySerializer
is_job_start = True
def get(self, request, *args, **kwargs):
return Response({})
def post(self, request, *args, **kwargs):
obj = self.get_object()
new_workflow_job = obj.create_relaunch_workflow_job()
result = new_workflow_job.signal_start()
data = WorkflowJobSerializer(new_workflow_job, context=self.get_serializer_context()).data
headers = {'Location': new_workflow_job.get_absolute_url()}
return Response(data, status=status.HTTP_201_CREATED, headers=headers)
# TODO:
class WorkflowJobTemplateWorkflowNodesList(SubListCreateAPIView):

View File

@ -1630,9 +1630,16 @@ class WorkflowJobAccess(BaseAccess):
return self.user.is_superuser
return self.user in obj.workflow_job_template.admin_role
# TODO: add support for relaunching workflow jobs
def can_start(self, obj, validate_license=True):
return False
if validate_license:
self.check_license()
if obj.survey_enabled:
self.check_license(feature='surveys')
if self.user.is_superuser:
return True
return (obj.workflow_job_template and self.user in obj.workflow_job_template.execute_role)
def can_cancel(self, obj):
if not obj.can_cancel:

View File

@ -455,6 +455,10 @@ class Job(UnifiedJob, JobOptions, SurveyJobMixin, JobNotificationMixin):
def _global_timeout_setting(self):
return 'DEFAULT_JOB_TIMEOUT'
@classmethod
def _get_unified_job_template_class(cls):
return JobTemplate
def get_absolute_url(self):
return reverse('api:job_detail', args=(self.pk,))

View File

@ -357,7 +357,6 @@ class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique, Notificatio
dest_field.add(*list(src_field_value.all().values_list('id', flat=True)))
return unified_job
def copy_unified_jt(self):
'''
Create a copy of this unified job template.
@ -585,6 +584,13 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique
def _get_parent_field_name(cls):
return 'unified_job_template' # Override in subclasses.
@classmethod
def _get_unified_job_template_class(cls):
'''
Return subclass of UnifiedJobTemplate that applies to this unified job.
'''
raise NotImplementedError # Implement in subclass.
def _global_timeout_setting(self):
"Override in child classes, None value indicates this is not configurable"
return None
@ -699,6 +705,36 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique
pass
super(UnifiedJob, self).delete()
def copy_unified_job(self):
'''
Create a copy of this unified job.
'''
unified_job_class = self.__class__
unified_jt_class = self._get_unified_job_template_class()
create_kwargs = {}
m2m_fields = {}
for field_name in unified_jt_class._get_unified_job_field_names():
# Foreign keys can be specified as field_name or field_name_id.
id_field_name = '%s_id' % field_name
if hasattr(self, id_field_name):
value = getattr(self, id_field_name)
if hasattr(value, 'id'):
value = value.id
create_kwargs[id_field_name] = value
elif hasattr(self, field_name):
field_obj = self._meta.get_field_by_name(field_name)[0]
# Many to Many can be specified as field_name
if isinstance(field_obj, models.ManyToManyField):
m2m_fields[field_name] = getattr(self, field_name)
else:
create_kwargs[field_name] = getattr(self, field_name)
unified_job = unified_job_class(**create_kwargs)
unified_job.save()
for field_name, src_field_value in m2m_fields.iteritems():
dest_field = getattr(unified_job, field_name)
dest_field.add(*list(src_field_value.all().values_list('id', flat=True)))
return unified_job
def result_stdout_raw_handle(self, attempt=0):
"""Return a file-like object containing the standard out of the
job's result.

View File

@ -322,6 +322,12 @@ class WorkflowJobOptions(BaseModel):
node_links = self._create_workflow_nodes(old_node_list, user=user)
self._inherit_node_relationships(old_node_list, node_links)
def create_relaunch_workflow_job(self):
self.launch_type = 'relaunch'
new_workflow_job = self.copy_unified_job()
new_workflow_job.copy_nodes_from_original(original=self)
return new_workflow_job
class WorkflowJobTemplate(UnifiedJobTemplate, WorkflowJobOptions, SurveyJobTemplateMixin, ResourceMixin):
class Meta:
@ -424,6 +430,11 @@ class WorkflowJobTemplate(UnifiedJobTemplate, WorkflowJobOptions, SurveyJobTempl
return new_wfjt
# Stub in place because of old migraitons, can remove if migraitons are squashed
class WorkflowJobInheritNodesMixin(object):
pass
class WorkflowJob(UnifiedJob, WorkflowJobOptions, SurveyJobMixin, JobNotificationMixin):
class Meta:
app_label = 'main'
@ -446,6 +457,10 @@ class WorkflowJob(UnifiedJob, WorkflowJobOptions, SurveyJobMixin, JobNotificatio
def _get_parent_field_name(cls):
return 'workflow_job_template'
@classmethod
def _get_unified_job_template_class(cls):
return WorkflowJobTemplate
def _has_failed(self):
return False