From 2947c03adbcc2317a98a2d2cd9a71260919c4372 Mon Sep 17 00:00:00 2001 From: chouseknecht Date: Sat, 25 May 2013 00:12:59 -0400 Subject: [PATCH] Add a re-run button to Jobs page. --- .../ui/static/js/controllers/JobTemplates.js | 95 +------------ ansibleworks/ui/static/js/controllers/Jobs.js | 7 +- .../ui/static/js/helpers/JobTemplate.js | 125 +++++++++++++++++- ansibleworks/ui/static/js/helpers/Lookup.js | 1 - ansibleworks/ui/static/js/lists/Jobs.js | 26 ++-- 5 files changed, 147 insertions(+), 107 deletions(-) diff --git a/ansibleworks/ui/static/js/controllers/JobTemplates.js b/ansibleworks/ui/static/js/controllers/JobTemplates.js index 29f412fb82..73ef50c12c 100644 --- a/ansibleworks/ui/static/js/controllers/JobTemplates.js +++ b/ansibleworks/ui/static/js/controllers/JobTemplates.js @@ -13,7 +13,7 @@ function JobTemplatesList ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobTemplateList, GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, PromptPasswords, JobTemplateForm, CredentialList, - LookUpInit) + LookUpInit, SubmitJob) { ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior //scope. @@ -133,100 +133,15 @@ function JobTemplatesList ($scope, $rootScope, $location, $log, $routeParams, Re } } - function postJob(data) { - // Create the job record - (scope.credentialWatchRemove) ? scope.credentialWatchRemove() : null; - var dt = new Date().toISOString(); - Rest.setUrl(data.related.jobs); - Rest.post({ - name: data.name + ' ' + dt, // job name required and unique - description: data.description, - job_template: data.id, - inventory: data.inventory, - project: data.project, - playbook: data.playbook, - credential: data.credential, - forks: data.forks, - limit: data.limit, - verbosity: data.verbosity, - extra_vars: data.extra_vars - }) - .success( function(data, status, headers, config) { - if (data.passwords_needed_to_start.length > 0) { - // Passwords needed. Prompt for passwords, then start job. - PromptPasswords({ - scope: scope, - passwords: data.passwords_needed_to_start, - start_url: data.related.start - }); - } - else { - // No passwords needed, start the job! - Rest.setUrl(data.related.start); - Rest.post() - .success( function(data, status, headers, config) { - $location.path('/jobs'); - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Failed to start job. POST returned status: ' + status }); - }); - } - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Failed to create job. POST returned status: ' + status }); - }); - }; - scope.submitJob = function(id) { - // Get the job details - Rest.setUrl(defaultUrl + id + '/'); - Rest.get() - .success( function(data, status, headers, config) { - // Create a job record - scope.credential = ''; - if (data.credential == '' || data.credential == null) { - // Template does not have credential, prompt for one - if (scope.credentialWatchRemove) { - scope.credentialWatchRemove(); - } - scope.credentialWatchRemove = scope.$watch('credential', function(newVal, oldVal) { - if (newVal !== oldVal) { - // After user selects a credential from the modal, - // submit the job - if (scope.credential != '' && scope.credential !== null && scope.credential !== undefined) { - data.credential = scope.credential; - postJob(data); - } - } - }); - LookUpInit({ - scope: scope, - form: JobTemplateForm, - current_item: null, - list: CredentialList, - field: 'credential', - hdr: 'Credential Required' - }); - scope.lookUpCredential(); - } - else { - // We have what we need, submit the job - postJob(data); - } - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Failed to get job template details. GET returned status: ' + status }); - }); - }; - + SubmitJob({ scope: scope, id: id }); + } } JobTemplatesList.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobTemplateList', 'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', - 'ProcessErrors','GetBasePath', 'PromptPasswords', 'JobTemplateForm', 'CredentialList', 'LookUpInit' + 'ProcessErrors','GetBasePath', 'PromptPasswords', 'JobTemplateForm', 'CredentialList', 'LookUpInit', + 'SubmitJob' ]; function JobTemplatesAdd ($scope, $rootScope, $compile, $location, $log, $routeParams, JobTemplateForm, diff --git a/ansibleworks/ui/static/js/controllers/Jobs.js b/ansibleworks/ui/static/js/controllers/Jobs.js index 94f738bf71..26561136db 100644 --- a/ansibleworks/ui/static/js/controllers/Jobs.js +++ b/ansibleworks/ui/static/js/controllers/Jobs.js @@ -12,7 +12,7 @@ function JobsListCtrl ($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobList, GenerateList, LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, - ClearScope, ProcessErrors, GetBasePath, LookUpInit) + ClearScope, ProcessErrors, GetBasePath, LookUpInit, SubmitJob) { ClearScope('htmlTemplate'); var list = JobList; @@ -105,11 +105,14 @@ function JobsListCtrl ($scope, $rootScope, $location, $log, $routeParams, Rest, } + scope.submitJob = function(id, template) { + SubmitJob({ scope: scope, id: id, template: template }); + } } JobsListCtrl.$inject = [ '$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'JobList', 'GenerateList', 'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', - 'ProcessErrors','GetBasePath', 'LookUpInit' + 'ProcessErrors','GetBasePath', 'LookUpInit', 'SubmitJob' ]; diff --git a/ansibleworks/ui/static/js/helpers/JobTemplate.js b/ansibleworks/ui/static/js/helpers/JobTemplate.js index 6d55fede20..87920bc3af 100644 --- a/ansibleworks/ui/static/js/helpers/JobTemplate.js +++ b/ansibleworks/ui/static/js/helpers/JobTemplate.js @@ -4,8 +4,11 @@ * JobTemplateHelper * */ -angular.module('JobTemplateHelper', [ 'RestServices', 'Utilities', 'CredentialFormDefinition' ]) - .factory('PromptPasswords',['CredentialForm', '$compile', 'Rest', '$location', function(JobTemplateForm, $compile, Rest, $location) { +angular.module('JobTemplateHelper', [ 'RestServices', 'Utilities', 'CredentialFormDefinition', 'CredentialsListDefinition', + 'LookUpHelper', 'JobTemplateFormDefinition' ]) + + .factory('PromptPasswords',['CredentialForm', '$compile', 'Rest', '$location', + function(JobTemplateForm, $compile, Rest, $location) { return function(params) { var scope = params.scope; @@ -24,7 +27,13 @@ angular.module('JobTemplateHelper', [ 'RestServices', 'Utilities', 'CredentialFo Rest.setUrl(start_url); Rest.post(pswd) .success( function(data, status, headers, config) { - $location.path('/jobs'); + var base = $location.path().replace(/^\//,'').split('/')[0]; + if (base == 'jobs') { + scope.refreshJob(); + } + else { + $location.path('/jobs'); + } }) .error( function(data, status, headers, config) { ProcessErrors(scope, data, status, null, @@ -32,6 +41,7 @@ angular.module('JobTemplateHelper', [ 'RestServices', 'Utilities', 'CredentialFo }); } + html += html += "
\n"; for (var i=0; i < passwords.length; i++) { // Add the password field @@ -86,6 +96,114 @@ angular.module('JobTemplateHelper', [ 'RestServices', 'Utilities', 'CredentialFo $compile(element.contents())(scope); $('#password-modal').modal(); } + }]) + + .factory('SubmitJob',['PromptPasswords', 'CredentialForm', '$compile', 'Rest', '$location', 'GetBasePath', 'CredentialList', + 'LookUpInit', 'JobTemplateForm', 'ProcessErrors', + function(PromptPasswords, JobTemplateForm, $compile, Rest, $location, GetBasePath, CredentialList, LookUpInit, JobTemplateForm, + ProcessErrors) { + return function(params) { + var scope = params.scope; + var id = params.id; + var template_name = (params.template) ? params.template : null; + var base = $location.path().replace(/^\//,'').split('/')[0]; + var url = GetBasePath(base) + id + '/'; + + function postJob(data) { + // Create the job record + (scope.credentialWatchRemove) ? scope.credentialWatchRemove() : null; + var dt = new Date().toISOString(); + var url = (data.related.jobs) ? data.related.jobs : data.related.job_template + 'jobs/'; + var name = (template_name) ? template_name : data.name; + Rest.setUrl(url); + Rest.post({ + name: name + ' ' + dt, // job name required and unique + description: data.description, + job_template: data.id, + inventory: data.inventory, + project: data.project, + playbook: data.playbook, + credential: data.credential, + forks: data.forks, + limit: data.limit, + verbosity: data.verbosity, + extra_vars: data.extra_vars + }) + .success( function(data, status, headers, config) { + if (data.passwords_needed_to_start.length > 0) { + // Passwords needed. Prompt for passwords, then start job. + PromptPasswords({ + scope: scope, + passwords: data.passwords_needed_to_start, + start_url: data.related.start + }); + } + else { + // No passwords needed, start the job! + Rest.setUrl(data.related.start); + Rest.post() + .success( function(data, status, headers, config) { + var base = $location.path().replace(/^\//,'').split('/')[0]; + if (base == 'jobs') { + scope.refreshJob(); + } + else { + $location.path('/jobs'); + } + }) + .error( function(data, status, headers, config) { + ProcessErrors(scope, data, status, null, + { hdr: 'Error!', msg: 'Failed to start job. POST returned status: ' + status }); + }); + } + }) + .error( function(data, status, headers, config) { + ProcessErrors(scope, data, status, null, + { hdr: 'Error!', msg: 'Failed to create job. POST returned status: ' + status }); + }); + }; + + // Get the job or job_template record + Rest.setUrl(url); + Rest.get() + .success( function(data, status, headers, config) { + // Create a job record + scope.credential = ''; + if (data.credential == '' || data.credential == null) { + // Template does not have credential, prompt for one + if (scope.credentialWatchRemove) { + scope.credentialWatchRemove(); + } + scope.credentialWatchRemove = scope.$watch('credential', function(newVal, oldVal) { + if (newVal !== oldVal) { + // After user selects a credential from the modal, + // submit the job + if (scope.credential != '' && scope.credential !== null && scope.credential !== undefined) { + data.credential = scope.credential; + postJob(data); + } + } + }); + LookUpInit({ + scope: scope, + form: JobTemplateForm, + current_item: null, + list: CredentialList, + field: 'credential', + hdr: 'Credential Required' + }); + scope.lookUpCredential(); + } + else { + // We have what we need, submit the job + postJob(data); + } + }) + .error( function(data, status, headers, config) { + ProcessErrors(scope, data, status, null, + { hdr: 'Error!', msg: 'Failed to get job template details. GET returned status: ' + status }); + }); + }; }]); @@ -109,6 +227,5 @@ angular.module('JobTemplateHelper', [ 'RestServices', 'Utilities', 'CredentialFo - diff --git a/ansibleworks/ui/static/js/helpers/Lookup.js b/ansibleworks/ui/static/js/helpers/Lookup.js index b03e46900d..fe19472d38 100644 --- a/ansibleworks/ui/static/js/helpers/Lookup.js +++ b/ansibleworks/ui/static/js/helpers/Lookup.js @@ -15,7 +15,6 @@ */ angular.module('LookUpHelper', [ 'RestServices', 'Utilities', 'SearchHelper', 'PaginateHelper', 'ListGenerator', 'ApiLoader' ]) - .factory('LookUpInit', ['Alert', 'Rest', 'GenerateList', 'SearchInit', 'PaginateInit', 'GetBasePath', function(Alert, Rest, GenerateList, SearchInit, PaginateInit, GetBasePath) { return function(params) { diff --git a/ansibleworks/ui/static/js/lists/Jobs.js b/ansibleworks/ui/static/js/lists/Jobs.js index 29088fc733..09b8917082 100644 --- a/ansibleworks/ui/static/js/lists/Jobs.js +++ b/ansibleworks/ui/static/js/lists/Jobs.js @@ -60,13 +60,6 @@ angular.module('JobsListDefinition', []) }, fieldActions: { - edit: { - icon: 'icon-edit', - label: 'Edit', - ngClick: "editJob(\{\{ job.id \}\}, '\{\{ job.name \}\}')", - class: 'btn-success btn-small', - awToolTip: 'Edit job details', - }, summary: { label: 'Hosts', icon: 'icon-th-large', @@ -84,14 +77,27 @@ angular.module('JobsListDefinition', []) awToolTip: 'View events', ngDisabled: "job.status == 'new'" }, + edit: { + icon: 'icon-edit', + label: 'Edit', + ngClick: "editJob(\{\{ job.id \}\}, '\{\{ job.name \}\}')", + class: 'btn-success btn-small', + awToolTip: 'Edit job details', + }, + rerun: { + icon: 'icon-retweet', + mode: 'all', + ngClick: "submitJob(\{\{ job.id \}\}, '\{\{ job.summary_fields.job_template.name \}\}' )", + class: 'btn-success btn-small', + awToolTip: 'Re-run this job', + }, cancel: { icon: 'icon-minus-sign', - label: 'Cancel', - mode: 'all', + mode: 'all', ngClick: 'deleteJob(\{\{ job.id \}\})', class: 'btn-danger btn-small', awToolTip: 'Cancel job', ngDisabled: "job.status != 'new' && job.status != 'pending' && job.status != 'running'" - } + }, } });