mirror of
https://github.com/ansible/awx.git
synced 2026-02-20 20:50:06 -03:30
Merge pull request #106 from jaredevantabor/scan-job-templates
Scan job templates
This commit is contained in:
@@ -55,6 +55,8 @@ import 'tower/shared/InventoryTree';
|
|||||||
import 'tower/shared/Timer';
|
import 'tower/shared/Timer';
|
||||||
import 'tower/shared/Socket';
|
import 'tower/shared/Socket';
|
||||||
|
|
||||||
|
import 'tower/job-templates/main';
|
||||||
|
|
||||||
/*#if DEBUG#*/
|
/*#if DEBUG#*/
|
||||||
import {__deferLoadIfEnabled} from 'tower/debug';
|
import {__deferLoadIfEnabled} from 'tower/debug';
|
||||||
__deferLoadIfEnabled();
|
__deferLoadIfEnabled();
|
||||||
@@ -74,6 +76,7 @@ var tower = angular.module('Tower', [
|
|||||||
'UserFormDefinition',
|
'UserFormDefinition',
|
||||||
'FormGenerator',
|
'FormGenerator',
|
||||||
'OrganizationListDefinition',
|
'OrganizationListDefinition',
|
||||||
|
'jobTemplates',
|
||||||
'UserListDefinition',
|
'UserListDefinition',
|
||||||
'UserHelper',
|
'UserHelper',
|
||||||
'PromptDialog',
|
'PromptDialog',
|
||||||
@@ -267,6 +270,11 @@ var tower = angular.module('Tower', [
|
|||||||
controller: JobTemplatesAdd
|
controller: JobTemplatesAdd
|
||||||
}).
|
}).
|
||||||
|
|
||||||
|
when('/inventories/:inventory_id/job_templates/:template_id', {
|
||||||
|
templateUrl: urlPrefix + 'partials/job_templates.html',
|
||||||
|
controller: JobTemplatesEdit
|
||||||
|
}).
|
||||||
|
|
||||||
when('/inventories/:inventory_id/manage', {
|
when('/inventories/:inventory_id/manage', {
|
||||||
templateUrl: urlPrefix + 'partials/inventory-manage.html',
|
templateUrl: urlPrefix + 'partials/inventory-manage.html',
|
||||||
controller: InventoriesManage
|
controller: InventoriesManage
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
* @description This controller's for the Inventory page
|
* @description This controller's for the Inventory page
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import 'tower/job-templates/main';
|
||||||
|
|
||||||
export function InventoriesList($scope, $rootScope, $location, $log, $routeParams, $compile, $filter, Rest, Alert, InventoryList, generateList,
|
export function InventoriesList($scope, $rootScope, $location, $log, $routeParams, $compile, $filter, Rest, Alert, InventoryList, generateList,
|
||||||
LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, Wait, Stream,
|
LoadBreadCrumbs, Prompt, SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors, GetBasePath, Wait, Stream,
|
||||||
@@ -482,7 +483,8 @@ InventoriesAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log
|
|||||||
|
|
||||||
export function InventoriesEdit($scope, $rootScope, $compile, $location, $log, $routeParams, InventoryForm, GenerateForm, Rest,
|
export function InventoriesEdit($scope, $rootScope, $compile, $location, $log, $routeParams, InventoryForm, GenerateForm, Rest,
|
||||||
Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, generateList, OrganizationList, SearchInit, PaginateInit,
|
Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, generateList, OrganizationList, SearchInit, PaginateInit,
|
||||||
LookUpInit, GetBasePath, ParseTypeChange, Wait, ToJSON, ParseVariableString, Stream) {
|
LookUpInit, GetBasePath, ParseTypeChange, Wait, ToJSON, ParseVariableString, Stream, RelatedSearchInit, RelatedPaginateInit,
|
||||||
|
Prompt, PlaybookRun, CreateDialog, deleteJobTemplate) {
|
||||||
|
|
||||||
ClearScope();
|
ClearScope();
|
||||||
|
|
||||||
@@ -492,16 +494,28 @@ export function InventoriesEdit($scope, $rootScope, $compile, $location, $log, $
|
|||||||
generator = GenerateForm,
|
generator = GenerateForm,
|
||||||
inventory_id = $routeParams.inventory_id,
|
inventory_id = $routeParams.inventory_id,
|
||||||
master = {},
|
master = {},
|
||||||
fld, json_data, data;
|
fld, json_data, data,
|
||||||
|
relatedSets = {};
|
||||||
|
|
||||||
form.well = true;
|
form.well = true;
|
||||||
form.formLabelSize = null;
|
form.formLabelSize = null;
|
||||||
form.formFieldSize = null;
|
form.formFieldSize = null;
|
||||||
|
$scope.inventory_id = inventory_id;
|
||||||
generator.inject(form, { mode: 'edit', related: true, scope: $scope });
|
generator.inject(form, { mode: 'edit', related: true, scope: $scope });
|
||||||
|
|
||||||
generator.reset();
|
generator.reset();
|
||||||
LoadBreadCrumbs();
|
|
||||||
|
|
||||||
|
// After the project is loaded, retrieve each related set
|
||||||
|
if ($scope.inventoryLoadedRemove) {
|
||||||
|
$scope.inventoryLoadedRemove();
|
||||||
|
}
|
||||||
|
$scope.projectLoadedRemove = $scope.$on('inventoryLoaded', function () {
|
||||||
|
var set;
|
||||||
|
for (set in relatedSets) {
|
||||||
|
$scope.search(relatedSets[set].iterator);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Wait('start');
|
Wait('start');
|
||||||
Rest.setUrl(GetBasePath('inventory') + inventory_id + '/');
|
Rest.setUrl(GetBasePath('inventory') + inventory_id + '/');
|
||||||
@@ -530,6 +544,24 @@ export function InventoriesEdit($scope, $rootScope, $compile, $location, $log, $
|
|||||||
data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField];
|
data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
relatedSets = form.relatedSets(data.related);
|
||||||
|
|
||||||
|
// Initialize related search functions. Doing it here to make sure relatedSets object is populated.
|
||||||
|
RelatedSearchInit({
|
||||||
|
scope: $scope,
|
||||||
|
form: form,
|
||||||
|
relatedSets: relatedSets
|
||||||
|
});
|
||||||
|
RelatedPaginateInit({
|
||||||
|
scope: $scope,
|
||||||
|
relatedSets: relatedSets
|
||||||
|
});
|
||||||
|
|
||||||
|
LoadBreadCrumbs({
|
||||||
|
path: $location.path(),
|
||||||
|
title: $scope.inventory_name
|
||||||
|
});
|
||||||
|
|
||||||
Wait('stop');
|
Wait('stop');
|
||||||
$scope.parseType = 'yaml';
|
$scope.parseType = 'yaml';
|
||||||
ParseTypeChange({
|
ParseTypeChange({
|
||||||
@@ -546,6 +578,7 @@ export function InventoriesEdit($scope, $rootScope, $compile, $location, $log, $
|
|||||||
field: 'organization',
|
field: 'organization',
|
||||||
input_type: 'radio'
|
input_type: 'radio'
|
||||||
});
|
});
|
||||||
|
$scope.$emit('inventoryLoaded');
|
||||||
})
|
})
|
||||||
.error(function (data, status) {
|
.error(function (data, status) {
|
||||||
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
||||||
@@ -627,11 +660,179 @@ export function InventoriesEdit($scope, $rootScope, $compile, $location, $log, $
|
|||||||
$scope.addScanJob = function(){
|
$scope.addScanJob = function(){
|
||||||
$location.path($location.path()+'/job_templates/add');
|
$location.path($location.path()+'/job_templates/add');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.launchScanJob = function(){
|
||||||
|
PlaybookRun({ scope: $scope, id: this.scan_job_template.id });
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.scheduleScanJob = function(){
|
||||||
|
$location.path('/job_templates/'+this.scan_job_template.id+'/schedules');
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.editScanJob = function(){
|
||||||
|
$location.path($location.path()+'/job_templates/'+this.scan_job_template.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.copyScanJobTemplate = function(){
|
||||||
|
var id = this.scan_job_template.id,
|
||||||
|
name = this.scan_job_template.name,
|
||||||
|
element,
|
||||||
|
buttons = [{
|
||||||
|
"label": "Cancel",
|
||||||
|
"onClick": function() {
|
||||||
|
$(this).dialog('close');
|
||||||
|
},
|
||||||
|
"icon": "fa-times",
|
||||||
|
"class": "btn btn-default",
|
||||||
|
"id": "copy-close-button"
|
||||||
|
},{
|
||||||
|
"label": "Copy",
|
||||||
|
"onClick": function() {
|
||||||
|
copyAction();
|
||||||
|
},
|
||||||
|
"icon": "fa-copy",
|
||||||
|
"class": "btn btn-primary",
|
||||||
|
"id": "job-copy-button"
|
||||||
|
}],
|
||||||
|
copyAction = function () {
|
||||||
|
// retrieve the copy of the job template object from the api, then overwrite the name and throw away the id
|
||||||
|
Wait('start');
|
||||||
|
var url = GetBasePath('job_templates')+id;
|
||||||
|
Rest.setUrl(url);
|
||||||
|
Rest.get()
|
||||||
|
.success(function (data) {
|
||||||
|
data.name = $scope.new_copy_name;
|
||||||
|
delete data.id;
|
||||||
|
$scope.$emit('GoToCopy', data);
|
||||||
|
})
|
||||||
|
.error(function (data) {
|
||||||
|
Wait('stop');
|
||||||
|
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
||||||
|
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
CreateDialog({
|
||||||
|
id: 'copy-job-modal' ,
|
||||||
|
title: "Copy",
|
||||||
|
scope: $scope,
|
||||||
|
buttons: buttons,
|
||||||
|
width: 500,
|
||||||
|
height: 300,
|
||||||
|
minWidth: 200,
|
||||||
|
callback: 'CopyDialogReady'
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#job_name').text(name);
|
||||||
|
$('#copy-job-modal').show();
|
||||||
|
|
||||||
|
|
||||||
|
if ($scope.removeCopyDialogReady) {
|
||||||
|
$scope.removeCopyDialogReady();
|
||||||
|
}
|
||||||
|
$scope.removeCopyDialogReady = $scope.$on('CopyDialogReady', function() {
|
||||||
|
//clear any old remaining text
|
||||||
|
$scope.new_copy_name = "" ;
|
||||||
|
$scope.copy_form.$setPristine();
|
||||||
|
$('#copy-job-modal').dialog('open');
|
||||||
|
$('#job-copy-button').attr('ng-disabled', "!copy_form.$valid");
|
||||||
|
element = angular.element(document.getElementById('job-copy-button'));
|
||||||
|
$compile(element)($scope);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($scope.removeGoToCopy) {
|
||||||
|
$scope.removeGoToCopy();
|
||||||
|
}
|
||||||
|
$scope.removeGoToCopy = $scope.$on('GoToCopy', function(e, data) {
|
||||||
|
var url = GetBasePath('job_templates'),
|
||||||
|
old_survey_url = (data.related.survey_spec) ? data.related.survey_spec : "" ;
|
||||||
|
Rest.setUrl(url);
|
||||||
|
Rest.post(data)
|
||||||
|
.success(function (data) {
|
||||||
|
if(data.survey_enabled===true){
|
||||||
|
$scope.$emit("CopySurvey", data, old_survey_url);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('#copy-job-modal').dialog('close');
|
||||||
|
Wait('stop');
|
||||||
|
$location.path($location.path() + '/job_templates/' + data.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
.error(function (data) {
|
||||||
|
Wait('stop');
|
||||||
|
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
||||||
|
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($scope.removeCopySurvey) {
|
||||||
|
$scope.removeCopySurvey();
|
||||||
|
}
|
||||||
|
$scope.removeCopySurvey = $scope.$on('CopySurvey', function(e, new_data, old_url) {
|
||||||
|
// var url = data.related.survey_spec;
|
||||||
|
Rest.setUrl(old_url);
|
||||||
|
Rest.get()
|
||||||
|
.success(function (survey_data) {
|
||||||
|
|
||||||
|
Rest.setUrl(new_data.related.survey_spec);
|
||||||
|
Rest.post(survey_data)
|
||||||
|
.success(function () {
|
||||||
|
$('#copy-job-modal').dialog('close');
|
||||||
|
Wait('stop');
|
||||||
|
$location.path($location.path() + '/job_templates/' + new_data.id);
|
||||||
|
})
|
||||||
|
.error(function (data) {
|
||||||
|
Wait('stop');
|
||||||
|
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
||||||
|
msg: 'Call to ' + new_data.related.survey_spec + ' failed. DELETE returned status: ' + status });
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
.error(function (data) {
|
||||||
|
Wait('stop');
|
||||||
|
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
||||||
|
msg: 'Call to ' + old_url + ' failed. DELETE returned status: ' + status });
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.deleteScanJob = function () {
|
||||||
|
var id = this.scan_job_template.id ,
|
||||||
|
action = function () {
|
||||||
|
$('#prompt-modal').modal('hide');
|
||||||
|
Wait('start');
|
||||||
|
deleteJobTemplate(id)
|
||||||
|
.success(function () {
|
||||||
|
$('#prompt-modal').modal('hide');
|
||||||
|
$scope.search(form.related.scan_job_templates.iterator);
|
||||||
|
})
|
||||||
|
.error(function (data) {
|
||||||
|
Wait('stop');
|
||||||
|
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
||||||
|
msg: 'DELETE returned status: ' + status });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Prompt({
|
||||||
|
hdr: 'Delete',
|
||||||
|
body: '<div class=\"alert alert-info\">Delete job template ' + this.scan_job_template.name + '?</div>',
|
||||||
|
action: action
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InventoriesEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'InventoryForm', 'GenerateForm',
|
InventoriesEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'InventoryForm', 'GenerateForm',
|
||||||
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'generateList', 'OrganizationList', 'SearchInit',
|
'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'generateList', 'OrganizationList', 'SearchInit',
|
||||||
'PaginateInit', 'LookUpInit', 'GetBasePath', 'ParseTypeChange', 'Wait', 'ToJSON', 'ParseVariableString', 'Stream'
|
'PaginateInit', 'LookUpInit', 'GetBasePath', 'ParseTypeChange', 'Wait', 'ToJSON', 'ParseVariableString', 'Stream', 'RelatedSearchInit', 'RelatedPaginateInit',
|
||||||
|
'Prompt', 'PlaybookRun', 'CreateDialog', 'deleteJobTemplate'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -276,7 +276,8 @@ export function JobTemplatesAdd($scope, $rootScope, $compile, $location, $log, $
|
|||||||
|
|
||||||
$scope.job_type_options = [
|
$scope.job_type_options = [
|
||||||
{ value: 'run', label: 'Run' },
|
{ value: 'run', label: 'Run' },
|
||||||
{ value: 'check', label: 'Check' }
|
{ value: 'check', label: 'Check' },
|
||||||
|
{ value: 'scan' , label: 'Scan'}
|
||||||
];
|
];
|
||||||
|
|
||||||
$scope.verbosity_options = [
|
$scope.verbosity_options = [
|
||||||
@@ -301,12 +302,13 @@ export function JobTemplatesAdd($scope, $rootScope, $compile, $location, $log, $
|
|||||||
LookUpInit({
|
LookUpInit({
|
||||||
scope: $scope,
|
scope: $scope,
|
||||||
form: form,
|
form: form,
|
||||||
current_item: null,
|
current_item: ($routeParams.inventory_id !== undefined) ? $routeParams.inventory_id : null,
|
||||||
list: InventoryList,
|
list: InventoryList,
|
||||||
field: 'inventory',
|
field: 'inventory',
|
||||||
input_type: "radio"
|
input_type: "radio"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Clone the CredentialList object for use with cloud_credential. Cloning
|
// Clone the CredentialList object for use with cloud_credential. Cloning
|
||||||
// and changing properties to avoid collision.
|
// and changing properties to avoid collision.
|
||||||
jQuery.extend(true, CloudCredentialList, CredentialList);
|
jQuery.extend(true, CloudCredentialList, CredentialList);
|
||||||
@@ -340,10 +342,17 @@ export function JobTemplatesAdd($scope, $rootScope, $compile, $location, $log, $
|
|||||||
parent_scope: $scope
|
parent_scope: $scope
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Update playbook select whenever project value changes
|
// Update playbook select whenever project value changes
|
||||||
selectPlaybook = function (oldValue, newValue) {
|
selectPlaybook = function (oldValue, newValue) {
|
||||||
var url;
|
var url;
|
||||||
if (oldValue !== newValue) {
|
if($scope.job_type.value === 'scan' && $scope.project_name === "Default"){
|
||||||
|
$scope.playbook_options = ['Default'];
|
||||||
|
$scope.playbook = 'Default';
|
||||||
|
Wait('stop');
|
||||||
|
}
|
||||||
|
else if (oldValue !== newValue) {
|
||||||
if ($scope.project) {
|
if ($scope.project) {
|
||||||
Wait('start');
|
Wait('start');
|
||||||
url = GetBasePath('projects') + $scope.project + '/playbooks/';
|
url = GetBasePath('projects') + $scope.project + '/playbooks/';
|
||||||
@@ -365,6 +374,49 @@ export function JobTemplatesAdd($scope, $rootScope, $compile, $location, $log, $
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.jobTypeChange = function(){
|
||||||
|
if($scope.job_type){
|
||||||
|
if($scope.job_type.value === 'scan'){
|
||||||
|
// $scope.project_name = 'Default';
|
||||||
|
// $scope.project = null;
|
||||||
|
$scope.toggleScanInfo();
|
||||||
|
}
|
||||||
|
else if($scope.project_name === "Default"){
|
||||||
|
$scope.project_name = null;
|
||||||
|
$scope.playbook_options = [];
|
||||||
|
// $scope.playbook = 'null';
|
||||||
|
$scope.job_templates_form.playbook.$setPristine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.toggleScanInfo = function() {
|
||||||
|
$scope.project_name = 'Default';
|
||||||
|
if($scope.project === null){
|
||||||
|
selectPlaybook();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$scope.project = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if ($routeParams.inventory_id) {
|
||||||
|
// This means that the job template form was accessed via inventory prop's
|
||||||
|
// This also means the job is a scan job.
|
||||||
|
$scope.job_type.value = 'scan';
|
||||||
|
$scope.jobTypeChange();
|
||||||
|
$scope.inventory = $routeParams.inventory_id;
|
||||||
|
Rest.setUrl(GetBasePath('inventory') + $routeParams.inventory_id + '/');
|
||||||
|
Rest.get()
|
||||||
|
.success(function (data) {
|
||||||
|
$scope.inventory_name = data.name;
|
||||||
|
})
|
||||||
|
.error(function (data, status) {
|
||||||
|
ProcessErrors($scope, data, status, form, { hdr: 'Error!',
|
||||||
|
msg: 'Failed to lookup inventory: ' + data.id + '. GET returned status: ' + status });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Detect and alert user to potential SCM status issues
|
// Detect and alert user to potential SCM status issues
|
||||||
checkSCMStatus = function (oldValue, newValue) {
|
checkSCMStatus = function (oldValue, newValue) {
|
||||||
if (oldValue !== newValue && !Empty($scope.project)) {
|
if (oldValue !== newValue && !Empty($scope.project)) {
|
||||||
@@ -432,7 +484,17 @@ export function JobTemplatesAdd($scope, $rootScope, $compile, $location, $log, $
|
|||||||
|
|
||||||
|
|
||||||
function saveCompleted() {
|
function saveCompleted() {
|
||||||
setTimeout(function() { $scope.$apply(function() { $location.path('/job_templates'); }); }, 500);
|
setTimeout(function() {
|
||||||
|
$scope.$apply(function() {
|
||||||
|
var base = $location.path().replace(/^\//, '').split('/')[0];
|
||||||
|
if (base === 'job_templates') {
|
||||||
|
ReturnToCaller();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ReturnToCaller(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($scope.removeTemplateSaveSuccess) {
|
if ($scope.removeTemplateSaveSuccess) {
|
||||||
@@ -472,7 +534,10 @@ export function JobTemplatesAdd($scope, $rootScope, $compile, $location, $log, $
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
data.extra_vars = ToJSON($scope.parseType, $scope.variables, true);
|
data.extra_vars = ToJSON($scope.parseType, $scope.variables, true);
|
||||||
|
if(data.job_type === 'scan' && $scope.default_scan === true){
|
||||||
|
data.project = "";
|
||||||
|
data.playbook = "";
|
||||||
|
}
|
||||||
Rest.setUrl(defaultUrl);
|
Rest.setUrl(defaultUrl);
|
||||||
Rest.post(data)
|
Rest.post(data)
|
||||||
.success(function(data) {
|
.success(function(data) {
|
||||||
@@ -591,7 +656,8 @@ export function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log,
|
|||||||
// Our job type options
|
// Our job type options
|
||||||
$scope.job_type_options = [
|
$scope.job_type_options = [
|
||||||
{ value: 'run', label: 'Run' },
|
{ value: 'run', label: 'Run' },
|
||||||
{ value: 'check', label: 'Check' }
|
{ value: 'check', label: 'Check' },
|
||||||
|
{ value: 'scan', label: 'Scan'}
|
||||||
];
|
];
|
||||||
|
|
||||||
$scope.verbosity_options = [
|
$scope.verbosity_options = [
|
||||||
@@ -617,7 +683,12 @@ export function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log,
|
|||||||
|
|
||||||
getPlaybooks = function (project) {
|
getPlaybooks = function (project) {
|
||||||
var url;
|
var url;
|
||||||
if (!Empty(project)) {
|
if($scope.job_type.value === 'scan' && $scope.project_name === "Default"){
|
||||||
|
$scope.playbook_options = ['Default'];
|
||||||
|
$scope.playbook = 'Default';
|
||||||
|
Wait('stop');
|
||||||
|
}
|
||||||
|
else if (!Empty(project)) {
|
||||||
url = GetBasePath('projects') + project + '/playbooks/';
|
url = GetBasePath('projects') + project + '/playbooks/';
|
||||||
Wait('start');
|
Wait('start');
|
||||||
Rest.setUrl(url);
|
Rest.setUrl(url);
|
||||||
@@ -648,6 +719,32 @@ export function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log,
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.jobTypeChange = function(){
|
||||||
|
if($scope.job_type){
|
||||||
|
if($scope.job_type.value === 'scan'){
|
||||||
|
// $scope.project_name = 'Default';
|
||||||
|
// $scope.project = null;
|
||||||
|
$scope.toggleScanInfo();
|
||||||
|
}
|
||||||
|
else if($scope.project_name === "Default"){
|
||||||
|
$scope.project_name = null;
|
||||||
|
$scope.playbook_options = [];
|
||||||
|
// $scope.playbook = 'null';
|
||||||
|
$scope.job_templates_form.playbook.$setPristine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.toggleScanInfo = function() {
|
||||||
|
$scope.project_name = 'Default';
|
||||||
|
if($scope.project === null){
|
||||||
|
getPlaybooks();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$scope.project = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Detect and alert user to potential SCM status issues
|
// Detect and alert user to potential SCM status issues
|
||||||
checkSCMStatus = function () {
|
checkSCMStatus = function () {
|
||||||
if (!Empty($scope.project)) {
|
if (!Empty($scope.project)) {
|
||||||
@@ -888,7 +985,17 @@ export function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log,
|
|||||||
});
|
});
|
||||||
|
|
||||||
function saveCompleted() {
|
function saveCompleted() {
|
||||||
setTimeout(function() { $scope.$apply(function() { $location.path('/job_templates'); }); }, 500);
|
setTimeout(function() {
|
||||||
|
$scope.$apply(function() {
|
||||||
|
var base = $location.path().replace(/^\//, '').split('/')[0];
|
||||||
|
if (base === 'job_templates') {
|
||||||
|
ReturnToCaller();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ReturnToCaller(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($scope.removeTemplateSaveSuccess) {
|
if ($scope.removeTemplateSaveSuccess) {
|
||||||
|
|||||||
@@ -97,26 +97,35 @@ export default
|
|||||||
},
|
},
|
||||||
|
|
||||||
related: {
|
related: {
|
||||||
scan_jobs: {
|
scan_job_templates: {
|
||||||
type: 'collection',
|
type: 'collection',
|
||||||
title: 'Scan Jobs',
|
title: 'Scan Job Templates',
|
||||||
iterator: 'scan_job',
|
iterator: 'scan_job_template',
|
||||||
index: false,
|
index: false,
|
||||||
open: false,
|
open: false,
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
add: {
|
add: {
|
||||||
ngClick: "addScanJob(inventory_id)",
|
ngClick: "addScanJob()",
|
||||||
icon: 'icon-plus',
|
icon: 'icon-plus',
|
||||||
label: 'Add',
|
label: 'Add',
|
||||||
awToolTip: 'Add a scan job'
|
awToolTip: 'Add a scan job template'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
fields: {
|
fields: {
|
||||||
|
smart_status: {
|
||||||
|
label: 'Status',
|
||||||
|
// columnClass: 'col-md-2 col-sm-2 col-xs-2',
|
||||||
|
searchable: false,
|
||||||
|
nosort: true,
|
||||||
|
ngInclude: "'/static/partials/scan-job-template-smart-status.html'",
|
||||||
|
type: 'template'
|
||||||
|
},
|
||||||
name: {
|
name: {
|
||||||
key: true,
|
key: true,
|
||||||
label: 'Name'
|
label: 'Name',
|
||||||
|
linkTo: '/#/inventories/{{inventory_id}}/job_templates/{{scan_job_template.id}}'
|
||||||
},
|
},
|
||||||
description: {
|
description: {
|
||||||
label: 'Description'
|
label: 'Description'
|
||||||
@@ -124,19 +133,39 @@ export default
|
|||||||
},
|
},
|
||||||
|
|
||||||
fieldActions: {
|
fieldActions: {
|
||||||
|
submit: {
|
||||||
|
label: 'Launch',
|
||||||
|
ngClick: "launchScanJob()",
|
||||||
|
awToolTip: 'Launch the scan job template',
|
||||||
|
'class': 'btn btn-default'
|
||||||
|
},
|
||||||
|
schedule: {
|
||||||
|
label: 'Schedule',
|
||||||
|
ngClick: 'scheduleScanJob()',
|
||||||
|
awToolTip: 'Schedule future job template runs',
|
||||||
|
dataPlacement: 'top',
|
||||||
|
},
|
||||||
edit: {
|
edit: {
|
||||||
label: 'Edit',
|
label: 'Edit',
|
||||||
ngClick: "edit('organizations', organization.id, organization.name)",
|
ngClick: "editScanJob()",
|
||||||
icon: 'icon-edit',
|
icon: 'icon-edit',
|
||||||
awToolTip: 'Edit the organization',
|
awToolTip: 'Edit the scan job template',
|
||||||
'class': 'btn btn-default'
|
'class': 'btn btn-default'
|
||||||
},
|
},
|
||||||
"delete": {
|
"delete": {
|
||||||
label: 'Delete',
|
label: 'Delete',
|
||||||
ngClick: "delete('organizations', organization.id, organization.name, 'organizations')",
|
ngClick: "deleteScanJob()",
|
||||||
icon: 'icon-trash',
|
icon: 'icon-trash',
|
||||||
"class": 'btn-danger',
|
"class": 'btn-danger',
|
||||||
awToolTip: 'Delete the organization'
|
awToolTip: 'Delete the scan job template'
|
||||||
|
},
|
||||||
|
copy: {
|
||||||
|
label: 'Copy',
|
||||||
|
ngClick: "copyScanJobTemplate()",
|
||||||
|
"class": 'btn-danger btn-xs',
|
||||||
|
awToolTip: 'Copy template',
|
||||||
|
dataPlacement: 'top',
|
||||||
|
ngHide: 'job_template.summary_fields.can_copy === false'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,14 +173,10 @@ export default
|
|||||||
|
|
||||||
relatedSets: function(urls) {
|
relatedSets: function(urls) {
|
||||||
return {
|
return {
|
||||||
scan_jobs: {
|
scan_job_templates: {
|
||||||
iterator: 'scan_job',
|
iterator: 'scan_job_template',
|
||||||
url: urls.organizations
|
url: urls.scan_job_templates
|
||||||
},
|
}
|
||||||
// schedules: {
|
|
||||||
// iterator: 'schedule',
|
|
||||||
// url: urls.schedules
|
|
||||||
// }
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ export default
|
|||||||
label: 'Job Type',
|
label: 'Job Type',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
ngOptions: 'type.label for type in job_type_options track by type.value',
|
ngOptions: 'type.label for type in job_type_options track by type.value',
|
||||||
|
ngChange: 'jobTypeChange()',
|
||||||
"default": 0,
|
"default": 0,
|
||||||
addRequired: true,
|
addRequired: true,
|
||||||
editRequired: true,
|
editRequired: true,
|
||||||
@@ -101,7 +102,7 @@ export default
|
|||||||
awPopOver: "<p>Select the project containing the playbook you want this job to execute.</p>",
|
awPopOver: "<p>Select the project containing the playbook you want this job to execute.</p>",
|
||||||
dataTitle: 'Project',
|
dataTitle: 'Project',
|
||||||
dataPlacement: 'right',
|
dataPlacement: 'right',
|
||||||
dataContainer: "body"
|
dataContainer: "body",
|
||||||
},
|
},
|
||||||
playbook: {
|
playbook: {
|
||||||
label: 'Playbook',
|
label: 'Playbook',
|
||||||
@@ -113,7 +114,24 @@ export default
|
|||||||
awPopOver: "<p>Select the playbook to be executed by this job.</p>",
|
awPopOver: "<p>Select the playbook to be executed by this job.</p>",
|
||||||
dataTitle: 'Playbook',
|
dataTitle: 'Playbook',
|
||||||
dataPlacement: 'right',
|
dataPlacement: 'right',
|
||||||
dataContainer: "body"
|
dataContainer: "body",
|
||||||
|
},
|
||||||
|
// default_scan: {
|
||||||
|
// label: "Use default scan job project and playbook",
|
||||||
|
// type: 'checkbox',
|
||||||
|
// ngChange: 'toggleScanInfo()',
|
||||||
|
// ngShow: 'job_type.value === "scan" && project_name !== "Default"',
|
||||||
|
// column: 1,
|
||||||
|
// awPopOver: "<p>Scan jobs templates use a default project and default playbook. Uncheck this box to override these defaults.</p>",
|
||||||
|
// dataTitle: 'Scan jobs',
|
||||||
|
// dataPlacement: 'right',
|
||||||
|
// dataContainer: "body"
|
||||||
|
// },
|
||||||
|
default_scan: {
|
||||||
|
type: 'custom',
|
||||||
|
column: 1,
|
||||||
|
ngShow: 'job_type.value === "scan" && project_name !== "Default"',
|
||||||
|
control: '<a href="" ng-click="toggleScanInfo()">Reset to default project and playbook</a>'
|
||||||
},
|
},
|
||||||
credential: {
|
credential: {
|
||||||
label: 'Machine Credential',
|
label: 'Machine Credential',
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -171,6 +171,11 @@ angular.module('JobTemplatesHelper', ['Utilities'])
|
|||||||
input_type: "radio"
|
input_type: "radio"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if(scope.project === "" && scope.playbook === ""){
|
||||||
|
scope.toggleScanInfo();
|
||||||
|
}
|
||||||
|
|
||||||
RelatedSearchInit({
|
RelatedSearchInit({
|
||||||
scope: scope,
|
scope: scope,
|
||||||
form: form,
|
form: form,
|
||||||
@@ -193,7 +198,4 @@ angular.module('JobTemplatesHelper', ['Utilities'])
|
|||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}]);
|
}]);
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
var rest, getBasePath;
|
||||||
|
|
||||||
|
export default
|
||||||
|
[ 'Rest',
|
||||||
|
'GetBasePath',
|
||||||
|
function(_rest, _getBasePath) {
|
||||||
|
rest = _rest;
|
||||||
|
getBasePath = _getBasePath;
|
||||||
|
return deleteJobTemplate;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
function deleteJobTemplate(id) {
|
||||||
|
var url = getBasePath('job_templates');
|
||||||
|
|
||||||
|
url = url + id;
|
||||||
|
|
||||||
|
rest.setUrl(url);
|
||||||
|
return rest.destroy();
|
||||||
|
}
|
||||||
5
awx/ui/static/js/job-templates/main.js
Normal file
5
awx/ui/static/js/job-templates/main.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import deleteJobTemplate from './delete-job-template.service';
|
||||||
|
|
||||||
|
export default
|
||||||
|
angular.module('jobTemplates', [])
|
||||||
|
.service('deleteJobTemplate', deleteJobTemplate);
|
||||||
@@ -95,7 +95,6 @@ export default
|
|||||||
awToolTip: 'Copy template',
|
awToolTip: 'Copy template',
|
||||||
dataPlacement: 'top',
|
dataPlacement: 'top',
|
||||||
ngHide: 'job_template.summary_fields.can_copy===false'
|
ngHide: 'job_template.summary_fields.can_copy===false'
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ export default
|
|||||||
angular.module('ScanJobsListDefinition', [])
|
angular.module('ScanJobsListDefinition', [])
|
||||||
.value( 'ScanJobsList', {
|
.value( 'ScanJobsList', {
|
||||||
|
|
||||||
name: 'scan_jobs',
|
name: 'scan_job_templates',
|
||||||
iterator: 'scan_job',
|
iterator: 'scan_job_template',
|
||||||
editTitle: 'Scan Jobs',
|
editTitle: 'Scan Jobs',
|
||||||
'class': 'table-condensed',
|
'class': 'table-condensed',
|
||||||
index: false,
|
index: false,
|
||||||
|
|||||||
@@ -1107,6 +1107,8 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
|
|||||||
html += "\" ";
|
html += "\" ";
|
||||||
html += this.attr(field, 'ngOptions');
|
html += this.attr(field, 'ngOptions');
|
||||||
html += (field.ngChange) ? this.attr(field, 'ngChange') : "";
|
html += (field.ngChange) ? this.attr(field, 'ngChange') : "";
|
||||||
|
html += (field.ngDisabled) ? this.attr(field, 'ngDisabled'): "";
|
||||||
|
html += (field.ngRequired) ? this.attr(field, 'ngRequired') : "";
|
||||||
html += buildId(field, fld, this.form);
|
html += buildId(field, fld, this.form);
|
||||||
html += (options.mode === 'edit' && field.editRequired) ? "required " : "";
|
html += (options.mode === 'edit' && field.editRequired) ? "required " : "";
|
||||||
html += (options.mode === 'add' && field.addRequired) ? "required " : "";
|
html += (options.mode === 'add' && field.addRequired) ? "required " : "";
|
||||||
@@ -1331,6 +1333,7 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
|
|||||||
html += "<span class=\"input-group-btn\">\n";
|
html += "<span class=\"input-group-btn\">\n";
|
||||||
html += "<button type=\"button\" class=\"lookup-btn btn btn-default\" " + this.attr(field, 'ngClick');
|
html += "<button type=\"button\" class=\"lookup-btn btn btn-default\" " + this.attr(field, 'ngClick');
|
||||||
html += (field.readonly || field.showonly) ? " disabled " : "";
|
html += (field.readonly || field.showonly) ? " disabled " : "";
|
||||||
|
html += (field.ngDisabled) ? this.attr(field, "ngDisabled"): "";
|
||||||
html += "id=\"" + fld + "-lookup-btn\"><i class=\"fa fa-search\"></i></button>\n";
|
html += "id=\"" + fld + "-lookup-btn\"><i class=\"fa fa-search\"></i></button>\n";
|
||||||
html += "</span>\n";
|
html += "</span>\n";
|
||||||
html += "<input type=\"text\" class=\"form-control input-medium lookup\" ";
|
html += "<input type=\"text\" class=\"form-control input-medium lookup\" ";
|
||||||
@@ -1338,6 +1341,8 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
|
|||||||
html += "name=\"" + field.sourceModel + '_' + field.sourceField + "\" ";
|
html += "name=\"" + field.sourceModel + '_' + field.sourceField + "\" ";
|
||||||
html += "class=\"form-control\" ";
|
html += "class=\"form-control\" ";
|
||||||
html += (field.ngChange) ? this.attr(field, 'ngChange') : "";
|
html += (field.ngChange) ? this.attr(field, 'ngChange') : "";
|
||||||
|
html += (field.ngDisabled) ? this.attr(field, 'ngDisabled') : "" ;
|
||||||
|
html += (field.ngRequired) ? this.attr(field, 'ngRequired') : "";
|
||||||
html += (field.id) ? this.attr(field, 'id') : "";
|
html += (field.id) ? this.attr(field, 'id') : "";
|
||||||
html += (field.placeholder) ? this.attr(field, 'placeholder') : "";
|
html += (field.placeholder) ? this.attr(field, 'placeholder') : "";
|
||||||
html += (options.mode === 'edit' && field.editRequired) ? "required " : "";
|
html += (options.mode === 'edit' && field.editRequired) ? "required " : "";
|
||||||
|
|||||||
@@ -3,4 +3,11 @@
|
|||||||
<div id="inventory-edit-modal-dialog"></div>
|
<div id="inventory-edit-modal-dialog"></div>
|
||||||
<div id="scan-jobs-list" style="padding-top:40px"></div>
|
<div id="scan-jobs-list" style="padding-top:40px"></div>
|
||||||
<div ng-include="'/static/partials/logviewer.html'"></div>
|
<div ng-include="'/static/partials/logviewer.html'"></div>
|
||||||
|
<div id="copy-job-modal" style="display:none">
|
||||||
|
<form name="copy_form" id="copy_form">
|
||||||
|
What would you like to name the copy of job template <b><span id=job_name></span></b>?<br>
|
||||||
|
<input id="new_copy_name" name="new_copy_name" ng-model ="new_copy_name" ng-required="true" class="form-control ng-pristine ng-invalid-required ng-invalid" style="margin-top:10px;">
|
||||||
|
<div class="error survey_error ng-hide" ng-show="copy_form.new_copy_name.$dirty && copy_form.new_copy_name.$error.required">Please enter a name for this job template copy.</div></input>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
<aw-smart-status jobs="scan_job_template.summary_fields.recent_jobs"></aw-smart-status>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import jobTemplates from 'tower/job-templates/main';
|
||||||
|
import {describeModule} from '../describe-module';
|
||||||
|
|
||||||
|
describeModule(jobTemplates.name)
|
||||||
|
.testService('deleteJobTemplate', function(test, restStub) {
|
||||||
|
|
||||||
|
var service;
|
||||||
|
|
||||||
|
test.withService(function(_service) {
|
||||||
|
service = _service;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('deletes the job template', function() {
|
||||||
|
var result = {};
|
||||||
|
|
||||||
|
var actual = service();
|
||||||
|
|
||||||
|
restStub.succeedOn('destroy', result);
|
||||||
|
restStub.flush();
|
||||||
|
|
||||||
|
expect(actual).to.eventually.equal(result);
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -35,10 +35,19 @@ RestStub.prototype =
|
|||||||
|
|
||||||
return this.deferred.promise;
|
return this.deferred.promise;
|
||||||
},
|
},
|
||||||
|
destroy: function() {
|
||||||
|
this.deferred = this.deferred || {};
|
||||||
|
this.deferred.destroy = this[this.currentUrl];
|
||||||
|
|
||||||
|
return this.deferred.destroy.promise;
|
||||||
|
},
|
||||||
succeedAt: function(url, value) {
|
succeedAt: function(url, value) {
|
||||||
assertUrlDeferred(url, this);
|
assertUrlDeferred(url, this);
|
||||||
this[url].resolve(value);
|
this[url].resolve(value);
|
||||||
},
|
},
|
||||||
|
succeedOn: function(method, value) {
|
||||||
|
this.deferred[method] = value;
|
||||||
|
},
|
||||||
succeed: function(value) {
|
succeed: function(value) {
|
||||||
this.deferred.resolve(value);
|
this.deferred.resolve(value);
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user