1
0
mirror of https://github.com/ansible/awx.git synced 2024-10-31 23:51:09 +03:00

Implement /launch endpoint on job template

Partial implementation of:

https://trello.com/c/7uXHs7ze/14-require-admin-to-be-able-to-run-a-job-without-a-job-template
This commit is contained in:
Matthew Jones 2014-09-04 13:25:21 -04:00
parent e48309b6aa
commit 58b71ca9f9
6 changed files with 85 additions and 1 deletions

View File

@ -130,6 +130,7 @@ permission_urls = patterns('awx.api.views',
job_template_urls = patterns('awx.api.views',
url(r'^$', 'job_template_list'),
url(r'^(?P<pk>[0-9]+)/$', 'job_template_detail'),
url(r'^(?P<pk>[0-9]+)launch/$', 'job_template_launch'),
url(r'^(?P<pk>[0-9]+)/jobs/$', 'job_template_jobs_list'),
url(r'^(?P<pk>[0-9]+)/callback/$', 'job_template_callback'),
url(r'^(?P<pk>[0-9]+)/schedules/$', 'job_template_schedules_list'),

View File

@ -1337,6 +1337,31 @@ class JobTemplateDetail(RetrieveUpdateDestroyAPIView):
model = JobTemplate
serializer_class = JobTemplateSerializer
class JobTemplateLaunch(GenericAPIView):
model = JobTemplate
def get(self, request, *args, **kwargs):
obj = self.get_object()
data = {}
data['can_start_without_user_input'] = obj.can_start_without_user_input()
data['passwords_needed_to_start'] = obj.passwords_needed_to_start
data['ask_variables_on_launch'] = obj.ask_variables_on_launch
return Response(data)
def post(self, request, *args, **obj):
obj = self.get_object()
if not request.user.can_access(self.model, 'start', obj):
raise PermissionDenied()
new_job = obj.create_unified_job()
result = new_job.signal_start(**request.DATA)
if not result:
data = dict(passwords_needed_to_start=obj.passwords_needed_to_start)
return Response(data, status=status.HTTP_400_BAD_REQUEST)
else:
data = dict(job=new_job.id)
return Response(data, status=status.HTTP_202_ACCEPTED)
class JobTemplateSchedulesList(SubListCreateAPIView):
view_name = "Job Template Schedules"

View File

@ -920,6 +920,26 @@ class JobTemplateAccess(BaseAccess):
return True
def can_start(self, obj):
reader = TaskSerializer()
validation_info = reader.from_file()
if 'test' in sys.argv or 'jenkins' in sys.argv:
validation_info['free_instances'] = 99999999
validation_info['time_remaining'] = 99999999
validation_info['grace_period_remaining'] = 99999999
if validation_info.get('time_remaining', None) is None:
raise PermissionDenied("license is missing")
if validation_info.get("grace_period_remaining") <= 0:
raise PermissionDenied("license has expired")
if validation_info.get('free_instances', 0) < 0:
raise PermissionDenied("Host Count exceeds available instances")
dep_access = self.user.can_access(Inventory, 'read', obj.inventory) and \
self.user.can_access(Project, 'read', obj.project)
return self.can_read(obj) and dep_access
def can_change(self, obj, data):
return self.can_read(obj) and self.can_add(data)

View File

@ -189,6 +189,18 @@ class JobTemplate(UnifiedJobTemplate, JobOptions):
needed.append(pw)
return bool(self.credential and not len(needed))
@property
def passwords_needed_to_start(self):
'''Return list of password field names needed to start the job.'''
needed = []
if self.credential:
for pw in self.credential.passwords_needed:
if pw == 'password':
needed.append('ssh_password')
else:
needed.append(pw)
return needed
def _can_update(self):
return self.can_start_without_user_input()

View File

@ -302,7 +302,7 @@ class BaseTestMixin(object):
self.assertFalse(response.content)
#if return_response_object:
# return response
if response.status_code not in [ 202, 204, 405 ] and method_name != 'head' and response.content:
if response.status_code not in [ 204, 405 ] and method_name != 'head' and response.content:
# no JSON responses in these at least for now, 409 should probably return some (FIXME)
if response['Content-Type'].startswith('application/json'):
obj = json.loads(response.content)

View File

@ -681,6 +681,32 @@ class JobTemplateTest(BaseJobTestMixin, django.test.TestCase):
# FIXME: Check other credentials and optional fields.
def test_launch_job_template(self):
url = reverse('api:job_template_list')
data = dict(
name = 'launched job template',
job_type = PERM_INVENTORY_DEPLOY,
inventory = self.inv_eng.pk,
project = self.proj_dev.pk,
playbook = self.proj_dev.playbooks[0],
)
with self.current_user(self.user_sue):
response = self.post(url, data, expect=201)
detail_url = reverse('api:job_template_detail',
args=(response['id'],))
self.assertEquals(response['url'], detail_url)
launch_url = reverse('api:job_template_launch',
args=(response['id'],))
# Invalid auth can't trigger the launch endpoint
self.check_invalid_auth(launch_url, {}, methods=('post',))
with self.current_user(self.user_sue):
response = self.post(launch_url, {}, expect=202)
j = Job.objects.get(pk=response['job'])
self.assertTrue(j.status == 'new')
class JobTest(BaseJobTestMixin, django.test.TestCase):
def test_get_job_list(self):