mirror of
https://github.com/ansible/awx.git
synced 2026-03-20 02:17:37 -02:30
Implement model/view/launch paradigm for shard/split job templates
This commit is contained in:
committed by
AlanCoding
parent
89c2038ea3
commit
0b1776098b
@@ -3011,7 +3011,7 @@ class JobTemplateSerializer(JobTemplateMixin, UnifiedJobTemplateSerializer, JobO
|
|||||||
fields = ('*', 'host_config_key', 'ask_diff_mode_on_launch', 'ask_variables_on_launch', 'ask_limit_on_launch', 'ask_tags_on_launch',
|
fields = ('*', 'host_config_key', 'ask_diff_mode_on_launch', 'ask_variables_on_launch', 'ask_limit_on_launch', 'ask_tags_on_launch',
|
||||||
'ask_skip_tags_on_launch', 'ask_job_type_on_launch', 'ask_verbosity_on_launch', 'ask_inventory_on_launch',
|
'ask_skip_tags_on_launch', 'ask_job_type_on_launch', 'ask_verbosity_on_launch', 'ask_inventory_on_launch',
|
||||||
'ask_credential_on_launch', 'survey_enabled', 'become_enabled', 'diff_mode',
|
'ask_credential_on_launch', 'survey_enabled', 'become_enabled', 'diff_mode',
|
||||||
'allow_simultaneous', 'custom_virtualenv')
|
'allow_simultaneous', 'custom_virtualenv', 'job_shard_count')
|
||||||
|
|
||||||
def get_related(self, obj):
|
def get_related(self, obj):
|
||||||
res = super(JobTemplateSerializer, self).get_related(obj)
|
res = super(JobTemplateSerializer, self).get_related(obj)
|
||||||
|
|||||||
@@ -2903,7 +2903,7 @@ class JobTemplateLaunch(RetrieveAPIView):
|
|||||||
raise PermissionDenied()
|
raise PermissionDenied()
|
||||||
|
|
||||||
passwords = serializer.validated_data.pop('credential_passwords', {})
|
passwords = serializer.validated_data.pop('credential_passwords', {})
|
||||||
new_job = obj.create_unified_job(**serializer.validated_data)
|
new_job = obj.create_job(**serializer.validated_data)
|
||||||
result = new_job.signal_start(**passwords)
|
result = new_job.signal_start(**passwords)
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
@@ -2914,7 +2914,10 @@ class JobTemplateLaunch(RetrieveAPIView):
|
|||||||
data = OrderedDict()
|
data = OrderedDict()
|
||||||
data['job'] = new_job.id
|
data['job'] = new_job.id
|
||||||
data['ignored_fields'] = self.sanitize_for_response(ignored_fields)
|
data['ignored_fields'] = self.sanitize_for_response(ignored_fields)
|
||||||
data.update(JobSerializer(new_job, context=self.get_serializer_context()).to_representation(new_job))
|
if isinstance(new_job, WorkflowJob):
|
||||||
|
data.update(WorkflowJobSerializer(new_job, context=self.get_serializer_context()).to_representation(new_job))
|
||||||
|
else:
|
||||||
|
data.update(JobSerializer(new_job, context=self.get_serializer_context()).to_representation(new_job))
|
||||||
headers = {'Location': new_job.get_absolute_url(request)}
|
headers = {'Location': new_job.get_absolute_url(request)}
|
||||||
return Response(data, status=status.HTTP_201_CREATED, headers=headers)
|
return Response(data, status=status.HTTP_201_CREATED, headers=headers)
|
||||||
|
|
||||||
|
|||||||
20
awx/main/migrations/0048_v340_split_jobs.py
Normal file
20
awx/main/migrations/0048_v340_split_jobs.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.11 on 2018-08-14 13:43
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('main', '0047_v330_activitystream_instance'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='jobtemplate',
|
||||||
|
name='job_shard_count',
|
||||||
|
field=models.IntegerField(blank=True,
|
||||||
|
default=0,
|
||||||
|
help_text='The number of jobs to split into at runtime. Will cause the Job Template to launch a workflow.'),
|
||||||
|
),
|
||||||
|
]
|
||||||
26
awx/main/migrations/0049_v340_add_job_template.py
Normal file
26
awx/main/migrations/0049_v340_add_job_template.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11.11 on 2018-08-14 16:04
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('main', '0048_v340_split_jobs'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='workflowjob',
|
||||||
|
name='job_template',
|
||||||
|
field=models.ForeignKey(blank=True,
|
||||||
|
default=None,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
related_name='sharded_jobs', to='main.JobTemplate'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -277,6 +277,12 @@ class JobTemplate(UnifiedJobTemplate, JobOptions, SurveyJobTemplateMixin, Resour
|
|||||||
default=False,
|
default=False,
|
||||||
allows_field='credentials'
|
allows_field='credentials'
|
||||||
)
|
)
|
||||||
|
job_shard_count = models.IntegerField(
|
||||||
|
blank=True,
|
||||||
|
default=0,
|
||||||
|
help_text=_("The number of jobs to split into at runtime. Will cause the Job Template to launch a workflow."),
|
||||||
|
)
|
||||||
|
|
||||||
admin_role = ImplicitRoleField(
|
admin_role = ImplicitRoleField(
|
||||||
parent_role=['project.organization.job_template_admin_role', 'inventory.organization.job_template_admin_role']
|
parent_role=['project.organization.job_template_admin_role', 'inventory.organization.job_template_admin_role']
|
||||||
)
|
)
|
||||||
@@ -318,6 +324,11 @@ class JobTemplate(UnifiedJobTemplate, JobOptions, SurveyJobTemplateMixin, Resour
|
|||||||
'''
|
'''
|
||||||
Create a new job based on this template.
|
Create a new job based on this template.
|
||||||
'''
|
'''
|
||||||
|
if self.job_shard_count > 1:
|
||||||
|
# A sharded Job Template will generate a WorkflowJob rather than a Job
|
||||||
|
from awx.main.models.workflow import WorkflowJobTemplate
|
||||||
|
kwargs['_unified_job_class'] = WorkflowJobTemplate._get_unified_job_class()
|
||||||
|
kwargs['_unified_job_field_names'] = WorkflowJobTemplate._get_unified_job_field_names()
|
||||||
return self.create_unified_job(**kwargs)
|
return self.create_unified_job(**kwargs)
|
||||||
|
|
||||||
def get_absolute_url(self, request=None):
|
def get_absolute_url(self, request=None):
|
||||||
|
|||||||
@@ -328,6 +328,8 @@ class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique, Notificatio
|
|||||||
'''
|
'''
|
||||||
Create a new unified job based on this unified job template.
|
Create a new unified job based on this unified job template.
|
||||||
'''
|
'''
|
||||||
|
from awx.main.models import JobTemplate, WorkflowJob
|
||||||
|
|
||||||
new_job_passwords = kwargs.pop('survey_passwords', {})
|
new_job_passwords = kwargs.pop('survey_passwords', {})
|
||||||
eager_fields = kwargs.pop('_eager_fields', None)
|
eager_fields = kwargs.pop('_eager_fields', None)
|
||||||
|
|
||||||
@@ -336,8 +338,10 @@ class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique, Notificatio
|
|||||||
password_list = self.survey_password_variables()
|
password_list = self.survey_password_variables()
|
||||||
encrypt_dict(kwargs.get('extra_vars', {}), password_list)
|
encrypt_dict(kwargs.get('extra_vars', {}), password_list)
|
||||||
|
|
||||||
unified_job_class = self._get_unified_job_class()
|
unified_job_class = kwargs.pop("_unified_job_class", self._get_unified_job_class())
|
||||||
fields = self._get_unified_job_field_names()
|
fields = kwargs.pop("_unified_job_field_names", self._get_unified_job_field_names())
|
||||||
|
print("UJC: {}".format(unified_job_class))
|
||||||
|
print("fields: {}".format(fields))
|
||||||
unallowed_fields = set(kwargs.keys()) - set(fields)
|
unallowed_fields = set(kwargs.keys()) - set(fields)
|
||||||
if unallowed_fields:
|
if unallowed_fields:
|
||||||
logger.warn('Fields {} are not allowed as overrides.'.format(unallowed_fields))
|
logger.warn('Fields {} are not allowed as overrides.'.format(unallowed_fields))
|
||||||
@@ -350,7 +354,11 @@ class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique, Notificatio
|
|||||||
setattr(unified_job, fd, val)
|
setattr(unified_job, fd, val)
|
||||||
|
|
||||||
# Set the unified job template back-link on the job
|
# Set the unified job template back-link on the job
|
||||||
parent_field_name = unified_job_class._get_parent_field_name()
|
# TODO: fix this hack properly before merge matburt
|
||||||
|
if isinstance(self, JobTemplate) and isinstance(unified_job, WorkflowJob):
|
||||||
|
parent_field_name = "job_template"
|
||||||
|
else:
|
||||||
|
parent_field_name = unified_job_class._get_parent_field_name()
|
||||||
setattr(unified_job, parent_field_name, self)
|
setattr(unified_job, parent_field_name, self)
|
||||||
|
|
||||||
# For JobTemplate-based jobs with surveys, add passwords to list for perma-redaction
|
# For JobTemplate-based jobs with surveys, add passwords to list for perma-redaction
|
||||||
|
|||||||
@@ -433,6 +433,14 @@ class WorkflowJob(UnifiedJob, WorkflowJobOptions, SurveyJobMixin, JobNotificatio
|
|||||||
default=None,
|
default=None,
|
||||||
on_delete=models.SET_NULL,
|
on_delete=models.SET_NULL,
|
||||||
)
|
)
|
||||||
|
job_template = models.ForeignKey(
|
||||||
|
'JobTemplate',
|
||||||
|
related_name='sharded_jobs',
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
default=None,
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def workflow_nodes(self):
|
def workflow_nodes(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user