From eccfe128ddadae000e4ba4c9b02223954964dd03 Mon Sep 17 00:00:00 2001 From: Chris Houseknecht Date: Wed, 11 Jun 2014 18:43:56 -0400 Subject: [PATCH] Job submission error handling If playbook submission fails, check for a 400 status and parse the key/value pairs returned by the API. This occurs on an attempt to submit a job template that is no longer valid. Fixed JS compile errors from prior commit. --- awx/ui/static/js/controllers/JobDetail.js | 4 +- awx/ui/static/js/helpers/JobSubmission.js | 73 ++++++++++++++--------- 2 files changed, 46 insertions(+), 31 deletions(-) diff --git a/awx/ui/static/js/controllers/JobDetail.js b/awx/ui/static/js/controllers/JobDetail.js index ce4231fa4c..7b972e68f7 100644 --- a/awx/ui/static/js/controllers/JobDetail.js +++ b/awx/ui/static/js/controllers/JobDetail.js @@ -8,7 +8,7 @@ 'use strict'; function JobDetailController ($scope, $compile, $routeParams, $log, ClearScope, Breadcrumbs, LoadBreadCrumbs, GetBasePath, Wait, Rest, ProcessErrors, DigestEvents, - SelectPlay, SelectTask, Socket, GetElapsed, SelectHost, FilterAllByHostName, DrawGraph, LoadHostSummary) { + SelectPlay, SelectTask, Socket, GetElapsed, SelectHost, FilterAllByHostName, DrawGraph, LoadHostSummary, ReloadHostSummaryList) { ClearScope(); @@ -700,5 +700,5 @@ function JobDetailController ($scope, $compile, $routeParams, $log, ClearScope, JobDetailController.$inject = [ '$scope', '$compile', '$routeParams', '$log', 'ClearScope', 'Breadcrumbs', 'LoadBreadCrumbs', 'GetBasePath', 'Wait', 'Rest', 'ProcessErrors', 'DigestEvents', 'SelectPlay', 'SelectTask', 'Socket', 'GetElapsed', 'SelectHost', 'FilterAllByHostName', 'DrawGraph', - 'LoadHostSummary' + 'LoadHostSummary', 'ReloadHostSummaryList' ]; diff --git a/awx/ui/static/js/helpers/JobSubmission.js b/awx/ui/static/js/helpers/JobSubmission.js index 65692b59e4..b5a1818220 100644 --- a/awx/ui/static/js/helpers/JobSubmission.js +++ b/awx/ui/static/js/helpers/JobSubmission.js @@ -16,7 +16,7 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential passwords = params.passwords || {}, callback = params.callback || 'JobLaunched', url = params.url; - + Wait('start'); Rest.setUrl(url); Rest.post(passwords) @@ -33,11 +33,11 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential .factory('PromptForCredential', ['$location', 'Wait', 'GetBasePath', 'LookUpInit', 'JobTemplateForm', 'CredentialList', 'Rest', 'Prompt', 'ProcessErrors', function($location, Wait, GetBasePath, LookUpInit, JobTemplateForm, CredentialList, Rest, Prompt, ProcessErrors) { return function(params) { - + var scope = params.scope, callback = params.callback || 'CredentialReady', selectionMade; - + Wait('stop'); scope.credential = ''; @@ -48,7 +48,7 @@ function($location, Wait, GetBasePath, LookUpInit, JobTemplateForm, CredentialLi selectionMade = function () { scope.$emit(callback, scope.credential); }; - + LookUpInit({ url: GetBasePath('credentials') + '?kind=ssh', scope: scope, @@ -107,15 +107,15 @@ function($location, Wait, GetBasePath, LookUpInit, JobTemplateForm, CredentialLi acceptedPasswords = {}, scope = parent_scope.$new(), e, buttons; - + Wait('stop'); - + function buildHtml() { var fld, field, html; html = ""; html += "
Launching this job requires the passwords listed below. Enter and confirm each password before continuing.
\n"; html += "
\n"; - + passwords.forEach(function(password) { // Prompt for password field = form.fields[password]; @@ -204,7 +204,7 @@ function($location, Wait, GetBasePath, LookUpInit, JobTemplateForm, CredentialLi $('#password-modal').dialog('open'); $('#password-accept-button').attr({ "disabled": "disabled" }); }); - + scope.passwordAccept = function() { if (!scope.password_form.$invalid) { passwords.forEach(function(password) { @@ -258,7 +258,7 @@ function($location, Wait, GetBasePath, LookUpInit, JobTemplateForm, CredentialLi "" + " click for help\n"; - + scope.helpText = "

After defining any extra variables, click Continue to start the job. Otherwise, click cancel to abort.

" + "

Extra variables are passed as command line variables to the playbook run. It is equivalent to the -e or --extra-vars " + "command line parameter for ansible-playbook. Provide key/value pairs using either YAML or JSON.

" + @@ -368,8 +368,8 @@ function($location, Wait, GetBasePath, LookUpInit, JobTemplateForm, CredentialLi }]) // Submit request to run a playbook -.factory('PlaybookRun', ['$location','$routeParams', 'LaunchJob', 'PromptForPasswords', 'Rest', 'GetBasePath', 'ProcessErrors', 'Wait', 'Empty', 'PromptForCredential', 'PromptForVars', - function ($location, $routeParams, LaunchJob, PromptForPasswords, Rest, GetBasePath, ProcessErrors, Wait, Empty, PromptForCredential, PromptForVars) { +.factory('PlaybookRun', ['$location','$routeParams', 'LaunchJob', 'PromptForPasswords', 'Rest', 'GetBasePath', 'Alert', 'ProcessErrors', 'Wait', 'Empty', 'PromptForCredential', 'PromptForVars', + function ($location, $routeParams, LaunchJob, PromptForPasswords, Rest, GetBasePath, Alert, ProcessErrors, Wait, Empty, PromptForCredential, PromptForVars) { return function (params) { var scope = params.scope, id = params.id, @@ -397,24 +397,39 @@ function($location, Wait, GetBasePath, LookUpInit, JobTemplateForm, CredentialLi var url = (job_template.related.jobs) ? job_template.related.jobs : job_template.related.job_template + 'jobs/'; Wait('start'); Rest.setUrl(url); - Rest.post(job_template).success(function (data) { - new_job_id = data.id; - launch_url = data.related.start; - prompt_for_vars = data.ask_variables_on_launch; - new_job = data; - if (data.passwords_needed_to_start.length > 0) { - scope.$emit('PromptForPasswords', data.passwords_needed_to_start); - } - else if (data.ask_variables_on_launch) { - scope.$emit('PromptForVars'); - } - else { - scope.$emit('StartPlaybookRun'); - } - }).error(function (data, status) { - ProcessErrors(scope, data, status, null, { hdr: 'Error!', - msg: 'Failed to create job. POST returned status: ' + status }); - }); + Rest.post(job_template) + .success(function (data) { + new_job_id = data.id; + launch_url = data.related.start; + prompt_for_vars = data.ask_variables_on_launch; + new_job = data; + if (data.passwords_needed_to_start.length > 0) { + scope.$emit('PromptForPasswords', data.passwords_needed_to_start); + } + else if (data.ask_variables_on_launch) { + scope.$emit('PromptForVars'); + } + else { + scope.$emit('StartPlaybookRun'); + } + }) + .error(function (data, status) { + var key, html; + if (status === 400) { + // there's a data problem with the job template + html = "\n"; + Wait('stop'); + Alert('Job Template Error', "

Fix the following issues before using the template:

" + html, 'alert-danger'); + } + else { + ProcessErrors(scope, data, status, null, { hdr: 'Error!', + msg: 'Failed to create job. POST returned status: ' + status }); + } + }); }); if (scope.removeCancelJob) {