mirror of
https://github.com/ansible/awx.git
synced 2026-05-08 09:57:35 -02:30
Propagate launch/relaunch logic across the app. Removed some old launch related factories.
This commit is contained in:
@@ -16,14 +16,12 @@ function ListTemplatesController(
|
|||||||
$state,
|
$state,
|
||||||
Alert,
|
Alert,
|
||||||
Dataset,
|
Dataset,
|
||||||
InitiatePlaybookRun,
|
|
||||||
ProcessErrors,
|
ProcessErrors,
|
||||||
Prompt,
|
Prompt,
|
||||||
PromptService,
|
PromptService,
|
||||||
resolvedModels,
|
resolvedModels,
|
||||||
strings,
|
strings,
|
||||||
Wait,
|
Wait
|
||||||
Empty
|
|
||||||
) {
|
) {
|
||||||
const vm = this || {};
|
const vm = this || {};
|
||||||
const [jobTemplate, workflowTemplate] = resolvedModels;
|
const [jobTemplate, workflowTemplate] = resolvedModels;
|
||||||
@@ -42,7 +40,7 @@ function ListTemplatesController(
|
|||||||
position: 'right',
|
position: 'right',
|
||||||
arrowHeight: 15
|
arrowHeight: 15
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
$scope.canAddJobTemplate = jobTemplate.options('actions.POST');
|
$scope.canAddJobTemplate = jobTemplate.options('actions.POST');
|
||||||
$scope.canAddWorkflowJobTemplate = workflowTemplate.options('actions.POST');
|
$scope.canAddWorkflowJobTemplate = workflowTemplate.options('actions.POST');
|
||||||
@@ -347,6 +345,7 @@ function ListTemplatesController(
|
|||||||
launchConf: launchData.data,
|
launchConf: launchData.data,
|
||||||
launchOptions: launchOptions.data,
|
launchOptions: launchOptions.data,
|
||||||
template: template.id,
|
template: template.id,
|
||||||
|
templateType: template.type,
|
||||||
prompts: PromptService.processPromptValues({
|
prompts: PromptService.processPromptValues({
|
||||||
launchConf: launchData.data,
|
launchConf: launchData.data,
|
||||||
launchOptions: launchOptions.data
|
launchOptions: launchOptions.data
|
||||||
@@ -368,79 +367,75 @@ function ListTemplatesController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function runWorkflowTemplate(template) {
|
function runWorkflowTemplate(template) {
|
||||||
InitiatePlaybookRun({ scope: $scope, id: template.id, job_type: 'workflow_job_template' });
|
const selectedWorkflowJobTemplate = workflowTemplate.create();
|
||||||
|
const preLaunchPromises = [
|
||||||
|
selectedWorkflowJobTemplate.getLaunch(template.id),
|
||||||
|
selectedWorkflowJobTemplate.optionsLaunch(template.id),
|
||||||
|
];
|
||||||
|
|
||||||
|
Promise.all(preLaunchPromises)
|
||||||
|
.then(([launchData, launchOptions]) => {
|
||||||
|
if (selectedWorkflowJobTemplate.canLaunchWithoutPrompt()) {
|
||||||
|
return selectedWorkflowJobTemplate
|
||||||
|
.postLaunch({ id: template.id })
|
||||||
|
.then(({ data }) => {
|
||||||
|
$state.go('workflowResults', { id: data.workflow_job }, { reload: true });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const promptData = {
|
||||||
|
launchConf: launchData.data,
|
||||||
|
launchOptions: launchOptions.data,
|
||||||
|
template: template.id,
|
||||||
|
templateType: template.type,
|
||||||
|
prompts: PromptService.processPromptValues({
|
||||||
|
launchConf: launchData.data,
|
||||||
|
launchOptions: launchOptions.data
|
||||||
|
}),
|
||||||
|
triggerModalOpen: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (launchData.data.survey_enabled) {
|
||||||
|
selectedWorkflowJobTemplate.getSurveyQuestions(template.id)
|
||||||
|
.then(({ data }) => {
|
||||||
|
const processed = PromptService.processSurveyQuestions({ surveyQuestions: data.spec });
|
||||||
|
promptData.surveyQuestions = processed.surveyQuestions;
|
||||||
|
$scope.promptData = promptData;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
$scope.promptData = promptData;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.launchJob = () => {
|
$scope.launchJob = () => {
|
||||||
const jobLaunchData = {
|
const jobLaunchData = PromptService.bundlePromptDataForLaunch($scope.promptData);
|
||||||
extra_vars: $scope.promptData.extraVars
|
|
||||||
};
|
|
||||||
|
|
||||||
if ($scope.promptData.launchConf.ask_tags_on_launch){
|
|
||||||
jobLaunchData.job_tags = $scope.promptData.prompts.tags.value.map(a => a.value).join();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($scope.promptData.launchConf.ask_skip_tags_on_launch){
|
|
||||||
jobLaunchData.skip_tags = $scope.promptData.prompts.skipTags.value.map(a => a.value).join();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($scope.promptData.launchConf.ask_limit_on_launch && _.has($scope, 'promptData.prompts.limit.value')){
|
|
||||||
jobLaunchData.limit = $scope.promptData.prompts.limit.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($scope.promptData.launchConf.ask_job_type_on_launch && _.has($scope, 'promptData.prompts.jobType.value.value')) {
|
|
||||||
jobLaunchData.job_type = $scope.promptData.prompts.jobType.value.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($scope.promptData.launchConf.ask_verbosity_on_launch && _.has($scope, 'promptData.prompts.verbosity.value.value')) {
|
|
||||||
jobLaunchData.verbosity = $scope.promptData.prompts.verbosity.value.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($scope.promptData.launchConf.ask_inventory_on_launch && !Empty($scope.promptData.prompts.inventory.value.id)){
|
|
||||||
jobLaunchData.inventory_id = $scope.promptData.prompts.inventory.value.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($scope.promptData.launchConf.ask_credential_on_launch){
|
|
||||||
jobLaunchData.credentials = [];
|
|
||||||
$scope.promptData.prompts.credentials.value.forEach((credential) => {
|
|
||||||
jobLaunchData.credentials.push(credential.id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($scope.promptData.launchConf.ask_diff_mode_on_launch && _.has($scope, 'promptData.prompts.diffMode.value')) {
|
|
||||||
jobLaunchData.diff_mode = $scope.promptData.prompts.diffMode.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($scope.promptData.prompts.credentials.passwords) {
|
|
||||||
_.forOwn($scope.promptData.prompts.credentials.passwords, (val, key) => {
|
|
||||||
if (!jobLaunchData.credential_passwords) {
|
|
||||||
jobLaunchData.credential_passwords = {};
|
|
||||||
}
|
|
||||||
if (key === "ssh_key_unlock") {
|
|
||||||
jobLaunchData.credential_passwords.ssh_key_unlock = val.value;
|
|
||||||
} else if (key !== "vault") {
|
|
||||||
jobLaunchData.credential_passwords[`${key}_password`] = val.value;
|
|
||||||
} else {
|
|
||||||
_.each(val, (vaultCred) => {
|
|
||||||
jobLaunchData.credential_passwords[vaultCred.vault_id ? `${key}_password.${vaultCred.vault_id}` : `${key}_password`] = vaultCred.value;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the extra_vars dict is empty, we don't want to include it if we didn't prompt for anything.
|
// If the extra_vars dict is empty, we don't want to include it if we didn't prompt for anything.
|
||||||
if(_.isEmpty(jobLaunchData.extra_vars) && !($scope.promptData.launchConf.ask_variables_on_launch && $scope.promptData.launchConf.survey_enabled && $scope.promptData.surveyQuestions.length > 0)){
|
if(_.isEmpty(jobLaunchData.extra_vars) && !($scope.promptData.launchConf.ask_variables_on_launch && $scope.promptData.launchConf.survey_enabled && $scope.promptData.surveyQuestions.length > 0)){
|
||||||
delete jobLaunchData.extra_vars;
|
delete jobLaunchData.extra_vars;
|
||||||
}
|
}
|
||||||
|
|
||||||
jobTemplate.create().postLaunch({
|
if($scope.promptData.templateType === 'job_template') {
|
||||||
id: $scope.promptData.template,
|
jobTemplate.create().postLaunch({
|
||||||
launchData: jobLaunchData
|
id: $scope.promptData.template,
|
||||||
})
|
launchData: jobLaunchData
|
||||||
.then((launchRes) => {
|
})
|
||||||
$state.go('jobResult', { id: launchRes.data.job }, { reload: true });
|
.then((launchRes) => {
|
||||||
})
|
$state.go('jobResult', { id: launchRes.data.job }, { reload: true });
|
||||||
.catch(createErrorHandler('launch job template', 'POST'));
|
})
|
||||||
|
.catch(createErrorHandler('launch job template', 'POST'));
|
||||||
|
} else if($scope.promptData.templateType === 'workflow_job_template') {
|
||||||
|
workflowTemplate.create().postLaunch({
|
||||||
|
id: $scope.promptData.template,
|
||||||
|
launchData: jobLaunchData
|
||||||
|
})
|
||||||
|
.then((launchRes) => {
|
||||||
|
$state.go('workflowResults', { id: launchRes.data.workflow_job }, { reload: true });
|
||||||
|
})
|
||||||
|
.catch(createErrorHandler('launch workflow job template', 'POST'));
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,14 +445,12 @@ ListTemplatesController.$inject = [
|
|||||||
'$state',
|
'$state',
|
||||||
'Alert',
|
'Alert',
|
||||||
'Dataset',
|
'Dataset',
|
||||||
'InitiatePlaybookRun',
|
|
||||||
'ProcessErrors',
|
'ProcessErrors',
|
||||||
'Prompt',
|
'Prompt',
|
||||||
'PromptService',
|
'PromptService',
|
||||||
'resolvedModels',
|
'resolvedModels',
|
||||||
'TemplatesStrings',
|
'TemplatesStrings',
|
||||||
'Wait',
|
'Wait'
|
||||||
'Empty'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
export default ListTemplatesController;
|
export default ListTemplatesController;
|
||||||
|
|||||||
@@ -5,17 +5,108 @@ const atRelaunch = {
|
|||||||
bindings: {
|
bindings: {
|
||||||
state: '<'
|
state: '<'
|
||||||
},
|
},
|
||||||
controller: ['RelaunchJob', 'InitiatePlaybookRun', 'ComponentsStrings', '$scope', atRelaunchCtrl],
|
controller: ['ProcessErrors', 'AdhocRun', 'ComponentsStrings',
|
||||||
|
'ProjectModel', 'InventorySourceModel', 'WorkflowJobModel', 'Alert',
|
||||||
|
'AdHocCommandModel', 'JobModel', 'JobTemplateModel', 'PromptService',
|
||||||
|
'GetBasePath', '$state', '$q', '$scope', atRelaunchCtrl
|
||||||
|
],
|
||||||
controllerAs: 'vm'
|
controllerAs: 'vm'
|
||||||
};
|
};
|
||||||
|
|
||||||
function atRelaunchCtrl (RelaunchJob, InitiatePlaybookRun, strings, $scope) {
|
function atRelaunchCtrl (
|
||||||
|
ProcessErrors, AdhocRun, strings,
|
||||||
|
Project, InventorySource, WorkflowJob, Alert,
|
||||||
|
AdHocCommand, Job, JobTemplate, PromptService,
|
||||||
|
GetBasePath, $state, $q, $scope
|
||||||
|
) {
|
||||||
const vm = this;
|
const vm = this;
|
||||||
const scope = $scope.$parent;
|
const scope = $scope.$parent;
|
||||||
const job = _.get(scope, 'job') || _.get(scope, 'completed_job');
|
const job = _.get(scope, 'job') || _.get(scope, 'completed_job');
|
||||||
|
const jobObj = new Job();
|
||||||
|
const jobTemplate = new JobTemplate();
|
||||||
|
|
||||||
|
const checkRelaunchPlaybook = (option) => {
|
||||||
|
jobObj.getRelaunch({
|
||||||
|
id: job.id
|
||||||
|
}).then((getRelaunchRes) => {
|
||||||
|
if (
|
||||||
|
getRelaunchRes.data.passwords_needed_to_start &&
|
||||||
|
getRelaunchRes.data.passwords_needed_to_start.length > 0
|
||||||
|
) {
|
||||||
|
const jobPromises = [
|
||||||
|
jobObj.request('get', job.id),
|
||||||
|
jobTemplate.optionsLaunch(job.unified_job_template)
|
||||||
|
];
|
||||||
|
|
||||||
|
$q.all(jobPromises)
|
||||||
|
.then(([jobRes, launchOptions]) => {
|
||||||
|
const populatedJob = jobRes.data;
|
||||||
|
const jobTypeChoices = _.get(
|
||||||
|
launchOptions,
|
||||||
|
'data.actions.POST.job_type.choices',
|
||||||
|
[]
|
||||||
|
).map(c => ({ label: c[1], value: c[0] }));
|
||||||
|
const verbosityChoices = _.get(
|
||||||
|
launchOptions,
|
||||||
|
'data.actions.POST.verbosity.choices',
|
||||||
|
[]
|
||||||
|
).map(c => ({ label: c[1], value: c[0] }));
|
||||||
|
|
||||||
|
vm.promptData = {
|
||||||
|
launchConf: {
|
||||||
|
passwords_needed_to_start: getRelaunchRes.data.passwords_needed_to_start
|
||||||
|
},
|
||||||
|
launchOptions: launchOptions.data,
|
||||||
|
job: job.id,
|
||||||
|
relaunchHostType: option ? (option.name).toLowerCase() : null,
|
||||||
|
prompts: {
|
||||||
|
credentials: {
|
||||||
|
value: populatedJob.summary_fields.credentials ? populatedJob.summary_fields.credentials : []
|
||||||
|
},
|
||||||
|
variables: {
|
||||||
|
value: populatedJob.extra_vars
|
||||||
|
},
|
||||||
|
inventory: {
|
||||||
|
value: populatedJob.summary_fields.inventory ? populatedJob.summary_fields.inventory : null
|
||||||
|
},
|
||||||
|
verbosity: {
|
||||||
|
value: _.find(verbosityChoices, item => item.value === populatedJob.verbosity),
|
||||||
|
choices: verbosityChoices
|
||||||
|
},
|
||||||
|
jobType: {
|
||||||
|
value: _.find(jobTypeChoices, item => item.value === populatedJob.job_type),
|
||||||
|
choices: jobTypeChoices
|
||||||
|
},
|
||||||
|
limit: {
|
||||||
|
value: populatedJob.limit
|
||||||
|
},
|
||||||
|
tags: {
|
||||||
|
value: populatedJob.job_tags
|
||||||
|
},
|
||||||
|
skipTags: {
|
||||||
|
value: populatedJob.skip_tags
|
||||||
|
},
|
||||||
|
diffMode: {
|
||||||
|
value: populatedJob.diff_mode
|
||||||
|
}
|
||||||
|
},
|
||||||
|
triggerModalOpen: true
|
||||||
|
};
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
jobObj.postRelaunch({
|
||||||
|
id: job.id
|
||||||
|
}).then((launchRes) => {
|
||||||
|
if (!$state.includes('jobs')) {
|
||||||
|
$state.go('jobResult', { id: launchRes.data.id }, { reload: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
vm.$onInit = () => {
|
vm.$onInit = () => {
|
||||||
vm.showRelaunch = !(job.type === 'system_job') && job.summary_fields.user_capabilities.start;
|
vm.showRelaunch = job.type !== 'system_job' && job.summary_fields.user_capabilities.start;
|
||||||
vm.showDropdown = job.type === 'job' && job.failed === true;
|
vm.showDropdown = job.type === 'job' && job.failed === true;
|
||||||
|
|
||||||
vm.createDropdown();
|
vm.createDropdown();
|
||||||
@@ -46,27 +137,97 @@ function atRelaunchCtrl (RelaunchJob, InitiatePlaybookRun, strings, $scope) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
vm.relaunchJob = () => {
|
vm.relaunchJob = () => {
|
||||||
let typeId;
|
|
||||||
|
|
||||||
if (job.type === 'inventory_update') {
|
if (job.type === 'inventory_update') {
|
||||||
typeId = job.inventory_source;
|
const inventorySource = new InventorySource();
|
||||||
} else if (job.type === 'project_update') {
|
|
||||||
typeId = job.project;
|
|
||||||
} else if (job.type === 'job' || job.type === 'system_job'
|
|
||||||
|| job.type === 'ad_hoc_command' || job.type === 'workflow_job') {
|
|
||||||
typeId = job.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
RelaunchJob({ scope, id: typeId, type: job.type, name: job.name });
|
inventorySource.getUpdate(job.inventory_source)
|
||||||
|
.then((getUpdateRes) => {
|
||||||
|
if (getUpdateRes.data.can_update) {
|
||||||
|
inventorySource.postUpdate(job.inventory_source)
|
||||||
|
.then((postUpdateRes) => {
|
||||||
|
if (!$state.includes('jobs')) {
|
||||||
|
$state.go('inventorySyncStdout', { id: postUpdateRes.data.id }, { reload: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Alert(
|
||||||
|
'Permission Denied', 'You do not have permission to sync this inventory source. Please contact your system administrator.',
|
||||||
|
'alert-danger'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (job.type === 'project_update') {
|
||||||
|
const project = new Project();
|
||||||
|
|
||||||
|
project.getUpdate(job.project)
|
||||||
|
.then((getUpdateRes) => {
|
||||||
|
if (getUpdateRes.data.can_update) {
|
||||||
|
project.postUpdate(job.project)
|
||||||
|
.then((postUpdateRes) => {
|
||||||
|
if (!$state.includes('jobs')) {
|
||||||
|
$state.go('scmUpdateStdout', { id: postUpdateRes.data.id }, { reload: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Alert(
|
||||||
|
'Permission Denied', 'You do not have access to update this project. Please contact your system administrator.',
|
||||||
|
'alert-danger'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (job.type === 'workflow_job') {
|
||||||
|
const workflowJob = new WorkflowJob();
|
||||||
|
|
||||||
|
workflowJob.postRelaunch({
|
||||||
|
id: job.id
|
||||||
|
}).then((launchRes) => {
|
||||||
|
if (!$state.includes('jobs')) {
|
||||||
|
$state.go('workflowResults', { id: launchRes.data.id }, { reload: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (job.type === 'ad_hoc_command') {
|
||||||
|
const adHocCommand = new AdHocCommand();
|
||||||
|
|
||||||
|
adHocCommand.getRelaunch({
|
||||||
|
id: job.id
|
||||||
|
}).then((getRelaunchRes) => {
|
||||||
|
if (
|
||||||
|
getRelaunchRes.data.passwords_needed_to_start &&
|
||||||
|
getRelaunchRes.data.passwords_needed_to_start.length > 0
|
||||||
|
) {
|
||||||
|
AdhocRun({ scope, project_id: job.id, relaunch: true });
|
||||||
|
} else {
|
||||||
|
adHocCommand.postRelaunch({
|
||||||
|
id: job.id
|
||||||
|
}).then((launchRes) => {
|
||||||
|
if (!$state.includes('jobs')) {
|
||||||
|
$state.go('adHocJobStdout', { id: launchRes.data.id }, { reload: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (job.type === 'job') {
|
||||||
|
checkRelaunchPlaybook();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
vm.relaunchOn = (option) => {
|
vm.relaunchOn = (option) => {
|
||||||
InitiatePlaybookRun({
|
checkRelaunchPlaybook(option);
|
||||||
scope,
|
};
|
||||||
id: job.id,
|
|
||||||
relaunch: true,
|
vm.relaunchJobWithPassword = () => {
|
||||||
job_type: job.type,
|
jobObj.postRelaunch({
|
||||||
host_type: (option.name).toLowerCase()
|
id: vm.promptData.job,
|
||||||
|
relaunchData: PromptService.bundlePromptDataForRelaunch(vm.promptData)
|
||||||
|
}).then((launchRes) => {
|
||||||
|
if (!$state.includes('jobs')) {
|
||||||
|
$state.go('jobResult', { id: launchRes.data.job }, { reload: true });
|
||||||
|
}
|
||||||
|
}).catch(({ data, status }) => {
|
||||||
|
ProcessErrors($scope, data, status, null, {
|
||||||
|
hdr: 'Error!',
|
||||||
|
msg: `Error relaunching job. POST returned status: ${status}`
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,4 +30,5 @@
|
|||||||
ng-if="!vm.showDropdown">
|
ng-if="!vm.showDropdown">
|
||||||
<i class="{{ vm.icon }}"></i>
|
<i class="{{ vm.icon }}"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
<prompt prompt-data="vm.promptData" on-finish="vm.relaunchJobWithPassword()"></launch>
|
||||||
|
</div>
|
||||||
|
|||||||
44
awx/ui/client/lib/models/AdHocCommand.js
Normal file
44
awx/ui/client/lib/models/AdHocCommand.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
let Base;
|
||||||
|
let $http;
|
||||||
|
|
||||||
|
function getRelaunch (params) {
|
||||||
|
const req = {
|
||||||
|
method: 'GET',
|
||||||
|
url: `${this.path}${params.id}/relaunch/`
|
||||||
|
};
|
||||||
|
|
||||||
|
return $http(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
function postRelaunch (params) {
|
||||||
|
const req = {
|
||||||
|
method: 'POST',
|
||||||
|
url: `${this.path}${params.id}/relaunch/`
|
||||||
|
};
|
||||||
|
|
||||||
|
return $http(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
function AdHocCommandModel (method, resource, config) {
|
||||||
|
Base.call(this, 'ad_hoc_commands');
|
||||||
|
|
||||||
|
this.Constructor = AdHocCommandModel;
|
||||||
|
this.postRelaunch = postRelaunch.bind(this);
|
||||||
|
this.getRelaunch = getRelaunch.bind(this);
|
||||||
|
|
||||||
|
return this.create(method, resource, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
function AdHocCommandModelLoader (BaseModel, _$http_) {
|
||||||
|
Base = BaseModel;
|
||||||
|
$http = _$http_;
|
||||||
|
|
||||||
|
return AdHocCommandModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
AdHocCommandModelLoader.$inject = [
|
||||||
|
'BaseModel',
|
||||||
|
'$http'
|
||||||
|
];
|
||||||
|
|
||||||
|
export default AdHocCommandModelLoader;
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
let Base;
|
let Base;
|
||||||
let WorkflowJobTemplateNode;
|
let WorkflowJobTemplateNode;
|
||||||
|
let $http;
|
||||||
|
|
||||||
function setDependentResources (id) {
|
function setDependentResources (id) {
|
||||||
this.dependentResources = [
|
this.dependentResources = [
|
||||||
@@ -12,28 +13,51 @@ function setDependentResources (id) {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getUpdate (id) {
|
||||||
|
const req = {
|
||||||
|
method: 'GET',
|
||||||
|
url: `${this.path}${id}/update/`
|
||||||
|
};
|
||||||
|
|
||||||
|
return $http(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
function postUpdate (id) {
|
||||||
|
const req = {
|
||||||
|
method: 'POST',
|
||||||
|
url: `${this.path}${id}/update/`
|
||||||
|
};
|
||||||
|
|
||||||
|
return $http(req);
|
||||||
|
}
|
||||||
|
|
||||||
function InventorySourceModel (method, resource, config) {
|
function InventorySourceModel (method, resource, config) {
|
||||||
Base.call(this, 'inventory_sources');
|
Base.call(this, 'inventory_sources');
|
||||||
|
|
||||||
this.Constructor = InventorySourceModel;
|
this.Constructor = InventorySourceModel;
|
||||||
this.setDependentResources = setDependentResources.bind(this);
|
this.setDependentResources = setDependentResources.bind(this);
|
||||||
|
this.getUpdate = getUpdate.bind(this);
|
||||||
|
this.postUpdate = postUpdate.bind(this);
|
||||||
|
|
||||||
return this.create(method, resource, config);
|
return this.create(method, resource, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
function InventorySourceModelLoader (
|
function InventorySourceModelLoader (
|
||||||
BaseModel,
|
BaseModel,
|
||||||
WorkflowJobTemplateNodeModel
|
WorkflowJobTemplateNodeModel,
|
||||||
|
_$http_
|
||||||
) {
|
) {
|
||||||
Base = BaseModel;
|
Base = BaseModel;
|
||||||
WorkflowJobTemplateNode = WorkflowJobTemplateNodeModel;
|
WorkflowJobTemplateNode = WorkflowJobTemplateNodeModel;
|
||||||
|
$http = _$http_;
|
||||||
|
|
||||||
return InventorySourceModel;
|
return InventorySourceModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
InventorySourceModelLoader.$inject = [
|
InventorySourceModelLoader.$inject = [
|
||||||
'BaseModel',
|
'BaseModel',
|
||||||
'WorkflowJobTemplateNodeModel'
|
'WorkflowJobTemplateNodeModel',
|
||||||
|
'$http'
|
||||||
];
|
];
|
||||||
|
|
||||||
export default InventorySourceModelLoader;
|
export default InventorySourceModelLoader;
|
||||||
|
|||||||
@@ -1,21 +1,48 @@
|
|||||||
let Base;
|
let Base;
|
||||||
|
let $http;
|
||||||
|
|
||||||
|
function getRelaunch (params) {
|
||||||
|
const req = {
|
||||||
|
method: 'GET',
|
||||||
|
url: `${this.path}${params.id}/relaunch/`
|
||||||
|
};
|
||||||
|
|
||||||
|
return $http(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
function postRelaunch (params) {
|
||||||
|
const req = {
|
||||||
|
method: 'POST',
|
||||||
|
url: `${this.path}${params.id}/relaunch/`
|
||||||
|
};
|
||||||
|
|
||||||
|
if (params.relaunchData) {
|
||||||
|
req.data = params.relaunchData;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $http(req);
|
||||||
|
}
|
||||||
|
|
||||||
function JobModel (method, resource, config) {
|
function JobModel (method, resource, config) {
|
||||||
Base.call(this, 'jobs');
|
Base.call(this, 'jobs');
|
||||||
|
|
||||||
this.Constructor = JobModel;
|
this.Constructor = JobModel;
|
||||||
|
this.postRelaunch = postRelaunch.bind(this);
|
||||||
|
this.getRelaunch = getRelaunch.bind(this);
|
||||||
|
|
||||||
return this.create(method, resource, config);
|
return this.create(method, resource, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
function JobModelLoader (BaseModel) {
|
function JobModelLoader (BaseModel, _$http_) {
|
||||||
Base = BaseModel;
|
Base = BaseModel;
|
||||||
|
$http = _$http_;
|
||||||
|
|
||||||
return JobModel;
|
return JobModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
JobModelLoader.$inject = [
|
JobModelLoader.$inject = [
|
||||||
'BaseModel'
|
'BaseModel',
|
||||||
|
'$http'
|
||||||
];
|
];
|
||||||
|
|
||||||
export default JobModelLoader;
|
export default JobModelLoader;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ let Base;
|
|||||||
let JobTemplate;
|
let JobTemplate;
|
||||||
let WorkflowJobTemplateNode;
|
let WorkflowJobTemplateNode;
|
||||||
let InventorySource;
|
let InventorySource;
|
||||||
|
let $http;
|
||||||
|
|
||||||
function setDependentResources (id) {
|
function setDependentResources (id) {
|
||||||
this.dependentResources = [
|
this.dependentResources = [
|
||||||
@@ -26,11 +27,31 @@ function setDependentResources (id) {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getUpdate (id) {
|
||||||
|
const req = {
|
||||||
|
method: 'GET',
|
||||||
|
url: `${this.path}${id}/update/`
|
||||||
|
};
|
||||||
|
|
||||||
|
return $http(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
function postUpdate (id) {
|
||||||
|
const req = {
|
||||||
|
method: 'POST',
|
||||||
|
url: `${this.path}${id}/update/`
|
||||||
|
};
|
||||||
|
|
||||||
|
return $http(req);
|
||||||
|
}
|
||||||
|
|
||||||
function ProjectModel (method, resource, config) {
|
function ProjectModel (method, resource, config) {
|
||||||
Base.call(this, 'projects');
|
Base.call(this, 'projects');
|
||||||
|
|
||||||
this.Constructor = ProjectModel;
|
this.Constructor = ProjectModel;
|
||||||
this.setDependentResources = setDependentResources.bind(this);
|
this.setDependentResources = setDependentResources.bind(this);
|
||||||
|
this.getUpdate = getUpdate.bind(this);
|
||||||
|
this.postUpdate = postUpdate.bind(this);
|
||||||
|
|
||||||
return this.create(method, resource, config);
|
return this.create(method, resource, config);
|
||||||
}
|
}
|
||||||
@@ -40,11 +61,13 @@ function ProjectModelLoader (
|
|||||||
JobTemplateModel,
|
JobTemplateModel,
|
||||||
WorkflowJobTemplateNodeModel,
|
WorkflowJobTemplateNodeModel,
|
||||||
InventorySourceModel,
|
InventorySourceModel,
|
||||||
|
_$http_
|
||||||
) {
|
) {
|
||||||
Base = BaseModel;
|
Base = BaseModel;
|
||||||
JobTemplate = JobTemplateModel;
|
JobTemplate = JobTemplateModel;
|
||||||
WorkflowJobTemplateNode = WorkflowJobTemplateNodeModel;
|
WorkflowJobTemplateNode = WorkflowJobTemplateNodeModel;
|
||||||
InventorySource = InventorySourceModel;
|
InventorySource = InventorySourceModel;
|
||||||
|
$http = _$http_;
|
||||||
|
|
||||||
return ProjectModel;
|
return ProjectModel;
|
||||||
}
|
}
|
||||||
@@ -53,7 +76,8 @@ ProjectModelLoader.$inject = [
|
|||||||
'BaseModel',
|
'BaseModel',
|
||||||
'JobTemplateModel',
|
'JobTemplateModel',
|
||||||
'WorkflowJobTemplateNodeModel',
|
'WorkflowJobTemplateNodeModel',
|
||||||
'InventorySourceModel'
|
'InventorySourceModel',
|
||||||
|
'$http'
|
||||||
];
|
];
|
||||||
|
|
||||||
export default ProjectModelLoader;
|
export default ProjectModelLoader;
|
||||||
|
|||||||
@@ -1,21 +1,34 @@
|
|||||||
let Base;
|
let Base;
|
||||||
|
let $http;
|
||||||
|
|
||||||
|
function postRelaunch (params) {
|
||||||
|
const req = {
|
||||||
|
method: 'POST',
|
||||||
|
url: `${this.path}${params.id}/relaunch/`
|
||||||
|
};
|
||||||
|
|
||||||
|
return $http(req);
|
||||||
|
}
|
||||||
|
|
||||||
function WorkflowJobModel (method, resource, config) {
|
function WorkflowJobModel (method, resource, config) {
|
||||||
Base.call(this, 'workflow_jobs');
|
Base.call(this, 'workflow_jobs');
|
||||||
|
|
||||||
this.Constructor = WorkflowJobModel;
|
this.Constructor = WorkflowJobModel;
|
||||||
|
this.postRelaunch = postRelaunch.bind(this);
|
||||||
|
|
||||||
return this.create(method, resource, config);
|
return this.create(method, resource, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
function WorkflowJobModelLoader (BaseModel) {
|
function WorkflowJobModelLoader (BaseModel, _$http_) {
|
||||||
Base = BaseModel;
|
Base = BaseModel;
|
||||||
|
$http = _$http_;
|
||||||
|
|
||||||
return WorkflowJobModel;
|
return WorkflowJobModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkflowJobModelLoader.$inject = [
|
WorkflowJobModelLoader.$inject = [
|
||||||
'BaseModel'
|
'BaseModel',
|
||||||
|
'$http'
|
||||||
];
|
];
|
||||||
|
|
||||||
export default WorkflowJobModelLoader;
|
export default WorkflowJobModelLoader;
|
||||||
|
|||||||
@@ -1,21 +1,85 @@
|
|||||||
let Base;
|
let Base;
|
||||||
|
let $http;
|
||||||
|
|
||||||
|
function optionsLaunch (id) {
|
||||||
|
const req = {
|
||||||
|
method: 'OPTIONS',
|
||||||
|
url: `${this.path}${id}/launch/`
|
||||||
|
};
|
||||||
|
|
||||||
|
return $http(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLaunch (id) {
|
||||||
|
const req = {
|
||||||
|
method: 'GET',
|
||||||
|
url: `${this.path}${id}/launch/`
|
||||||
|
};
|
||||||
|
|
||||||
|
return $http(req)
|
||||||
|
.then(res => {
|
||||||
|
this.model.launch.GET = res.data;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function postLaunch (params) {
|
||||||
|
const req = {
|
||||||
|
method: 'POST',
|
||||||
|
url: `${this.path}${params.id}/launch/`
|
||||||
|
};
|
||||||
|
|
||||||
|
if (params.launchData) {
|
||||||
|
req.data = params.launchData;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $http(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSurveyQuestions (id) {
|
||||||
|
const req = {
|
||||||
|
method: 'GET',
|
||||||
|
url: `${this.path}${id}/survey_spec/`
|
||||||
|
};
|
||||||
|
|
||||||
|
return $http(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
function canLaunchWithoutPrompt () {
|
||||||
|
const launchData = this.model.launch.GET;
|
||||||
|
|
||||||
|
return (
|
||||||
|
launchData.can_start_without_user_input &&
|
||||||
|
!launchData.survey_enabled
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function WorkflowJobTemplateModel (method, resource, config) {
|
function WorkflowJobTemplateModel (method, resource, config) {
|
||||||
Base.call(this, 'workflow_job_templates');
|
Base.call(this, 'workflow_job_templates');
|
||||||
|
|
||||||
this.Constructor = WorkflowJobTemplateModel;
|
this.Constructor = WorkflowJobTemplateModel;
|
||||||
|
this.optionsLaunch = optionsLaunch.bind(this);
|
||||||
|
this.getLaunch = getLaunch.bind(this);
|
||||||
|
this.postLaunch = postLaunch.bind(this);
|
||||||
|
this.getSurveyQuestions = getSurveyQuestions.bind(this);
|
||||||
|
this.canLaunchWithoutPrompt = canLaunchWithoutPrompt.bind(this);
|
||||||
|
|
||||||
|
this.model.launch = {};
|
||||||
|
|
||||||
return this.create(method, resource, config);
|
return this.create(method, resource, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
function WorkflowJobTemplateModelLoader (BaseModel) {
|
function WorkflowJobTemplateModelLoader (BaseModel, _$http_) {
|
||||||
Base = BaseModel;
|
Base = BaseModel;
|
||||||
|
$http = _$http_;
|
||||||
|
|
||||||
return WorkflowJobTemplateModel;
|
return WorkflowJobTemplateModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkflowJobTemplateModelLoader.$inject = [
|
WorkflowJobTemplateModelLoader.$inject = [
|
||||||
'BaseModel'
|
'BaseModel',
|
||||||
|
'$http'
|
||||||
];
|
];
|
||||||
|
|
||||||
export default WorkflowJobTemplateModelLoader;
|
export default WorkflowJobTemplateModelLoader;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import atLibServices from '~services';
|
import atLibServices from '~services';
|
||||||
|
|
||||||
import Application from '~models/Application';
|
import Application from '~models/Application';
|
||||||
|
import AdHocCommand from '~models/AdHocCommand';
|
||||||
import Base from '~models/Base';
|
import Base from '~models/Base';
|
||||||
import Config from '~models/Config';
|
import Config from '~models/Config';
|
||||||
import Credential from '~models/Credential';
|
import Credential from '~models/Credential';
|
||||||
@@ -30,6 +31,7 @@ angular
|
|||||||
atLibServices
|
atLibServices
|
||||||
])
|
])
|
||||||
.service('ApplicationModel', Application)
|
.service('ApplicationModel', Application)
|
||||||
|
.service('AdHocCommandModel', AdHocCommand)
|
||||||
.service('BaseModel', Base)
|
.service('BaseModel', Base)
|
||||||
.service('ConfigModel', Config)
|
.service('ConfigModel', Config)
|
||||||
.service('CredentialModel', Credential)
|
.service('CredentialModel', Credential)
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
/* jshint unused: vars */
|
/* jshint unused: vars */
|
||||||
export default
|
export default
|
||||||
[ 'InitiatePlaybookRun',
|
[ 'templateUrl',
|
||||||
'templateUrl',
|
|
||||||
'$state',
|
'$state',
|
||||||
'Alert',
|
'Alert',
|
||||||
function JobTemplatesList(InitiatePlaybookRun, templateUrl, $state, Alert) {
|
'JobTemplateModel',
|
||||||
|
'WorkflowJobTemplateModel',
|
||||||
|
'PromptService',
|
||||||
|
'ProcessErrors',
|
||||||
|
function JobTemplatesList(templateUrl, $state, Alert, JobTemplate, WorkflowJobTemplate, PromptService, ProcessErrors) {
|
||||||
return {
|
return {
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
link: link,
|
link: link,
|
||||||
@@ -15,6 +18,9 @@ export default
|
|||||||
};
|
};
|
||||||
|
|
||||||
function link(scope, element, attr) {
|
function link(scope, element, attr) {
|
||||||
|
const jobTemplate = new JobTemplate();
|
||||||
|
const workflowTemplate = new WorkflowJobTemplate();
|
||||||
|
|
||||||
scope.$watch("data", function(data) {
|
scope.$watch("data", function(data) {
|
||||||
if (data) {
|
if (data) {
|
||||||
if (data.length > 0) {
|
if (data.length > 0) {
|
||||||
@@ -42,21 +48,131 @@ export default
|
|||||||
|
|
||||||
scope.launchTemplate = function(template){
|
scope.launchTemplate = function(template){
|
||||||
if(template) {
|
if(template) {
|
||||||
if(template.type && (template.type === 'Job Template' || template.type === 'job_template')) {
|
if(template.type && (template.type === 'Job Template' || template.type === 'job_template')) {
|
||||||
InitiatePlaybookRun({ scope: scope, id: template.id, job_type: 'job_template' });
|
const selectedJobTemplate = jobTemplate.create();
|
||||||
}
|
const preLaunchPromises = [
|
||||||
else if(template.type && (template.type === 'Workflow Job Template' || template.type === 'workflow_job_template')) {
|
selectedJobTemplate.getLaunch(template.id),
|
||||||
InitiatePlaybookRun({ scope: scope, id: template.id, job_type: 'workflow_job_template' });
|
selectedJobTemplate.optionsLaunch(template.id),
|
||||||
}
|
];
|
||||||
else {
|
|
||||||
// Something went wrong - Let the user know that we're unable to launch because we don't know
|
Promise.all(preLaunchPromises)
|
||||||
// what type of job template this is
|
.then(([launchData, launchOptions]) => {
|
||||||
Alert('Error: Unable to determine template type', 'We were unable to determine this template\'s type while launching.');
|
if (selectedJobTemplate.canLaunchWithoutPrompt()) {
|
||||||
}
|
return selectedJobTemplate
|
||||||
|
.postLaunch({ id: template.id })
|
||||||
|
.then(({ data }) => {
|
||||||
|
$state.go('jobResult', { id: data.job }, { reload: true });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const promptData = {
|
||||||
|
launchConf: launchData.data,
|
||||||
|
launchOptions: launchOptions.data,
|
||||||
|
template: template.id,
|
||||||
|
templateType: template.type,
|
||||||
|
prompts: PromptService.processPromptValues({
|
||||||
|
launchConf: launchData.data,
|
||||||
|
launchOptions: launchOptions.data
|
||||||
|
}),
|
||||||
|
triggerModalOpen: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (launchData.data.survey_enabled) {
|
||||||
|
selectedJobTemplate.getSurveyQuestions(template.id)
|
||||||
|
.then(({ data }) => {
|
||||||
|
const processed = PromptService.processSurveyQuestions({ surveyQuestions: data.spec });
|
||||||
|
promptData.surveyQuestions = processed.surveyQuestions;
|
||||||
|
scope.promptData = promptData;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
scope.promptData = promptData;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if(template.type && (template.type === 'Workflow Job Template' || template.type === 'workflow_job_template')) {
|
||||||
|
const selectedWorkflowJobTemplate = workflowTemplate.create();
|
||||||
|
const preLaunchPromises = [
|
||||||
|
selectedWorkflowJobTemplate.getLaunch(template.id),
|
||||||
|
selectedWorkflowJobTemplate.optionsLaunch(template.id),
|
||||||
|
];
|
||||||
|
|
||||||
|
Promise.all(preLaunchPromises)
|
||||||
|
.then(([launchData, launchOptions]) => {
|
||||||
|
if (selectedWorkflowJobTemplate.canLaunchWithoutPrompt()) {
|
||||||
|
return selectedWorkflowJobTemplate
|
||||||
|
.postLaunch({ id: template.id })
|
||||||
|
.then(({ data }) => {
|
||||||
|
$state.go('workflowResults', { id: data.workflow_job }, { reload: true });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const promptData = {
|
||||||
|
launchConf: launchData.data,
|
||||||
|
launchOptions: launchOptions.data,
|
||||||
|
template: template.id,
|
||||||
|
templateType: template.type,
|
||||||
|
prompts: PromptService.processPromptValues({
|
||||||
|
launchConf: launchData.data,
|
||||||
|
launchOptions: launchOptions.data
|
||||||
|
}),
|
||||||
|
triggerModalOpen: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (launchData.data.survey_enabled) {
|
||||||
|
selectedWorkflowJobTemplate.getSurveyQuestions(template.id)
|
||||||
|
.then(({ data }) => {
|
||||||
|
const processed = PromptService.processSurveyQuestions({ surveyQuestions: data.spec });
|
||||||
|
promptData.surveyQuestions = processed.surveyQuestions;
|
||||||
|
scope.promptData = promptData;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
scope.promptData = promptData;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Alert('Error: Unable to launch template', 'Template parameter is missing');
|
// Something went wrong - Let the user know that we're unable to launch because we don't know
|
||||||
|
// what type of job template this is
|
||||||
|
Alert('Error: Unable to determine template type', 'We were unable to determine this template\'s type while launching.');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Alert('Error: Unable to launch template', 'Template parameter is missing');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
scope.launchJob = () => {
|
||||||
|
const jobLaunchData = PromptService.bundlePromptDataForLaunch(scope.promptData);
|
||||||
|
|
||||||
|
// If the extra_vars dict is empty, we don't want to include it if we didn't prompt for anything.
|
||||||
|
if(_.isEmpty(jobLaunchData.extra_vars) && !(scope.promptData.launchConf.ask_variables_on_launch && scope.promptData.launchConf.survey_enabled && scope.promptData.surveyQuestions.length > 0)){
|
||||||
|
delete jobLaunchData.extra_vars;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(scope.promptData.templateType === 'job_template') {
|
||||||
|
jobTemplate.create().postLaunch({
|
||||||
|
id: scope.promptData.template,
|
||||||
|
launchData: jobLaunchData
|
||||||
|
})
|
||||||
|
.then((launchRes) => {
|
||||||
|
$state.go('jobResult', { id: launchRes.data.job }, { reload: true });
|
||||||
|
})
|
||||||
|
.catch(({data, status}) => {
|
||||||
|
ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Failed to launch job template: ' + status });
|
||||||
|
});
|
||||||
|
} else if(scope.promptData.templateType === 'workflow_job_template') {
|
||||||
|
workflowTemplate.create().postLaunch({
|
||||||
|
id: scope.promptData.template,
|
||||||
|
launchData: jobLaunchData
|
||||||
|
})
|
||||||
|
.then((launchRes) => {
|
||||||
|
$state.go('workflowResults', { id: launchRes.data.workflow_job }, { reload: true });
|
||||||
|
})
|
||||||
|
.catch(({data, status}) => {
|
||||||
|
ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Failed to launch workflow job template: ' + status });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
scope.editTemplate = function (template) {
|
scope.editTemplate = function (template) {
|
||||||
|
|||||||
@@ -56,3 +56,4 @@
|
|||||||
<translate>You can create a job template <a href="#/templates/add_job_template">here</a>.</translate></p>
|
<translate>You can create a job template <a href="#/templates/add_job_template">here</a>.</translate></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<prompt prompt-data="promptData" on-finish="launchJob()"></launch>
|
||||||
|
|||||||
@@ -230,25 +230,25 @@ function adhocController($q, $scope, $stateParams,
|
|||||||
$scope.removeStartAdhocRun();
|
$scope.removeStartAdhocRun();
|
||||||
}
|
}
|
||||||
$scope.removeStartAdhocRun = $scope.$on('StartAdhocRun', function() {
|
$scope.removeStartAdhocRun = $scope.$on('StartAdhocRun', function() {
|
||||||
var password;
|
var password;
|
||||||
for (password in $scope.passwords) {
|
for (password in $scope.passwords) {
|
||||||
data[$scope.passwords[password]] = $scope[
|
data[$scope.passwords[password]] = $scope[
|
||||||
$scope.passwords[password]
|
$scope.passwords[password]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
// Launch the adhoc job
|
// Launch the adhoc job
|
||||||
Rest.setUrl(GetBasePath('inventory') + id + '/ad_hoc_commands/');
|
Rest.setUrl(GetBasePath('inventory') + id + '/ad_hoc_commands/');
|
||||||
Rest.post(data)
|
Rest.post(data)
|
||||||
.then(({data}) => {
|
.then(({data}) => {
|
||||||
Wait('stop');
|
Wait('stop');
|
||||||
$state.go('adHocJobStdout', {id: data.id});
|
$state.go('adHocJobStdout', {id: data.id});
|
||||||
})
|
})
|
||||||
.catch(({data, status}) => {
|
.catch(({data, status}) => {
|
||||||
ProcessErrors($scope, data, status, adhocForm, {
|
ProcessErrors($scope, data, status, adhocForm, {
|
||||||
hdr: 'Error!',
|
hdr: 'Error!',
|
||||||
msg: 'Failed to launch adhoc command. POST ' +
|
msg: 'Failed to launch adhoc command. POST ' +
|
||||||
'returned status: ' + status });
|
'returned status: ' + status });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if ($scope.removeCreateLaunchDialog) {
|
if ($scope.removeCreateLaunchDialog) {
|
||||||
|
|||||||
@@ -71,12 +71,8 @@ export default ['i18n', function(i18n) {
|
|||||||
columnClass: 'col-lg-2 col-md-2 col-sm-3 col-xs-4',
|
columnClass: 'col-lg-2 col-md-2 col-sm-3 col-xs-4',
|
||||||
|
|
||||||
submit: {
|
submit: {
|
||||||
icon: 'icon-rocket',
|
|
||||||
mode: 'all',
|
|
||||||
ngClick: 'relaunchJob($event, completed_job.id)',
|
|
||||||
awToolTip: i18n._('Relaunch using the same parameters'),
|
|
||||||
dataPlacement: 'top',
|
|
||||||
ngShow: "!completed_job.type == 'system_job' || completed_job.summary_fields.user_capabilities.start",
|
ngShow: "!completed_job.type == 'system_job' || completed_job.summary_fields.user_capabilities.start",
|
||||||
|
// uses the at-relaunch directive
|
||||||
relaunch: true
|
relaunch: true
|
||||||
},
|
},
|
||||||
"delete": {
|
"delete": {
|
||||||
|
|||||||
@@ -237,10 +237,6 @@ function(jobData, jobDataOptions, jobLabels, jobFinished, count, $scope, ParseTy
|
|||||||
jobResultsService.cancelJob($scope.job);
|
jobResultsService.cancelJob($scope.job);
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.relaunchJob = function() {
|
|
||||||
jobResultsService.relaunchJob($scope);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.lessLabels = false;
|
$scope.lessLabels = false;
|
||||||
$scope.toggleLessLabels = function() {
|
$scope.toggleLessLabels = function() {
|
||||||
if (!$scope.lessLabels) {
|
if (!$scope.lessLabels) {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export default {
|
|||||||
return [preScope, eventOn];
|
return [preScope, eventOn];
|
||||||
}],
|
}],
|
||||||
// the GET for the particular job
|
// the GET for the particular job
|
||||||
jobData: ['Rest', 'GetBasePath', '$stateParams', '$q', '$state', 'Alert', 'jobResultsService', function(Rest, GetBasePath, $stateParams, $q, $state, Alert, jobResultsService) {
|
jobData: ['jobResultsService', '$stateParams', function(jobResultsService, $stateParams) {
|
||||||
return jobResultsService.getJobData($stateParams.id);
|
return jobResultsService.getJobData($stateParams.id);
|
||||||
}],
|
}],
|
||||||
Dataset: ['QuerySet', '$stateParams', 'jobData',
|
Dataset: ['QuerySet', '$stateParams', 'jobData',
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
*************************************************/
|
*************************************************/
|
||||||
|
|
||||||
|
|
||||||
export default ['$q', 'Prompt', '$filter', 'Wait', 'Rest', '$state', 'ProcessErrors', 'InitiatePlaybookRun', 'GetBasePath', 'Alert', '$rootScope', 'i18n',
|
export default ['$q', 'Prompt', '$filter', 'Wait', 'Rest', '$state', 'ProcessErrors', 'GetBasePath', 'Alert', '$rootScope', 'i18n',
|
||||||
function ($q, Prompt, $filter, Wait, Rest, $state, ProcessErrors, InitiatePlaybookRun, GetBasePath, Alert, $rootScope, i18n) {
|
function ($q, Prompt, $filter, Wait, Rest, $state, ProcessErrors, GetBasePath, Alert, $rootScope, i18n) {
|
||||||
var val = {
|
var val = {
|
||||||
// the playbook_on_stats event returns the count data in a weird format.
|
// the playbook_on_stats event returns the count data in a weird format.
|
||||||
// format to what we need!
|
// format to what we need!
|
||||||
@@ -162,10 +162,6 @@ function ($q, Prompt, $filter, Wait, Rest, $state, ProcessErrors, InitiatePlaybo
|
|||||||
actionText: i18n._('PROCEED')
|
actionText: i18n._('PROCEED')
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
relaunchJob: function(scope) {
|
|
||||||
InitiatePlaybookRun({ scope: scope, id: scope.job.id,
|
|
||||||
relaunch: true });
|
|
||||||
},
|
|
||||||
getJobData: function(id){
|
getJobData: function(id){
|
||||||
var val = $q.defer();
|
var val = $q.defer();
|
||||||
|
|
||||||
|
|||||||
@@ -24,13 +24,6 @@ export default
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (scope.removePromptForPasswords) {
|
|
||||||
scope.removePromptForPasswords();
|
|
||||||
}
|
|
||||||
scope.removePromptForPasswords = scope.$on('PromptForPasswords', function() {
|
|
||||||
PromptForPasswords({ scope: scope, passwords: inventory_source.passwords_needed_to_update, callback: 'StartTheUpdate' });
|
|
||||||
});
|
|
||||||
|
|
||||||
if (scope.removeStartTheUpdate) {
|
if (scope.removeStartTheUpdate) {
|
||||||
scope.removeStartTheUpdate();
|
scope.removeStartTheUpdate();
|
||||||
}
|
}
|
||||||
@@ -49,13 +42,7 @@ export default
|
|||||||
else {
|
else {
|
||||||
inventory_source = data;
|
inventory_source = data;
|
||||||
if (data.can_update) {
|
if (data.can_update) {
|
||||||
if (data.passwords_needed_to_update) {
|
scope.$emit('StartTheUpdate', {});
|
||||||
Wait('stop');
|
|
||||||
scope.$emit('PromptForPasswords');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
scope.$emit('StartTheUpdate', {});
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Wait('stop');
|
Wait('stop');
|
||||||
Alert('Error Launching Sync', 'Unable to execute the inventory sync. Please contact your system administrator.',
|
Alert('Error Launching Sync', 'Unable to execute the inventory sync. Please contact your system administrator.',
|
||||||
|
|||||||
@@ -25,13 +25,6 @@ export default
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (scope.removePromptForPasswords) {
|
|
||||||
scope.removePromptForPasswords();
|
|
||||||
}
|
|
||||||
scope.removePromptForPasswords = scope.$on('PromptForPasswords', function() {
|
|
||||||
PromptForPasswords({ scope: scope, passwords: project.passwords_needed_to_update, callback: 'StartTheUpdate' });
|
|
||||||
});
|
|
||||||
|
|
||||||
if (scope.removeStartTheUpdate) {
|
if (scope.removeStartTheUpdate) {
|
||||||
scope.removeStartTheUpdate();
|
scope.removeStartTheUpdate();
|
||||||
}
|
}
|
||||||
@@ -46,13 +39,7 @@ export default
|
|||||||
.then(({data}) => {
|
.then(({data}) => {
|
||||||
project = data;
|
project = data;
|
||||||
if (project.can_update) {
|
if (project.can_update) {
|
||||||
if (project.passwords_needed_to_updated) {
|
scope.$emit('StartTheUpdate', {});
|
||||||
Wait('stop');
|
|
||||||
scope.$emit('PromptForPasswords');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
scope.$emit('StartTheUpdate', {});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Alert('Permission Denied', 'You do not have access to update this project. Please contact your system administrator.',
|
Alert('Permission Denied', 'You do not have access to update this project. Please contact your system administrator.',
|
||||||
|
|||||||
@@ -92,12 +92,8 @@ export default ['i18n', function(i18n) {
|
|||||||
dataPlacement: "top"
|
dataPlacement: "top"
|
||||||
},
|
},
|
||||||
submit: {
|
submit: {
|
||||||
icon: 'icon-rocket',
|
|
||||||
mode: 'all',
|
|
||||||
ngClick: 'relaunchJob($event, job.id)',
|
|
||||||
awToolTip: i18n._('Relaunch using the same parameters'),
|
|
||||||
dataPlacement: 'top',
|
|
||||||
ngShow: "!(job.type == 'system_job') && job.summary_fields.user_capabilities.start",
|
ngShow: "!(job.type == 'system_job') && job.summary_fields.user_capabilities.start",
|
||||||
|
// uses the at-relaunch directive
|
||||||
relaunch: true,
|
relaunch: true,
|
||||||
},
|
},
|
||||||
cancel: {
|
cancel: {
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
export default
|
|
||||||
function JobStatusToolTip() {
|
|
||||||
return function(status) {
|
|
||||||
var toolTip;
|
|
||||||
switch (status) {
|
|
||||||
case 'successful':
|
|
||||||
case 'success':
|
|
||||||
toolTip = 'There were no failed tasks.';
|
|
||||||
break;
|
|
||||||
case 'failed':
|
|
||||||
toolTip = 'Some tasks encountered errors.';
|
|
||||||
break;
|
|
||||||
case 'canceled':
|
|
||||||
toolTip = 'Stopped by user request.';
|
|
||||||
break;
|
|
||||||
case 'new':
|
|
||||||
toolTip = 'In queue, waiting on task manager.';
|
|
||||||
break;
|
|
||||||
case 'waiting':
|
|
||||||
toolTip = 'SCM Update or Inventory Update is executing.';
|
|
||||||
break;
|
|
||||||
case 'pending':
|
|
||||||
toolTip = 'Not in queue, waiting on task manager.';
|
|
||||||
break;
|
|
||||||
case 'running':
|
|
||||||
toolTip = 'Playbook tasks executing.';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return toolTip;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
export default
|
|
||||||
function JobsListUpdate() {
|
|
||||||
return function(params) {
|
|
||||||
var scope = params.scope,
|
|
||||||
parent_scope = params.parent_scope,
|
|
||||||
list = params.list;
|
|
||||||
|
|
||||||
scope[list.name].forEach(function(item, item_idx) {
|
|
||||||
var fld, field,
|
|
||||||
itm = scope[list.name][item_idx];
|
|
||||||
|
|
||||||
//if (item.type === 'inventory_update') {
|
|
||||||
// itm.name = itm.name.replace(/^.*?:/,'').replace(/^: /,'');
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Set the item type label
|
|
||||||
if (list.fields.type) {
|
|
||||||
parent_scope.type_choices.forEach(function(choice) {
|
|
||||||
if (choice.value === item.type) {
|
|
||||||
itm.type_label = choice.label;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Set the job status label
|
|
||||||
parent_scope.status_choices.forEach(function(status) {
|
|
||||||
if (status.value === item.status) {
|
|
||||||
itm.status_label = status.label;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (list.name === 'completed_jobs' || list.name === 'running_jobs') {
|
|
||||||
itm.status_tip = itm.status_label + '. Click for details.';
|
|
||||||
}
|
|
||||||
else if (list.name === 'queued_jobs') {
|
|
||||||
itm.status_tip = 'Pending';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy summary_field values
|
|
||||||
for (field in list.fields) {
|
|
||||||
fld = list.fields[field];
|
|
||||||
if (fld.sourceModel) {
|
|
||||||
if (itm.summary_fields[fld.sourceModel]) {
|
|
||||||
itm[field] = itm.summary_fields[fld.sourceModel][fld.sourceField];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
export default
|
|
||||||
function RelaunchAdhoc(AdhocRun) {
|
|
||||||
return function(params) {
|
|
||||||
var scope = params.scope,
|
|
||||||
id = params.id;
|
|
||||||
AdhocRun({ scope: scope, project_id: id, relaunch: true });
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
RelaunchAdhoc.$inject =
|
|
||||||
[ 'AdhocRun' ];
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
export default
|
|
||||||
function RelaunchInventory(Wait, Rest, InventoryUpdate, ProcessErrors, GetBasePath) {
|
|
||||||
return function(params) {
|
|
||||||
var scope = params.scope,
|
|
||||||
id = params.id,
|
|
||||||
url = GetBasePath('inventory_sources') + id + '/';
|
|
||||||
Wait('start');
|
|
||||||
Rest.setUrl(url);
|
|
||||||
Rest.get()
|
|
||||||
.then(({data}) => {
|
|
||||||
InventoryUpdate({
|
|
||||||
scope: scope,
|
|
||||||
url: data.related.update
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(({data, status}) => {
|
|
||||||
ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Failed to retrieve inventory source: ' +
|
|
||||||
url + ' GET returned: ' + status });
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
RelaunchInventory.$inject =
|
|
||||||
[ 'Wait', 'Rest',
|
|
||||||
'InventoryUpdate', 'ProcessErrors', 'GetBasePath'
|
|
||||||
];
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
export default
|
|
||||||
function RelaunchJob(RelaunchInventory, RelaunchPlaybook, RelaunchSCM, RelaunchAdhoc) {
|
|
||||||
return function(params) {
|
|
||||||
var scope = params.scope,
|
|
||||||
id = params.id,
|
|
||||||
type = params.type,
|
|
||||||
name = params.name;
|
|
||||||
if (type === 'inventory_update') {
|
|
||||||
RelaunchInventory({ scope: scope, id: id});
|
|
||||||
}
|
|
||||||
else if (type === 'ad_hoc_command') {
|
|
||||||
RelaunchAdhoc({ scope: scope, id: id, name: name });
|
|
||||||
}
|
|
||||||
else if (type === 'job' || type === 'system_job' || type === 'workflow_job') {
|
|
||||||
RelaunchPlaybook({ scope: scope, id: id, name: name, job_type: type });
|
|
||||||
}
|
|
||||||
else if (type === 'project_update') {
|
|
||||||
RelaunchSCM({ scope: scope, id: id });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
RelaunchJob.$inject =
|
|
||||||
[ 'RelaunchInventory',
|
|
||||||
'RelaunchPlaybook',
|
|
||||||
'RelaunchSCM',
|
|
||||||
'RelaunchAdhoc'
|
|
||||||
];
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
export default
|
|
||||||
function RelaunchPlaybook(InitiatePlaybookRun) {
|
|
||||||
return function(params) {
|
|
||||||
var scope = params.scope,
|
|
||||||
id = params.id,
|
|
||||||
job_type = params.job_type;
|
|
||||||
InitiatePlaybookRun({ scope: scope, id: id, relaunch: true, job_type: job_type });
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
RelaunchPlaybook.$inject =
|
|
||||||
[ 'InitiatePlaybookRun' ];
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
export default
|
|
||||||
function RelaunchSCM(ProjectUpdate) {
|
|
||||||
return function(params) {
|
|
||||||
var scope = params.scope,
|
|
||||||
id = params.id;
|
|
||||||
ProjectUpdate({ scope: scope, project_id: id });
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
RelaunchSCM.$inject =
|
|
||||||
[ 'ProjectUpdate' ];
|
|
||||||
@@ -11,11 +11,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export default ['$state', '$rootScope', '$scope', '$stateParams',
|
export default ['$state', '$rootScope', '$scope', '$stateParams',
|
||||||
'Find', 'DeleteJob', 'RelaunchJob',
|
'Find', 'DeleteJob',
|
||||||
'GetBasePath', 'Dataset', 'QuerySet', 'ListDefinition', '$interpolate',
|
'GetBasePath', 'Dataset', 'QuerySet', 'ListDefinition', '$interpolate',
|
||||||
|
'WorkflowJobModel', 'ProjectModel', 'Alert', 'InventorySourceModel',
|
||||||
|
'AdHocCommandModel', 'JobModel',
|
||||||
function($state, $rootScope, $scope, $stateParams,
|
function($state, $rootScope, $scope, $stateParams,
|
||||||
Find, DeleteJob, RelaunchJob,
|
Find, DeleteJob,
|
||||||
GetBasePath, Dataset, qs, ListDefinition, $interpolate) {
|
GetBasePath, Dataset, qs, ListDefinition, $interpolate,
|
||||||
|
WorkflowJob, Project, Alert, InventorySource,
|
||||||
|
AdHocCommand, Job) {
|
||||||
|
|
||||||
var list = ListDefinition;
|
var list = ListDefinition;
|
||||||
|
|
||||||
@@ -95,42 +99,6 @@
|
|||||||
DeleteJob({ scope: $scope, id: id });
|
DeleteJob({ scope: $scope, id: id });
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.relaunchJob = function(event, id) {
|
|
||||||
let job, typeId, jobs;
|
|
||||||
try {
|
|
||||||
$(event.target).tooltip('hide');
|
|
||||||
} catch (e) {
|
|
||||||
//ignore
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($scope.completed_jobs) {
|
|
||||||
jobs = $scope.completed_jobs;
|
|
||||||
}
|
|
||||||
else if ($scope.running_jobs) {
|
|
||||||
jobs = $scope.running_jobs;
|
|
||||||
}
|
|
||||||
else if ($scope.queued_jobs) {
|
|
||||||
jobs = $scope.queued_jobs;
|
|
||||||
}
|
|
||||||
else if ($scope.all_jobs) {
|
|
||||||
jobs = $scope.all_jobs;
|
|
||||||
}
|
|
||||||
else if ($scope.jobs) {
|
|
||||||
jobs = $scope.jobs;
|
|
||||||
}
|
|
||||||
|
|
||||||
job = Find({list: jobs, key: 'id', val: id });
|
|
||||||
|
|
||||||
if (job.type === 'inventory_update') {
|
|
||||||
typeId = job.inventory_source;
|
|
||||||
} else if (job.type === 'project_update') {
|
|
||||||
typeId = job.project;
|
|
||||||
} else if (job.type === 'job' || job.type === "system_job" || job.type === 'ad_hoc_command' || job.type === 'workflow_job') {
|
|
||||||
typeId = job.id;
|
|
||||||
}
|
|
||||||
RelaunchJob({ scope: $scope, id: typeId, type: job.type, name: job.name });
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.viewjobResults = function(job) {
|
$scope.viewjobResults = function(job) {
|
||||||
|
|
||||||
var goTojobResults = function(state) {
|
var goTojobResults = function(state) {
|
||||||
|
|||||||
@@ -7,13 +7,6 @@
|
|||||||
import jobsList from './jobs-list.controller';
|
import jobsList from './jobs-list.controller';
|
||||||
import jobsRoute from './jobs.route';
|
import jobsRoute from './jobs.route';
|
||||||
import DeleteJob from './factories/delete-job.factory';
|
import DeleteJob from './factories/delete-job.factory';
|
||||||
import JobStatusToolTip from './factories/job-status-tool-tip.factory';
|
|
||||||
import JobsListUpdate from './factories/jobs-list-update.factory';
|
|
||||||
import RelaunchAdhoc from './factories/relaunch-adhoc.factory';
|
|
||||||
import RelaunchInventory from './factories/relaunch-inventory.factory';
|
|
||||||
import RelaunchJob from './factories/relaunch-job.factory';
|
|
||||||
import RelaunchPlaybook from './factories/relaunch-playbook.factory';
|
|
||||||
import RelaunchSCM from './factories/relaunch-scm.factory';
|
|
||||||
import AllJobsList from './all-jobs.list';
|
import AllJobsList from './all-jobs.list';
|
||||||
|
|
||||||
export default
|
export default
|
||||||
@@ -23,11 +16,4 @@ export default
|
|||||||
}])
|
}])
|
||||||
.controller('JobsList', jobsList)
|
.controller('JobsList', jobsList)
|
||||||
.factory('DeleteJob', DeleteJob)
|
.factory('DeleteJob', DeleteJob)
|
||||||
.factory('JobStatusToolTip', JobStatusToolTip)
|
|
||||||
.factory('JobsListUpdate', JobsListUpdate)
|
|
||||||
.factory('RelaunchAdhoc', RelaunchAdhoc)
|
|
||||||
.factory('RelaunchInventory', RelaunchInventory)
|
|
||||||
.factory('RelaunchJob', RelaunchJob)
|
|
||||||
.factory('RelaunchPlaybook', RelaunchPlaybook)
|
|
||||||
.factory('RelaunchSCM', RelaunchSCM)
|
|
||||||
.factory('AllJobsList', AllJobsList);
|
.factory('AllJobsList', AllJobsList);
|
||||||
|
|||||||
@@ -6,11 +6,11 @@
|
|||||||
|
|
||||||
export default ['$scope', '$rootScope',
|
export default ['$scope', '$rootScope',
|
||||||
'$stateParams', 'Rest', 'ProcessErrors',
|
'$stateParams', 'Rest', 'ProcessErrors',
|
||||||
'GetBasePath', 'InitiatePlaybookRun', 'Wait', 'TemplateCopyService',
|
'GetBasePath', 'InitiatePlaybookRun', 'Wait',
|
||||||
'$state', 'OrgJobTemplateList', 'OrgJobTemplateDataset', 'QuerySet',
|
'$state', 'OrgJobTemplateList', 'OrgJobTemplateDataset', 'QuerySet',
|
||||||
function($scope, $rootScope,
|
function($scope, $rootScope,
|
||||||
$stateParams, Rest, ProcessErrors,
|
$stateParams, Rest, ProcessErrors,
|
||||||
GetBasePath, InitiatePlaybookRun, Wait, TemplateCopyService,
|
GetBasePath, InitiatePlaybookRun, Wait,
|
||||||
$state, OrgJobTemplateList, Dataset, qs) {
|
$state, OrgJobTemplateList, Dataset, qs) {
|
||||||
|
|
||||||
var list = OrgJobTemplateList,
|
var list = OrgJobTemplateList,
|
||||||
@@ -81,24 +81,24 @@ export default ['$scope', '$rootScope',
|
|||||||
$state.go('jobTemplateSchedules', { id: id });
|
$state.go('jobTemplateSchedules', { id: id });
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.copyTemplate = function(id) {
|
// $scope.copyTemplate = function(id) {
|
||||||
Wait('start');
|
// Wait('start');
|
||||||
TemplateCopyService.get(id)
|
// TemplateCopyService.get(id)
|
||||||
.then((data) => {
|
// .then((data) => {
|
||||||
TemplateCopyService.set(data.results)
|
// TemplateCopyService.set(data.results)
|
||||||
.then((results) => {
|
// .then((results) => {
|
||||||
Wait('stop');
|
// Wait('stop');
|
||||||
if(results.type && results.type === 'job_template') {
|
// if(results.type && results.type === 'job_template') {
|
||||||
$state.go('templates.editJobTemplate', {job_template_id: results.id}, {reload: true});
|
// $state.go('templates.editJobTemplate', {job_template_id: results.id}, {reload: true});
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
})
|
// })
|
||||||
.catch(({data, status}) => {
|
// .catch(({data, status}) => {
|
||||||
ProcessErrors($rootScope, data, status, null, {hdr: 'Error!',
|
// ProcessErrors($rootScope, data, status, null, {hdr: 'Error!',
|
||||||
msg: 'Call failed. Return status: '+ status});
|
// msg: 'Call failed. Return status: '+ status});
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
};
|
// };
|
||||||
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -4,23 +4,79 @@
|
|||||||
* All Rights Reserved
|
* All Rights Reserved
|
||||||
*************************************************/
|
*************************************************/
|
||||||
|
|
||||||
export function PortalModeJobTemplatesController($scope, PortalJobTemplateList, InitiatePlaybookRun, Dataset) {
|
export function PortalModeJobTemplatesController($scope, PortalJobTemplateList, Dataset, $state, PromptService, JobTemplate, ProcessErrors) {
|
||||||
|
|
||||||
var list = PortalJobTemplateList;
|
var list = PortalJobTemplateList;
|
||||||
|
// search init
|
||||||
|
$scope.list = list;
|
||||||
|
$scope[`${list.iterator}_dataset`] = Dataset.data;
|
||||||
|
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
|
||||||
|
|
||||||
init();
|
const jobTemplate = new JobTemplate();
|
||||||
|
|
||||||
function init() {
|
|
||||||
// search init
|
|
||||||
$scope.list = list;
|
|
||||||
$scope[`${list.iterator}_dataset`] = Dataset.data;
|
|
||||||
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.submitJob = function(id) {
|
$scope.submitJob = function(id) {
|
||||||
InitiatePlaybookRun({ scope: $scope, id: id, job_type: 'job_template' });
|
const selectedJobTemplate = jobTemplate.create();
|
||||||
|
const preLaunchPromises = [
|
||||||
|
selectedJobTemplate.getLaunch(id),
|
||||||
|
selectedJobTemplate.optionsLaunch(id),
|
||||||
|
];
|
||||||
|
|
||||||
|
Promise.all(preLaunchPromises)
|
||||||
|
.then(([launchData, launchOptions]) => {
|
||||||
|
if (selectedJobTemplate.canLaunchWithoutPrompt()) {
|
||||||
|
return selectedJobTemplate
|
||||||
|
.postLaunch({ id: id })
|
||||||
|
.then(({ data }) => {
|
||||||
|
$state.go('jobResult', { id: data.job }, { reload: true });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const promptData = {
|
||||||
|
launchConf: launchData.data,
|
||||||
|
launchOptions: launchOptions.data,
|
||||||
|
template: id,
|
||||||
|
templateType: 'job_template',
|
||||||
|
prompts: PromptService.processPromptValues({
|
||||||
|
launchConf: launchData.data,
|
||||||
|
launchOptions: launchOptions.data
|
||||||
|
}),
|
||||||
|
triggerModalOpen: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (launchData.data.survey_enabled) {
|
||||||
|
selectedJobTemplate.getSurveyQuestions(id)
|
||||||
|
.then(({ data }) => {
|
||||||
|
const processed = PromptService.processSurveyQuestions({ surveyQuestions: data.spec });
|
||||||
|
promptData.surveyQuestions = processed.surveyQuestions;
|
||||||
|
$scope.promptData = promptData;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
$scope.promptData = promptData;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.launchJob = () => {
|
||||||
|
const jobLaunchData = PromptService.bundlePromptDataForLaunch($scope.promptData);
|
||||||
|
|
||||||
|
// If the extra_vars dict is empty, we don't want to include it if we didn't prompt for anything.
|
||||||
|
if(_.isEmpty(jobLaunchData.extra_vars) && !($scope.promptData.launchConf.ask_variables_on_launch && $scope.promptData.launchConf.survey_enabled && $scope.promptData.surveyQuestions.length > 0)){
|
||||||
|
delete jobLaunchData.extra_vars;
|
||||||
|
}
|
||||||
|
|
||||||
|
jobTemplate.create().postLaunch({
|
||||||
|
id: $scope.promptData.template,
|
||||||
|
launchData: jobLaunchData
|
||||||
|
})
|
||||||
|
.then((launchRes) => {
|
||||||
|
$state.go('jobResult', { id: launchRes.data.job }, { reload: true });
|
||||||
|
})
|
||||||
|
.catch(({data, status}) => {
|
||||||
|
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to launch job template: ' + status });
|
||||||
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PortalModeJobTemplatesController.$inject = ['$scope','PortalJobTemplateList', 'InitiatePlaybookRun', 'job_templatesDataset'];
|
PortalModeJobTemplatesController.$inject = ['$scope','PortalJobTemplateList', 'job_templatesDataset', '$state', 'PromptService', 'JobTemplateModel', 'ProcessErrors'];
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ export default {
|
|||||||
list: PortalJobTemplateList,
|
list: PortalJobTemplateList,
|
||||||
mode: 'edit'
|
mode: 'edit'
|
||||||
});
|
});
|
||||||
return html;
|
return html + '<prompt prompt-data="promptData" on-finish="launchJob()"></launch>';
|
||||||
},
|
},
|
||||||
controller: PortalModeJobTemplatesController
|
controller: PortalModeJobTemplatesController
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export default
|
export default
|
||||||
function SchedulePost(Rest, ProcessErrors, RRuleToAPI, Wait, $q, Schedule) {
|
function SchedulePost(Rest, ProcessErrors, RRuleToAPI, Wait, $q, Schedule, PromptService) {
|
||||||
return function(params) {
|
return function(params) {
|
||||||
var scope = params.scope,
|
var scope = params.scope,
|
||||||
url = params.url,
|
url = params.url,
|
||||||
@@ -36,57 +36,10 @@ export default
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(promptData) {
|
if(promptData) {
|
||||||
if(promptData.launchConf.survey_enabled){
|
scheduleData = PromptService.bundlePromptDataForSaving({
|
||||||
for (var i=0; i < promptData.surveyQuestions.length; i++){
|
promptData: promptData,
|
||||||
var fld = promptData.surveyQuestions[i].variable;
|
dataToSave: scheduleData
|
||||||
// grab all survey questions that have answers
|
});
|
||||||
if(promptData.surveyQuestions[i].required || (promptData.surveyQuestions[i].required === false && promptData.surveyQuestions[i].model.toString()!=="")) {
|
|
||||||
if(!scheduleData.extra_data) {
|
|
||||||
scheduleData.extra_data = {};
|
|
||||||
}
|
|
||||||
scheduleData.extra_data[fld] = promptData.surveyQuestions[i].model;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(promptData.surveyQuestions[i].required === false && _.isEmpty(promptData.surveyQuestions[i].model)) {
|
|
||||||
switch (promptData.surveyQuestions[i].type) {
|
|
||||||
// for optional text and text-areas, submit a blank string if min length is 0
|
|
||||||
// -- this is confusing, for an explanation see:
|
|
||||||
// http://docs.ansible.com/ansible-tower/latest/html/userguide/job_templates.html#optional-survey-questions
|
|
||||||
//
|
|
||||||
case "text":
|
|
||||||
case "textarea":
|
|
||||||
if (promptData.surveyQuestions[i].min === 0) {
|
|
||||||
scheduleData.extra_data[fld] = "";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(_.has(promptData, 'prompts.jobType.value.value') && _.get(promptData, 'launchConf.ask_job_type_on_launch')) {
|
|
||||||
scheduleData.job_type = promptData.launchConf.defaults.job_type && promptData.launchConf.defaults.job_type === promptData.prompts.jobType.value.value ? null : promptData.prompts.jobType.value.value;
|
|
||||||
}
|
|
||||||
if(_.has(promptData, 'prompts.tags.value') && _.get(promptData, 'launchConf.ask_tags_on_launch')){
|
|
||||||
const templateDefaultJobTags = promptData.launchConf.defaults.job_tags.split(',');
|
|
||||||
scheduleData.job_tags = (_.isEqual(templateDefaultJobTags.sort(), promptData.prompts.tags.value.map(a => a.value).sort())) ? null : promptData.prompts.tags.value.map(a => a.value).join();
|
|
||||||
}
|
|
||||||
if(_.has(promptData, 'prompts.skipTags.value') && _.get(promptData, 'launchConf.ask_skip_tags_on_launch')){
|
|
||||||
const templateDefaultSkipTags = promptData.launchConf.defaults.skip_tags.split(',');
|
|
||||||
scheduleData.skip_tags = (_.isEqual(templateDefaultSkipTags.sort(), promptData.prompts.skipTags.value.map(a => a.value).sort())) ? null : promptData.prompts.skipTags.value.map(a => a.value).join();
|
|
||||||
}
|
|
||||||
if(_.has(promptData, 'prompts.limit.value') && _.get(promptData, 'launchConf.ask_limit_on_launch')){
|
|
||||||
scheduleData.limit = promptData.launchConf.defaults.limit && promptData.launchConf.defaults.limit === promptData.prompts.limit.value ? null : promptData.prompts.limit.value;
|
|
||||||
}
|
|
||||||
if(_.has(promptData, 'prompts.verbosity.value.value') && _.get(promptData, 'launchConf.ask_verbosity_on_launch')){
|
|
||||||
scheduleData.verbosity = promptData.launchConf.defaults.verbosity && promptData.launchConf.defaults.verbosity === promptData.prompts.verbosity.value.value ? null : promptData.prompts.verbosity.value.value;
|
|
||||||
}
|
|
||||||
if(_.has(promptData, 'prompts.inventory.value') && _.get(promptData, 'launchConf.ask_inventory_on_launch')){
|
|
||||||
scheduleData.inventory = promptData.launchConf.defaults.inventory && promptData.launchConf.defaults.inventory.id === promptData.prompts.inventory.value.id ? null : promptData.prompts.inventory.value.id;
|
|
||||||
}
|
|
||||||
if(_.has(promptData, 'prompts.diffMode.value') && _.get(promptData, 'launchConf.ask_diff_mode_on_launch')){
|
|
||||||
scheduleData.diff_mode = promptData.launchConf.defaults.diff_mode && promptData.launchConf.defaults.diff_mode === promptData.prompts.diffMode.value ? null : promptData.prompts.diffMode.value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rest.setUrl(url);
|
Rest.setUrl(url);
|
||||||
@@ -212,5 +165,6 @@ SchedulePost.$inject =
|
|||||||
'RRuleToAPI',
|
'RRuleToAPI',
|
||||||
'Wait',
|
'Wait',
|
||||||
'$q',
|
'$q',
|
||||||
'ScheduleModel'
|
'ScheduleModel',
|
||||||
|
'PromptService'
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -8,7 +8,9 @@
|
|||||||
RESULTS
|
RESULTS
|
||||||
</div>
|
</div>
|
||||||
<div class="StandardOut-actions">
|
<div class="StandardOut-actions">
|
||||||
<button id="relaunch-job-button" class="List-actionButton jobResult-launchButton" data-placement="top" mode="all" ng-click="relaunchJob()" aw-tool-tip="Relaunch using the same parameters" data-original-title="" title=""><i class="icon-launch"></i> </button>
|
<div>
|
||||||
|
<at-relaunch></at-relaunch>
|
||||||
|
</div>
|
||||||
<button id="cancel-job-button" class="List-actionButton List-actionButton--delete jobResult-launchButton" data-placement="top" ng-click="deleteJob()" ng-show="job.status === 'waiting' || job.status === 'running' || job.status === 'pending'" aw-tool-tip="Cancel" data-original-title="" title=""><i class="fa fa-minus-circle"></i> </button>
|
<button id="cancel-job-button" class="List-actionButton List-actionButton--delete jobResult-launchButton" data-placement="top" ng-click="deleteJob()" ng-show="job.status === 'waiting' || job.status === 'running' || job.status === 'pending'" aw-tool-tip="Cancel" data-original-title="" title=""><i class="fa fa-minus-circle"></i> </button>
|
||||||
<button id="delete-job-button" class="List-actionButton List-actionButton--delete jobResult-launchButton" data-placement="top" ng-click="deleteJob()" ng-hide="job.status === 'waiting' || job.status === 'running' || job.status === 'pending' " aw-tool-tip="Delete" data-original-title="" title=""><i class="fa fa-trash-o"></i> </button>
|
<button id="delete-job-button" class="List-actionButton List-actionButton--delete jobResult-launchButton" data-placement="top" ng-click="deleteJob()" ng-hide="job.status === 'waiting' || job.status === 'running' || job.status === 'pending' " aw-tool-tip="Delete" data-original-title="" title=""><i class="fa fa-trash-o"></i> </button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -23,5 +23,14 @@ export default {
|
|||||||
"ad_hoc_command_events": []
|
"ad_hoc_command_events": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
jobData: ['Rest', 'GetBasePath', '$stateParams', function(Rest, GetBasePath, $stateParams) {
|
||||||
|
Rest.setUrl(GetBasePath('base') + 'ad_hoc_commands/' + $stateParams.id + '/');
|
||||||
|
return Rest.get()
|
||||||
|
.then(({data}) => {
|
||||||
|
return data;
|
||||||
|
});
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
RESULTS
|
RESULTS
|
||||||
</div>
|
</div>
|
||||||
<div class="StandardOut-actions">
|
<div class="StandardOut-actions">
|
||||||
<button id="relaunch-job-button" class="List-actionButton jobResult-launchButton" data-placement="top" mode="all" ng-click="relaunchJob()" aw-tool-tip="Relaunch using the same parameters" data-original-title="" title=""><i class="icon-launch"></i> </button>
|
<at-relaunch></at-relaunch>
|
||||||
<button id="cancel-job-button" class="List-actionButton List-actionButton--delete jobResult-launchButton" data-placement="top" ng-click="deleteJob()" ng-show="job.status === 'waiting' || job.status === 'running' || job.status === 'pending'" aw-tool-tip="Cancel" data-original-title="" title=""><i class="fa fa-minus-circle"></i> </button>
|
<button id="cancel-job-button" class="List-actionButton List-actionButton--delete jobResult-launchButton" data-placement="top" ng-click="deleteJob()" ng-show="job.status === 'waiting' || job.status === 'running' || job.status === 'pending'" aw-tool-tip="Cancel" data-original-title="" title=""><i class="fa fa-minus-circle"></i> </button>
|
||||||
<button id="delete-job-button" class="List-actionButton List-actionButton--delete jobResult-launchButton" data-placement="top" ng-click="deleteJob()" ng-hide="job.status === 'waiting' || job.status === 'running' || job.status === 'pending' " aw-tool-tip="Delete" data-original-title="" title=""><i class="fa fa-trash-o"></i> </button>
|
<button id="delete-job-button" class="List-actionButton List-actionButton--delete jobResult-launchButton" data-placement="top" ng-click="deleteJob()" ng-hide="job.status === 'waiting' || job.status === 'running' || job.status === 'pending' " aw-tool-tip="Delete" data-original-title="" title=""><i class="fa fa-trash-o"></i> </button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -25,5 +25,14 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
jobType: 'inventory_updates'
|
jobType: 'inventory_updates'
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
jobData: ['Rest', 'GetBasePath', '$stateParams', function(Rest, GetBasePath, $stateParams) {
|
||||||
|
Rest.setUrl(GetBasePath('base') + 'inventory_updates/' + $stateParams.id + '/');
|
||||||
|
return Rest.get()
|
||||||
|
.then(({data}) => {
|
||||||
|
return data;
|
||||||
|
});
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,5 +23,14 @@ export default {
|
|||||||
"system_job_events": [],
|
"system_job_events": [],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
jobData: ['Rest', 'GetBasePath', '$stateParams', function(Rest, GetBasePath, $stateParams) {
|
||||||
|
Rest.setUrl(GetBasePath('base') + 'system_jobs/' + $stateParams.id + '/');
|
||||||
|
return Rest.get()
|
||||||
|
.then(({data}) => {
|
||||||
|
return data;
|
||||||
|
});
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
RESULTS
|
RESULTS
|
||||||
</div>
|
</div>
|
||||||
<div class="StandardOut-actions">
|
<div class="StandardOut-actions">
|
||||||
<button id="relaunch-job-button" class="List-actionButton jobResult-launchButton" data-placement="top" mode="all" ng-click="relaunchJob()" aw-tool-tip="{{'Relaunch using the same parameters'|translate}}" data-original-title="" title=""><i class="icon-launch"></i> </button>
|
<at-relaunch></at-relaunch>
|
||||||
<button id="cancel-job-button" class="List-actionButton List-actionButton--delete jobResult-launchButton" data-placement="top" ng-click="deleteJob()" ng-show="job.status === 'waiting' || job.status === 'running' || job.status === 'pending'" aw-tool-tip="{{'Cancel'|translate}}" data-original-title="" title=""><i class="fa fa-minus-circle"></i> </button>
|
<button id="cancel-job-button" class="List-actionButton List-actionButton--delete jobResult-launchButton" data-placement="top" ng-click="deleteJob()" ng-show="job.status === 'waiting' || job.status === 'running' || job.status === 'pending'" aw-tool-tip="{{'Cancel'|translate}}" data-original-title="" title=""><i class="fa fa-minus-circle"></i> </button>
|
||||||
<button id="delete-job-button" class="List-actionButton List-actionButton--delete jobResult-launchButton" data-placement="top" ng-click="deleteJob()" ng-hide="job.status === 'waiting' || job.status === 'running' || job.status === 'pending' " aw-tool-tip="{{'Delete'|translate}}" data-original-title="" title=""><i class="fa fa-trash-o"></i> </button>
|
<button id="delete-job-button" class="List-actionButton List-actionButton--delete jobResult-launchButton" data-placement="top" ng-click="deleteJob()" ng-hide="job.status === 'waiting' || job.status === 'running' || job.status === 'pending' " aw-tool-tip="{{'Delete'|translate}}" data-original-title="" title=""><i class="fa fa-trash-o"></i> </button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -25,5 +25,14 @@ export default {
|
|||||||
"project_update_events": [],
|
"project_update_events": [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
jobData: ['Rest', 'GetBasePath', '$stateParams', function(Rest, GetBasePath, $stateParams) {
|
||||||
|
Rest.setUrl(GetBasePath('base') + 'project_updates/' + $stateParams.id + '/');
|
||||||
|
return Rest.get()
|
||||||
|
.then(({data}) => {
|
||||||
|
return data;
|
||||||
|
});
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -131,6 +131,10 @@ standard-out-log {
|
|||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.StandardOut-actions {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
.StandardOut-actionButton {
|
.StandardOut-actionButton {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
|
|||||||
@@ -12,8 +12,9 @@
|
|||||||
|
|
||||||
export function JobStdoutController ($rootScope, $scope, $state, $stateParams,
|
export function JobStdoutController ($rootScope, $scope, $state, $stateParams,
|
||||||
GetBasePath, Rest, ProcessErrors, Empty, GetChoices, LookUpName,
|
GetBasePath, Rest, ProcessErrors, Empty, GetChoices, LookUpName,
|
||||||
ParseTypeChange, ParseVariableString, RelaunchJob, DeleteJob, Wait, i18n,
|
ParseTypeChange, ParseVariableString, DeleteJob, Wait, i18n,
|
||||||
fieldChoices, fieldLabels) {
|
fieldChoices, fieldLabels, Project, Alert, InventorySource,
|
||||||
|
jobData) {
|
||||||
|
|
||||||
var job_id = $stateParams.id,
|
var job_id = $stateParams.id,
|
||||||
jobType = $state.current.data.jobType;
|
jobType = $state.current.data.jobType;
|
||||||
@@ -34,7 +35,12 @@ export function JobStdoutController ($rootScope, $scope, $state, $stateParams,
|
|||||||
|
|
||||||
if (data.status === 'failed' || data.status === 'canceled' || data.status === 'error' || data.status === 'successful') {
|
if (data.status === 'failed' || data.status === 'canceled' || data.status === 'error' || data.status === 'successful') {
|
||||||
// Go out and refresh the job details
|
// Go out and refresh the job details
|
||||||
getjobResults();
|
|
||||||
|
Rest.setUrl(GetBasePath('base') + jobType + '/' + job_id + '/');
|
||||||
|
Rest.get()
|
||||||
|
.then(({data}) => {
|
||||||
|
updateJobObj(data);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -72,149 +78,142 @@ export function JobStdoutController ($rootScope, $scope, $state, $stateParams,
|
|||||||
// Set the parse type so that CodeMirror knows how to display extra params YAML/JSON
|
// Set the parse type so that CodeMirror knows how to display extra params YAML/JSON
|
||||||
$scope.parseType = 'yaml';
|
$scope.parseType = 'yaml';
|
||||||
|
|
||||||
function getjobResults() {
|
function updateJobObj(updatedJobData) {
|
||||||
|
|
||||||
// Go out and get the job details based on the job type. jobType gets defined
|
// Go out and get the job details based on the job type. jobType gets defined
|
||||||
// in the data block of the route declaration for each of the different types
|
// in the data block of the route declaration for each of the different types
|
||||||
// of stdout jobs.
|
// of stdout jobs.
|
||||||
Rest.setUrl(GetBasePath('base') + jobType + '/' + job_id + '/');
|
|
||||||
Rest.get()
|
|
||||||
.then(({data}) => {
|
|
||||||
$scope.job = data;
|
|
||||||
$scope.job_template_name = data.name;
|
|
||||||
$scope.created_by = data.summary_fields.created_by;
|
|
||||||
$scope.project_name = (data.summary_fields.project) ? data.summary_fields.project.name : '';
|
|
||||||
$scope.inventory_name = (data.summary_fields.inventory) ? data.summary_fields.inventory.name : '';
|
|
||||||
$scope.job_template_url = '/#/templates/' + data.unified_job_template;
|
|
||||||
if($scope.inventory_name && data.inventory && data.summary_fields.inventory && data.summary_fields.inventory.kind) {
|
|
||||||
if(data.summary_fields.inventory.kind === '') {
|
|
||||||
$scope.inventory_url = '/#/inventories/inventory' + data.inventory;
|
|
||||||
}
|
|
||||||
else if(data.summary_fields.inventory.kind === 'smart') {
|
|
||||||
$scope.inventory_url = '/#/inventories/smart_inventory' + data.inventory;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$scope.inventory_url = '';
|
|
||||||
}
|
|
||||||
$scope.project_url = ($scope.project_name && data.project) ? '/#/projects/' + data.project : '';
|
|
||||||
$scope.credential_name = (data.summary_fields.credential) ? data.summary_fields.credential.name : '';
|
|
||||||
$scope.credential_url = (data.credential) ? '/#/credentials/' + data.credential : '';
|
|
||||||
$scope.cloud_credential_url = (data.cloud_credential) ? '/#/credentials/' + data.cloud_credential : '';
|
|
||||||
if(data.summary_fields && data.summary_fields.source_workflow_job &&
|
|
||||||
data.summary_fields.source_workflow_job.id){
|
|
||||||
$scope.workflow_result_link = `/#/workflows/${data.summary_fields.source_workflow_job.id}`;
|
|
||||||
}
|
|
||||||
$scope.playbook = data.playbook;
|
|
||||||
$scope.credential = data.credential;
|
|
||||||
$scope.cloud_credential = data.cloud_credential;
|
|
||||||
$scope.forks = data.forks;
|
|
||||||
$scope.limit = data.limit;
|
|
||||||
$scope.verbosity = data.verbosity;
|
|
||||||
$scope.job_tags = data.job_tags;
|
|
||||||
$scope.job.module_name = data.module_name;
|
|
||||||
if (data.extra_vars) {
|
|
||||||
$scope.variables = ParseVariableString(data.extra_vars);
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.$on('getInventorySource', function(e, d) {
|
$scope.job = updatedJobData;
|
||||||
$scope.inv_manage_group_link = '/#/inventories/inventory/' + d.inventory + '/inventory_sources/edit/' + d.id;
|
$scope.job_template_name = updatedJobData.name;
|
||||||
|
$scope.created_by = updatedJobData.summary_fields.created_by;
|
||||||
|
$scope.project_name = (updatedJobData.summary_fields.project) ? updatedJobData.summary_fields.project.name : '';
|
||||||
|
$scope.inventory_name = (updatedJobData.summary_fields.inventory) ? updatedJobData.summary_fields.inventory.name : '';
|
||||||
|
$scope.job_template_url = '/#/templates/' + updatedJobData.unified_job_template;
|
||||||
|
if($scope.inventory_name && updatedJobData.inventory && updatedJobData.summary_fields.inventory && updatedJobData.summary_fields.inventory.kind) {
|
||||||
|
if(updatedJobData.summary_fields.inventory.kind === '') {
|
||||||
|
$scope.inventory_url = '/#/inventories/inventory' + updatedJobData.inventory;
|
||||||
|
}
|
||||||
|
else if(updatedJobData.summary_fields.inventory.kind === 'smart') {
|
||||||
|
$scope.inventory_url = '/#/inventories/smart_inventory' + updatedJobData.inventory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$scope.inventory_url = '';
|
||||||
|
}
|
||||||
|
$scope.project_url = ($scope.project_name && updatedJobData.project) ? '/#/projects/' + updatedJobData.project : '';
|
||||||
|
$scope.credential_name = (updatedJobData.summary_fields.credential) ? updatedJobData.summary_fields.credential.name : '';
|
||||||
|
$scope.credential_url = (updatedJobData.credential) ? '/#/credentials/' + updatedJobData.credential : '';
|
||||||
|
$scope.cloud_credential_url = (updatedJobData.cloud_credential) ? '/#/credentials/' + updatedJobData.cloud_credential : '';
|
||||||
|
if(updatedJobData.summary_fields && updatedJobData.summary_fields.source_workflow_job &&
|
||||||
|
updatedJobData.summary_fields.source_workflow_job.id){
|
||||||
|
$scope.workflow_result_link = `/#/workflows/${updatedJobData.summary_fields.source_workflow_job.id}`;
|
||||||
|
}
|
||||||
|
$scope.playbook = updatedJobData.playbook;
|
||||||
|
$scope.credential = updatedJobData.credential;
|
||||||
|
$scope.cloud_credential = updatedJobData.cloud_credential;
|
||||||
|
$scope.forks = updatedJobData.forks;
|
||||||
|
$scope.limit = updatedJobData.limit;
|
||||||
|
$scope.verbosity = updatedJobData.verbosity;
|
||||||
|
$scope.job_tags = updatedJobData.job_tags;
|
||||||
|
$scope.job.module_name = updatedJobData.module_name;
|
||||||
|
if (updatedJobData.extra_vars) {
|
||||||
|
$scope.variables = ParseVariableString(updatedJobData.extra_vars);
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.$on('getInventorySource', function(e, d) {
|
||||||
|
$scope.inv_manage_group_link = '/#/inventories/inventory/' + d.inventory + '/inventory_sources/edit/' + d.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
// If we have a source then we have to go get the source choices from the server
|
||||||
|
if (!Empty(updatedJobData.source)) {
|
||||||
|
if ($scope.removeChoicesReady) {
|
||||||
|
$scope.removeChoicesReady();
|
||||||
|
}
|
||||||
|
$scope.removeChoicesReady = $scope.$on('ChoicesReady', function() {
|
||||||
|
$scope.source_choices.every(function(e) {
|
||||||
|
if (e.value === updatedJobData.source) {
|
||||||
|
$scope.source = e.label;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// If we have a source then we have to go get the source choices from the server
|
|
||||||
if (!Empty(data.source)) {
|
|
||||||
if ($scope.removeChoicesReady) {
|
|
||||||
$scope.removeChoicesReady();
|
|
||||||
}
|
|
||||||
$scope.removeChoicesReady = $scope.$on('ChoicesReady', function() {
|
|
||||||
$scope.source_choices.every(function(e) {
|
|
||||||
if (e.value === data.source) {
|
|
||||||
$scope.source = e.label;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// GetChoices can be found in the helper: Utilities.js
|
|
||||||
// It attaches the source choices to $scope.source_choices.
|
|
||||||
// Then, when the callback is fired, $scope.source is bound
|
|
||||||
// to the corresponding label.
|
|
||||||
GetChoices({
|
|
||||||
scope: $scope,
|
|
||||||
url: GetBasePath('inventory_sources'),
|
|
||||||
field: 'source',
|
|
||||||
variable: 'source_choices',
|
|
||||||
choice_name: 'choices',
|
|
||||||
callback: 'ChoicesReady'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// LookUpName can be found in the lookup-name.factory
|
|
||||||
// It attaches the name that it gets (based on the url)
|
|
||||||
// to the $scope variable defined by the attribute scope_var.
|
|
||||||
if (!Empty(data.credential)) {
|
|
||||||
LookUpName({
|
|
||||||
scope: $scope,
|
|
||||||
scope_var: 'credential',
|
|
||||||
url: GetBasePath('credentials') + data.credential + '/',
|
|
||||||
ignore_403: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Empty(data.inventory)) {
|
|
||||||
LookUpName({
|
|
||||||
scope: $scope,
|
|
||||||
scope_var: 'inventory',
|
|
||||||
url: GetBasePath('inventory') + data.inventory + '/'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Empty(data.project)) {
|
|
||||||
LookUpName({
|
|
||||||
scope: $scope,
|
|
||||||
scope_var: 'project',
|
|
||||||
url: GetBasePath('projects') + data.project + '/'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Empty(data.cloud_credential)) {
|
|
||||||
LookUpName({
|
|
||||||
scope: $scope,
|
|
||||||
scope_var: 'cloud_credential',
|
|
||||||
url: GetBasePath('credentials') + data.cloud_credential + '/',
|
|
||||||
ignore_403: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Empty(data.inventory_source)) {
|
|
||||||
LookUpName({
|
|
||||||
scope: $scope,
|
|
||||||
scope_var: 'inventory_source',
|
|
||||||
url: GetBasePath('inventory_sources') + data.inventory_source + '/',
|
|
||||||
callback: 'getInventorySource'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.extra_vars) {
|
|
||||||
ParseTypeChange({
|
|
||||||
scope: $scope,
|
|
||||||
field_id: 'pre-formatted-variables',
|
|
||||||
readOnly: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the job isn't running we want to clear out the interval that goes out and checks for stdout updates.
|
|
||||||
// This interval is defined in the standard out log directive controller.
|
|
||||||
if (data.status === 'successful' || data.status === 'failed' || data.status === 'error' || data.status === 'canceled') {
|
|
||||||
if ($rootScope.jobStdOutInterval) {
|
|
||||||
window.clearInterval($rootScope.jobStdOutInterval);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(({data, status}) => {
|
|
||||||
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
|
||||||
msg: 'Failed to retrieve job: ' + job_id + '. GET returned: ' + status });
|
|
||||||
});
|
});
|
||||||
|
// GetChoices can be found in the helper: Utilities.js
|
||||||
|
// It attaches the source choices to $scope.source_choices.
|
||||||
|
// Then, when the callback is fired, $scope.source is bound
|
||||||
|
// to the corresponding label.
|
||||||
|
GetChoices({
|
||||||
|
scope: $scope,
|
||||||
|
url: GetBasePath('inventory_sources'),
|
||||||
|
field: 'source',
|
||||||
|
variable: 'source_choices',
|
||||||
|
choice_name: 'choices',
|
||||||
|
callback: 'ChoicesReady'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// LookUpName can be found in the lookup-name.factory
|
||||||
|
// It attaches the name that it gets (based on the url)
|
||||||
|
// to the $scope variable defined by the attribute scope_var.
|
||||||
|
if (!Empty(updatedJobData.credential)) {
|
||||||
|
LookUpName({
|
||||||
|
scope: $scope,
|
||||||
|
scope_var: 'credential',
|
||||||
|
url: GetBasePath('credentials') + updatedJobData.credential + '/',
|
||||||
|
ignore_403: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Empty(updatedJobData.inventory)) {
|
||||||
|
LookUpName({
|
||||||
|
scope: $scope,
|
||||||
|
scope_var: 'inventory',
|
||||||
|
url: GetBasePath('inventory') + updatedJobData.inventory + '/'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Empty(updatedJobData.project)) {
|
||||||
|
LookUpName({
|
||||||
|
scope: $scope,
|
||||||
|
scope_var: 'project',
|
||||||
|
url: GetBasePath('projects') + updatedJobData.project + '/'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Empty(updatedJobData.cloud_credential)) {
|
||||||
|
LookUpName({
|
||||||
|
scope: $scope,
|
||||||
|
scope_var: 'cloud_credential',
|
||||||
|
url: GetBasePath('credentials') + updatedJobData.cloud_credential + '/',
|
||||||
|
ignore_403: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Empty(updatedJobData.inventory_source)) {
|
||||||
|
LookUpName({
|
||||||
|
scope: $scope,
|
||||||
|
scope_var: 'inventory_source',
|
||||||
|
url: GetBasePath('inventory_sources') + updatedJobData.inventory_source + '/',
|
||||||
|
callback: 'getInventorySource'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updatedJobData.extra_vars) {
|
||||||
|
ParseTypeChange({
|
||||||
|
scope: $scope,
|
||||||
|
field_id: 'pre-formatted-variables',
|
||||||
|
readOnly: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the job isn't running we want to clear out the interval that goes out and checks for stdout updates.
|
||||||
|
// This interval is defined in the standard out log directive controller.
|
||||||
|
if (updatedJobData.status === 'successful' || updatedJobData.status === 'failed' || updatedJobData.status === 'error' || updatedJobData.status === 'canceled') {
|
||||||
|
if ($rootScope.jobStdOutInterval) {
|
||||||
|
window.clearInterval($rootScope.jobStdOutInterval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,26 +254,13 @@ export function JobStdoutController ($rootScope, $scope, $state, $stateParams,
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.relaunchJob = function() {
|
updateJobObj(jobData);
|
||||||
var typeId, job = $scope.job;
|
|
||||||
if (job.type === 'inventory_update') {
|
|
||||||
typeId = job.inventory_source;
|
|
||||||
}
|
|
||||||
else if (job.type === 'project_update') {
|
|
||||||
typeId = job.project;
|
|
||||||
}
|
|
||||||
else if (job.type === 'job' || job.type === "system_job" || job.type === 'ad_hoc_command') {
|
|
||||||
typeId = job.id;
|
|
||||||
}
|
|
||||||
RelaunchJob({ scope: $scope, id: typeId, type: job.type, name: job.name });
|
|
||||||
};
|
|
||||||
|
|
||||||
getjobResults();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JobStdoutController.$inject = [ '$rootScope', '$scope', '$state',
|
JobStdoutController.$inject = [ '$rootScope', '$scope', '$state',
|
||||||
'$stateParams', 'GetBasePath', 'Rest', 'ProcessErrors',
|
'$stateParams', 'GetBasePath', 'Rest', 'ProcessErrors',
|
||||||
'Empty', 'GetChoices', 'LookUpName', 'ParseTypeChange',
|
'Empty', 'GetChoices', 'LookUpName', 'ParseTypeChange',
|
||||||
'ParseVariableString', 'RelaunchJob', 'DeleteJob', 'Wait', 'i18n',
|
'ParseVariableString', 'DeleteJob', 'Wait', 'i18n',
|
||||||
'fieldChoices', 'fieldLabels'];
|
'fieldChoices', 'fieldLabels', 'ProjectModel', 'Alert', 'InventorySourceModel',
|
||||||
|
'jobData'];
|
||||||
|
|||||||
@@ -72,12 +72,9 @@ export default ['i18n', function(i18n) {
|
|||||||
columnClass: 'col-lg-2 col-md-2 col-sm-3 col-xs-4',
|
columnClass: 'col-lg-2 col-md-2 col-sm-3 col-xs-4',
|
||||||
|
|
||||||
submit: {
|
submit: {
|
||||||
icon: 'icon-rocket',
|
ngShow: "!completed_job.type == 'system_job' || completed_job.summary_fields.user_capabilities.start",
|
||||||
mode: 'all',
|
// uses the at-relaunch directive
|
||||||
ngClick: 'relaunchJob($event, completed_job.id)',
|
relaunch: true
|
||||||
awToolTip: i18n._('Relaunch using the same parameters'),
|
|
||||||
dataPlacement: 'top',
|
|
||||||
ngShow: "!completed_job.type == 'system_job' || completed_job.summary_fields.user_capabilities.start"
|
|
||||||
},
|
},
|
||||||
"delete": {
|
"delete": {
|
||||||
mode: 'all',
|
mode: 'all',
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export default
|
|||||||
'Rest', 'Alert', 'ProcessErrors', 'GetBasePath', 'md5Setup',
|
'Rest', 'Alert', 'ProcessErrors', 'GetBasePath', 'md5Setup',
|
||||||
'ParseTypeChange', 'Wait', 'selectedLabels', 'i18n',
|
'ParseTypeChange', 'Wait', 'selectedLabels', 'i18n',
|
||||||
'Empty', 'Prompt', 'ToJSON', 'GetChoices', 'CallbackHelpInit',
|
'Empty', 'Prompt', 'ToJSON', 'GetChoices', 'CallbackHelpInit',
|
||||||
'InitiatePlaybookRun' , 'initSurvey', '$state', 'CreateSelect2',
|
'initSurvey', '$state', 'CreateSelect2',
|
||||||
'ToggleNotification','$q', 'InstanceGroupsService', 'InstanceGroupsData',
|
'ToggleNotification','$q', 'InstanceGroupsService', 'InstanceGroupsData',
|
||||||
'MultiCredentialService', 'availableLabels', 'projectGetPermissionDenied',
|
'MultiCredentialService', 'availableLabels', 'projectGetPermissionDenied',
|
||||||
'inventoryGetPermissionDenied', 'jobTemplateData', 'ParseVariableString', 'ConfigData',
|
'inventoryGetPermissionDenied', 'jobTemplateData', 'ParseVariableString', 'ConfigData',
|
||||||
@@ -26,7 +26,7 @@ export default
|
|||||||
ProcessErrors, GetBasePath, md5Setup,
|
ProcessErrors, GetBasePath, md5Setup,
|
||||||
ParseTypeChange, Wait, selectedLabels, i18n,
|
ParseTypeChange, Wait, selectedLabels, i18n,
|
||||||
Empty, Prompt, ToJSON, GetChoices, CallbackHelpInit,
|
Empty, Prompt, ToJSON, GetChoices, CallbackHelpInit,
|
||||||
InitiatePlaybookRun, SurveyControllerInit, $state, CreateSelect2,
|
SurveyControllerInit, $state, CreateSelect2,
|
||||||
ToggleNotification, $q, InstanceGroupsService, InstanceGroupsData,
|
ToggleNotification, $q, InstanceGroupsService, InstanceGroupsData,
|
||||||
MultiCredentialService, availableLabels, projectGetPermissionDenied,
|
MultiCredentialService, availableLabels, projectGetPermissionDenied,
|
||||||
inventoryGetPermissionDenied, jobTemplateData, ParseVariableString, ConfigData
|
inventoryGetPermissionDenied, jobTemplateData, ParseVariableString, ConfigData
|
||||||
@@ -718,50 +718,5 @@ export default
|
|||||||
$scope.formCancel = function () {
|
$scope.formCancel = function () {
|
||||||
$state.go('templates');
|
$state.go('templates');
|
||||||
};
|
};
|
||||||
|
|
||||||
// Related set: Add button
|
|
||||||
$scope.add = function (set) {
|
|
||||||
$rootScope.flashMessage = null;
|
|
||||||
$location.path('/' + base + '/' + $stateParams.job_template_id + '/' + set);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Related set: Edit button
|
|
||||||
$scope.edit = function (set, id) {
|
|
||||||
$rootScope.flashMessage = null;
|
|
||||||
$location.path('/' + set + '/' + id);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Launch a job using the selected template
|
|
||||||
$scope.launch = function() {
|
|
||||||
|
|
||||||
if ($scope.removePromptForSurvey) {
|
|
||||||
$scope.removePromptForSurvey();
|
|
||||||
}
|
|
||||||
$scope.removePromptForSurvey = $scope.$on('PromptForSurvey', function() {
|
|
||||||
var action = function () {
|
|
||||||
// $scope.$emit("GatherFormFields");
|
|
||||||
Wait('start');
|
|
||||||
$('#prompt-modal').modal('hide');
|
|
||||||
$scope.addSurvey();
|
|
||||||
|
|
||||||
};
|
|
||||||
Prompt({
|
|
||||||
hdr: 'Incomplete Survey',
|
|
||||||
body: '<div class="Prompt-bodyQuery">Do you want to create a survey before proceeding?</div>',
|
|
||||||
action: action
|
|
||||||
});
|
|
||||||
});
|
|
||||||
if($scope.survey_enabled === true && $scope.survey_exists!==true){
|
|
||||||
$scope.$emit("PromptForSurvey");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
InitiatePlaybookRun({
|
|
||||||
scope: $scope,
|
|
||||||
id: id,
|
|
||||||
job_type: 'job_template'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -65,37 +65,30 @@ export default [ 'Rest', 'GetBasePath', 'ProcessErrors', 'CredentialTypeModel',
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vm.promptData.prompts.credentials.passwordsNeededToStart = vm.promptData.launchConf.passwords_needed_to_start;
|
|
||||||
vm.promptData.prompts.credentials.passwords = {};
|
vm.promptData.prompts.credentials.passwords = {};
|
||||||
|
|
||||||
vm.promptData.prompts.credentials.value.forEach((credential) => {
|
vm.promptData.launchConf.passwords_needed_to_start.forEach((passwordNeeded) => {
|
||||||
if (credential.passwords_needed && credential.passwords_needed.length > 0) {
|
if(passwordNeeded === "ssh_password") {
|
||||||
credential.passwords_needed.forEach(passwordNeeded => {
|
vm.promptData.prompts.credentials.passwords.ssh = {};
|
||||||
let credPassObj = {
|
}
|
||||||
id: credential.id,
|
if(passwordNeeded === "become_password") {
|
||||||
name: credential.name
|
vm.promptData.prompts.credentials.passwords.become = {};
|
||||||
};
|
}
|
||||||
|
if(passwordNeeded === "ssh_key_unlock") {
|
||||||
|
vm.promptData.prompts.credentials.passwords.ssh_key_unlock = {};
|
||||||
|
}
|
||||||
|
if(passwordNeeded.startsWith("vault_password")) {
|
||||||
|
let vault_id;
|
||||||
|
if(passwordNeeded.includes('.')) {
|
||||||
|
vault_id = passwordNeeded.split(/\.(.+)/)[1];
|
||||||
|
}
|
||||||
|
|
||||||
if(passwordNeeded === "ssh_password") {
|
if(!vm.promptData.prompts.credentials.passwords.vault) {
|
||||||
vm.promptData.prompts.credentials.passwords.ssh = credPassObj;
|
vm.promptData.prompts.credentials.passwords.vault = [];
|
||||||
}
|
}
|
||||||
if(passwordNeeded === "become_password") {
|
|
||||||
vm.promptData.prompts.credentials.passwords.become = credPassObj;
|
|
||||||
}
|
|
||||||
if(passwordNeeded === "ssh_key_unlock") {
|
|
||||||
vm.promptData.prompts.credentials.passwords.ssh_key_unlock = credPassObj;
|
|
||||||
}
|
|
||||||
if(passwordNeeded.startsWith("vault_password")) {
|
|
||||||
if(passwordNeeded.includes('.')) {
|
|
||||||
credPassObj.vault_id = passwordNeeded.split(/\.(.+)/)[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!vm.promptData.prompts.credentials.passwords.vault) {
|
vm.promptData.prompts.credentials.passwords.vault.push({
|
||||||
vm.promptData.prompts.credentials.passwords.vault = [];
|
vault_id: vault_id
|
||||||
}
|
|
||||||
|
|
||||||
vm.promptData.prompts.credentials.passwords.vault.push(credPassObj);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
function PromptService (Empty, $filter) {
|
function PromptService (Empty, $filter) {
|
||||||
|
|
||||||
this.processPromptValues = (params) => {
|
this.processPromptValues = (params) => {
|
||||||
let prompts = {
|
const prompts = {
|
||||||
credentials: {},
|
credentials: {},
|
||||||
inventory: {},
|
inventory: {},
|
||||||
variables: {},
|
variables: {},
|
||||||
@@ -16,10 +16,23 @@ function PromptService (Empty, $filter) {
|
|||||||
prompts.credentials.value = _.has(params, 'launchConf.defaults.credentials') ? _.cloneDeep(params.launchConf.defaults.credentials) : [];
|
prompts.credentials.value = _.has(params, 'launchConf.defaults.credentials') ? _.cloneDeep(params.launchConf.defaults.credentials) : [];
|
||||||
prompts.inventory.value = _.has(params, 'currentValues.summary_fields.inventory') ? params.currentValues.summary_fields.inventory : (_.has(params, 'launchConf.defaults.inventory') ? params.launchConf.defaults.inventory : null);
|
prompts.inventory.value = _.has(params, 'currentValues.summary_fields.inventory') ? params.currentValues.summary_fields.inventory : (_.has(params, 'launchConf.defaults.inventory') ? params.launchConf.defaults.inventory : null);
|
||||||
|
|
||||||
let skipTags = _.has(params, 'currentValues.skip_tags') && params.currentValues.skip_tags ? params.currentValues.skip_tags : (_.has(params, 'launchConf.defaults.skip_tags') ? params.launchConf.defaults.skip_tags : "");
|
const skipTags = _.has(params, 'currentValues.skip_tags') && params.currentValues.skip_tags ? params.currentValues.skip_tags : (_.has(params, 'launchConf.defaults.skip_tags') ? params.launchConf.defaults.skip_tags : "");
|
||||||
let jobTags = _.has(params, 'currentValues.job_tags') && params.currentValues.job_tags ? params.currentValues.job_tags : (_.has(params, 'launchConf.defaults.job_tags') ? params.launchConf.defaults.job_tags : "");
|
const jobTags = _.has(params, 'currentValues.job_tags') && params.currentValues.job_tags ? params.currentValues.job_tags : (_.has(params, 'launchConf.defaults.job_tags') ? params.launchConf.defaults.job_tags : "");
|
||||||
|
|
||||||
prompts.variables.value = _.has(params, 'launchConf.defaults.extra_vars') && params.launchConf.defaults.extra_vars !== "" ? params.launchConf.defaults.extra_vars : "---";
|
let extraVars = '';
|
||||||
|
|
||||||
|
const hasCurrentExtraVars = _.get(params, 'currentValues.extra_data'),
|
||||||
|
hasDefaultExtraVars = _.get(params, 'launchConf.defaults.extra_vars');
|
||||||
|
|
||||||
|
if(hasCurrentExtraVars && hasDefaultExtraVars) {
|
||||||
|
extraVars = _.merge(jsyaml.safeLoad(params.launchConf.defaults.extra_vars), params.currentValues.extra_data);
|
||||||
|
} else if(hasCurrentExtraVars) {
|
||||||
|
extraVars = params.currentValues.extra_data;
|
||||||
|
} else if(hasDefaultExtraVars) {
|
||||||
|
extraVars = jsyaml.safeLoad(params.launchConf.defaults.extra_vars);
|
||||||
|
}
|
||||||
|
|
||||||
|
prompts.variables.value = extraVars && extraVars !== '' ? '---\n' + jsyaml.safeDump(extraVars) : '---\n';
|
||||||
prompts.verbosity.choices = _.get(params, 'launchOptions.actions.POST.verbosity.choices', []).map(c => ({label: c[1], value: c[0]}));
|
prompts.verbosity.choices = _.get(params, 'launchOptions.actions.POST.verbosity.choices', []).map(c => ({label: c[1], value: c[0]}));
|
||||||
prompts.verbosity.value = _.has(params, 'currentValues.verbosity') && params.currentValues.verbosity ? _.find(prompts.verbosity.choices, item => item.value === params.currentValues.verbosity) : _.find(prompts.verbosity.choices, item => item.value === params.launchConf.defaults.verbosity);
|
prompts.verbosity.value = _.has(params, 'currentValues.verbosity') && params.currentValues.verbosity ? _.find(prompts.verbosity.choices, item => item.value === params.currentValues.verbosity) : _.find(prompts.verbosity.choices, item => item.value === params.launchConf.defaults.verbosity);
|
||||||
prompts.jobType.choices = _.get(params, 'launchOptions.actions.POST.job_type.choices', []).map(c => ({label: c[1], value: c[0]}));
|
prompts.jobType.choices = _.get(params, 'launchOptions.actions.POST.job_type.choices', []).map(c => ({label: c[1], value: c[0]}));
|
||||||
@@ -27,7 +40,7 @@ function PromptService (Empty, $filter) {
|
|||||||
prompts.limit.value = _.has(params, 'currentValues.limit') && params.currentValues.limit ? params.currentValues.limit : (_.has(params, 'launchConf.defaults.limit') ? params.launchConf.defaults.limit : "");
|
prompts.limit.value = _.has(params, 'currentValues.limit') && params.currentValues.limit ? params.currentValues.limit : (_.has(params, 'launchConf.defaults.limit') ? params.launchConf.defaults.limit : "");
|
||||||
prompts.tags.options = prompts.tags.value = (jobTags && jobTags !== "") ? jobTags.split(',').map((i) => ({name: i, label: i, value: i})) : [];
|
prompts.tags.options = prompts.tags.value = (jobTags && jobTags !== "") ? jobTags.split(',').map((i) => ({name: i, label: i, value: i})) : [];
|
||||||
prompts.skipTags.options = prompts.skipTags.value = (skipTags && skipTags !== "") ? skipTags.split(',').map((i) => ({name: i, label: i, value: i})) : [];
|
prompts.skipTags.options = prompts.skipTags.value = (skipTags && skipTags !== "") ? skipTags.split(',').map((i) => ({name: i, label: i, value: i})) : [];
|
||||||
prompts.diffMode.value = _.has(params, 'currentValues.diff_mode') && typeof params.currentValues.diff_mode === 'boolean' ? params.currentValues.diff_mode : (_.has(params, 'launchConf.defaults.diff_mode') ? params.launchConf.defaults.diff_mode : false);
|
prompts.diffMode.value = _.has(params, 'currentValues.diff_mode') && typeof params.currentValues.diff_mode === 'boolean' ? params.currentValues.diff_mode : (_.has(params, 'launchConf.defaults.diff_mode') ? params.launchConf.defaults.diff_mode : null);
|
||||||
|
|
||||||
return prompts;
|
return prompts;
|
||||||
};
|
};
|
||||||
@@ -117,6 +130,144 @@ function PromptService (Empty, $filter) {
|
|||||||
missingSurveyValue: missingSurveyValue
|
missingSurveyValue: missingSurveyValue
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.bundlePromptDataForLaunch = (promptData) => {
|
||||||
|
const launchData = {
|
||||||
|
extra_vars: promptData.extraVars
|
||||||
|
};
|
||||||
|
|
||||||
|
if (promptData.launchConf.ask_tags_on_launch){
|
||||||
|
launchData.job_tags = promptData.prompts.tags.value.map(a => a.value).join();
|
||||||
|
}
|
||||||
|
if (promptData.launchConf.ask_skip_tags_on_launch){
|
||||||
|
launchData.skip_tags = promptData.prompts.skipTags.value.map(a => a.value).join();
|
||||||
|
}
|
||||||
|
if (promptData.launchConf.ask_limit_on_launch && _.has(promptData, 'prompts.limit.value')){
|
||||||
|
launchData.limit = promptData.prompts.limit.value;
|
||||||
|
}
|
||||||
|
if (promptData.launchConf.ask_job_type_on_launch && _.has(promptData, 'prompts.jobType.value.value')) {
|
||||||
|
launchData.job_type = promptData.prompts.jobType.value.value;
|
||||||
|
}
|
||||||
|
if (promptData.launchConf.ask_verbosity_on_launch && _.has(promptData, 'prompts.verbosity.value.value')) {
|
||||||
|
launchData.verbosity = promptData.prompts.verbosity.value.value;
|
||||||
|
}
|
||||||
|
if (promptData.launchConf.ask_inventory_on_launch && !Empty(promptData.prompts.inventory.value.id)){
|
||||||
|
launchData.inventory_id = promptData.prompts.inventory.value.id;
|
||||||
|
}
|
||||||
|
if (promptData.launchConf.ask_credential_on_launch){
|
||||||
|
launchData.credentials = [];
|
||||||
|
promptData.prompts.credentials.value.forEach((credential) => {
|
||||||
|
launchData.credentials.push(credential.id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (promptData.launchConf.ask_diff_mode_on_launch && _.has(promptData, 'prompts.diffMode.value')) {
|
||||||
|
launchData.diff_mode = promptData.prompts.diffMode.value;
|
||||||
|
}
|
||||||
|
if (promptData.prompts.credentials.passwords) {
|
||||||
|
_.forOwn(promptData.prompts.credentials.passwords, (val, key) => {
|
||||||
|
if (!launchData.credential_passwords) {
|
||||||
|
launchData.credential_passwords = {};
|
||||||
|
}
|
||||||
|
if (key === "ssh_key_unlock") {
|
||||||
|
launchData.credential_passwords.ssh_key_unlock = val.value;
|
||||||
|
} else if (key !== "vault") {
|
||||||
|
launchData.credential_passwords[`${key}_password`] = val.value;
|
||||||
|
} else {
|
||||||
|
_.each(val, (vaultCred) => {
|
||||||
|
launchData.credential_passwords[vaultCred.vault_id ? `${key}_password.${vaultCred.vault_id}` : `${key}_password`] = vaultCred.value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return launchData;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.bundlePromptDataForRelaunch = (promptData) => {
|
||||||
|
const launchData = {};
|
||||||
|
|
||||||
|
if(promptData.relaunchHostType) {
|
||||||
|
launchData.hosts = promptData.relaunchHostType;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (promptData.prompts.credentials.passwords) {
|
||||||
|
_.forOwn(promptData.prompts.credentials.passwords, (val, key) => {
|
||||||
|
if (!launchData.credential_passwords) {
|
||||||
|
launchData.credential_passwords = {};
|
||||||
|
}
|
||||||
|
if (key === "ssh_key_unlock") {
|
||||||
|
launchData.credential_passwords.ssh_key_unlock = val.value;
|
||||||
|
} else if (key !== "vault") {
|
||||||
|
launchData.credential_passwords[`${key}_password`] = val.value;
|
||||||
|
} else {
|
||||||
|
_.each(val, (vaultCred) => {
|
||||||
|
launchData.credential_passwords[vaultCred.vault_id ? `${key}_password.${vaultCred.vault_id}` : `${key}_password`] = vaultCred.value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return launchData;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.bundlePromptDataForSaving = (params) => {
|
||||||
|
|
||||||
|
const promptDataToSave = params.dataToSave ? params.dataToSave : {};
|
||||||
|
|
||||||
|
if(params.promptData.launchConf.survey_enabled){
|
||||||
|
for (var i=0; i < params.promptData.surveyQuestions.length; i++){
|
||||||
|
var fld = params.promptData.surveyQuestions[i].variable;
|
||||||
|
// grab all survey questions that have answers
|
||||||
|
if(params.promptData.surveyQuestions[i].required || (params.promptData.surveyQuestions[i].required === false && params.promptData.surveyQuestions[i].model.toString()!=="")) {
|
||||||
|
if(!promptDataToSave.extra_data) {
|
||||||
|
promptDataToSave.extra_data = {};
|
||||||
|
}
|
||||||
|
promptDataToSave.extra_data[fld] = params.promptData.surveyQuestions[i].model;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(params.promptData.surveyQuestions[i].required === false && _.isEmpty(params.promptData.surveyQuestions[i].model)) {
|
||||||
|
switch (params.promptData.surveyQuestions[i].type) {
|
||||||
|
// for optional text and text-areas, submit a blank string if min length is 0
|
||||||
|
// -- this is confusing, for an explanation see:
|
||||||
|
// http://docs.ansible.com/ansible-tower/latest/html/userguide/job_templates.html#optional-survey-questions
|
||||||
|
//
|
||||||
|
case "text":
|
||||||
|
case "textarea":
|
||||||
|
if (params.promptData.surveyQuestions[i].min === 0) {
|
||||||
|
promptDataToSave.extra_data[fld] = "";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_.has(params, 'promptData.prompts.jobType.value.value') && _.get(params, 'promptData.launchConf.ask_job_type_on_launch')) {
|
||||||
|
promptDataToSave.job_type = params.promptData.launchConf.defaults.job_type && params.promptData.launchConf.defaults.job_type === params.promptData.prompts.jobType.value.value ? null : params.promptData.prompts.jobType.value.value;
|
||||||
|
}
|
||||||
|
if(_.has(params, 'promptData.prompts.tags.value') && _.get(params, 'promptData.launchConf.ask_tags_on_launch')){
|
||||||
|
const templateDefaultJobTags = params.promptData.launchConf.defaults.job_tags.split(',');
|
||||||
|
promptDataToSave.job_tags = (_.isEqual(templateDefaultJobTags.sort(), params.promptData.prompts.tags.value.map(a => a.value).sort())) ? null : params.promptData.prompts.tags.value.map(a => a.value).join();
|
||||||
|
}
|
||||||
|
if(_.has(params, 'promptData.prompts.skipTags.value') && _.get(params, 'promptData.launchConf.ask_skip_tags_on_launch')){
|
||||||
|
const templateDefaultSkipTags = params.promptData.launchConf.defaults.skip_tags.split(',');
|
||||||
|
promptDataToSave.skip_tags = (_.isEqual(templateDefaultSkipTags.sort(), params.promptData.prompts.skipTags.value.map(a => a.value).sort())) ? null : params.promptData.prompts.skipTags.value.map(a => a.value).join();
|
||||||
|
}
|
||||||
|
if(_.has(params, 'promptData.prompts.limit.value') && _.get(params, 'promptData.launchConf.ask_limit_on_launch')){
|
||||||
|
promptDataToSave.limit = params.promptData.launchConf.defaults.limit && params.promptData.launchConf.defaults.limit === params.promptData.prompts.limit.value ? null : params.promptData.prompts.limit.value;
|
||||||
|
}
|
||||||
|
if(_.has(params, 'promptData.prompts.verbosity.value.value') && _.get(params, 'promptData.launchConf.ask_verbosity_on_launch')){
|
||||||
|
promptDataToSave.verbosity = params.promptData.launchConf.defaults.verbosity && params.promptData.launchConf.defaults.verbosity === params.promptData.prompts.verbosity.value.value ? null : params.promptData.prompts.verbosity.value.value;
|
||||||
|
}
|
||||||
|
if(_.has(params, 'promptData.prompts.inventory.value') && _.get(params, 'promptData.launchConf.ask_inventory_on_launch')){
|
||||||
|
promptDataToSave.inventory = params.promptData.launchConf.defaults.inventory && params.promptData.launchConf.defaults.inventory.id === params.promptData.prompts.inventory.value.id ? null : params.promptData.prompts.inventory.value.id;
|
||||||
|
}
|
||||||
|
if(_.has(params, 'promptData.prompts.diffMode.value') && _.get(params, 'promptData.launchConf.ask_diff_mode_on_launch')){
|
||||||
|
promptDataToSave.diff_mode = params.promptData.launchConf.defaults.diff_mode && params.promptData.launchConf.defaults.diff_mode === params.promptData.prompts.diffMode.value ? null : params.promptData.prompts.diffMode.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return promptDataToSave;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
PromptService.$inject = ['Empty', '$filter'];
|
PromptService.$inject = ['Empty', '$filter'];
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ export default
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.promptExtraVars = $.isEmptyObject(scope.promptData.extraVars) ? '---' : jsyaml.safeDump(scope.promptData.extraVars);
|
scope.promptExtraVars = $.isEmptyObject(scope.promptData.extraVars) ? '---' : '---\n' + jsyaml.safeDump(scope.promptData.extraVars);
|
||||||
|
|
||||||
ParseTypeChange({
|
ParseTypeChange({
|
||||||
scope: scope,
|
scope: scope,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="Prompt-previewRow--flex">
|
<div class="Prompt-previewRow--flex" ng-if="promptData.prompts.jobType.value">
|
||||||
<div class="Prompt-previewRowTitle">{{:: vm.strings.get('prompt.JOB_TYPE') }}</div>
|
<div class="Prompt-previewRowTitle">{{:: vm.strings.get('prompt.JOB_TYPE') }}</div>
|
||||||
<div class="Prompt-previewRowValue">
|
<div class="Prompt-previewRowValue">
|
||||||
<span ng-if="promptData.prompts.jobType.value.value === 'run'">{{:: vm.strings.get('prompt.PLAYBOOK_RUN') }}</span>
|
<span ng-if="promptData.prompts.jobType.value.value === 'run'">{{:: vm.strings.get('prompt.PLAYBOOK_RUN') }}</span>
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="Prompt-previewRow--flex">
|
<div class="Prompt-previewRow--flex" ng-if="promptData.prompts.inventory.value.id">
|
||||||
<div class="Prompt-previewRowTitle">{{:: vm.strings.get('prompt.INVENTORY') }}</div>
|
<div class="Prompt-previewRowTitle">{{:: vm.strings.get('prompt.INVENTORY') }}</div>
|
||||||
<div class="Prompt-previewRowValue" ng-bind="promptData.prompts.inventory.value.name"></div>
|
<div class="Prompt-previewRowValue" ng-bind="promptData.prompts.inventory.value.name"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
<div class="Prompt-previewRowTitle">{{:: vm.strings.get('prompt.LIMIT') }}</div>
|
<div class="Prompt-previewRowTitle">{{:: vm.strings.get('prompt.LIMIT') }}</div>
|
||||||
<div class="Prompt-previewRowValue" ng-bind="promptData.prompts.limit.value"></div>
|
<div class="Prompt-previewRowValue" ng-bind="promptData.prompts.limit.value"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="Prompt-previewRow--flex">
|
<div class="Prompt-previewRow--flex" ng-if="promptData.prompts.inventory.value.label">
|
||||||
<div class="Prompt-previewRowTitle">{{:: vm.strings.get('prompt.VERBOSITY') }}</div>
|
<div class="Prompt-previewRowTitle">{{:: vm.strings.get('prompt.VERBOSITY') }}</div>
|
||||||
<div class="Prompt-previewRowValue" ng-bind="promptData.prompts.verbosity.value.label"></div>
|
<div class="Prompt-previewRowValue" ng-bind="promptData.prompts.verbosity.value.label"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="Prompt-previewRow--flex">
|
<div class="Prompt-previewRow--flex" ng-if="promptData.prompts.diffMode.value !== null">
|
||||||
<div class="Prompt-previewRowTitle">{{:: vm.strings.get('prompt.SHOW_CHANGES') }}</div>
|
<div class="Prompt-previewRowTitle">{{:: vm.strings.get('prompt.SHOW_CHANGES') }}</div>
|
||||||
<div class="Prompt-previewRowValue">
|
<div class="Prompt-previewRowValue">
|
||||||
<span ng-if="promptData.prompts.diffMode.value">{{:: vm.strings.get('ON') }}</span>
|
<span ng-if="promptData.prompts.diffMode.value">{{:: vm.strings.get('ON') }}</span>
|
||||||
|
|||||||
@@ -77,61 +77,36 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
|
|||||||
unified_job_template: params.node.unifiedJobTemplate.id
|
unified_job_template: params.node.unifiedJobTemplate.id
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if(_.has(params, 'node.promptData.extraVars')) {
|
||||||
|
if(_.get(params, 'node.promptData.launchConf.defaults.extra_vars')) {
|
||||||
|
if(!sendableNodeData.extra_data) {
|
||||||
|
sendableNodeData.extra_data = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultVars = jsyaml.safeLoad(params.node.promptData.launchConf.defaults.extra_vars);
|
||||||
|
|
||||||
|
// Only include extra vars that differ from the template default vars
|
||||||
|
_.forOwn(params.node.promptData.extraVars, (value, key) => {
|
||||||
|
if(!defaultVars[key] || defaultVars[key] !== value) {
|
||||||
|
sendableNodeData.extra_data[key] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if(sendableNodeData.extra_data === {}) {
|
||||||
|
delete sendableNodeData.extra_data;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sendableNodeData.extra_data = params.node.promptData.extraVars;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check to see if the user has provided any prompt values that are different
|
// Check to see if the user has provided any prompt values that are different
|
||||||
// from the defaults in the job template
|
// from the defaults in the job template
|
||||||
|
|
||||||
if(params.node.unifiedJobTemplate.type === "job_template" && params.node.promptData) {
|
if(params.node.unifiedJobTemplate.type === "job_template" && params.node.promptData) {
|
||||||
if(params.node.promptData.launchConf.survey_enabled){
|
sendableNodeData = PromptService.bundlePromptDataForSaving({
|
||||||
for (var i=0; i < params.node.promptData.surveyQuestions.length; i++){
|
promptData: params.node.promptData,
|
||||||
var fld = params.node.promptData.surveyQuestions[i].variable;
|
dataToSave: sendableNodeData
|
||||||
// grab all survey questions that have answers
|
});
|
||||||
if(params.node.promptData.surveyQuestions[i].required || (params.node.promptData.surveyQuestions[i].required === false && params.node.promptData.surveyQuestions[i].model.toString()!=="")) {
|
|
||||||
if(!sendableNodeData.extra_data) {
|
|
||||||
sendableNodeData.extra_data = {};
|
|
||||||
}
|
|
||||||
sendableNodeData.extra_data[fld] = params.node.promptData.surveyQuestions[i].model;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(params.node.promptData.surveyQuestions[i].required === false && _.isEmpty(params.node.promptData.surveyQuestions[i].model)) {
|
|
||||||
switch (params.node.promptData.surveyQuestions[i].type) {
|
|
||||||
// for optional text and text-areas, submit a blank string if min length is 0
|
|
||||||
// -- this is confusing, for an explanation see:
|
|
||||||
// http://docs.ansible.com/ansible-tower/latest/html/userguide/job_templates.html#optional-survey-questions
|
|
||||||
//
|
|
||||||
case "text":
|
|
||||||
case "textarea":
|
|
||||||
if (params.node.promptData.surveyQuestions[i].min === 0) {
|
|
||||||
sendableNodeData.extra_data[fld] = "";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(_.has(params, 'node.promptData.prompts.jobType.value.value') && _.get(params, 'node.promptData.launchConf.ask_job_type_on_launch')) {
|
|
||||||
sendableNodeData.job_type = params.node.promptData.prompts.jobType.templateDefault === params.node.promptData.prompts.jobType.value.value ? null : params.node.promptData.prompts.jobType.value.value;
|
|
||||||
}
|
|
||||||
if(_.has(params, 'node.promptData.prompts.tags.value') && _.get(params, 'node.promptData.launchConf.ask_tags_on_launch')){
|
|
||||||
let templateDefaultJobTags = params.node.promptData.prompts.tags.templateDefault.split(',');
|
|
||||||
sendableNodeData.job_tags = (_.isEqual(templateDefaultJobTags.sort(), params.node.promptData.prompts.tags.value.map(a => a.value).sort())) ? null : params.node.promptData.prompts.tags.value.map(a => a.value).join();
|
|
||||||
}
|
|
||||||
if(_.has(params, 'node.promptData.prompts.skipTags.value') && _.get(params, 'node.promptData.launchConf.ask_skip_tags_on_launch')){
|
|
||||||
let templateDefaultSkipTags = params.node.promptData.prompts.skipTags.templateDefault.split(',');
|
|
||||||
sendableNodeData.skip_tags = (_.isEqual(templateDefaultSkipTags.sort(), params.node.promptData.prompts.skipTags.value.map(a => a.value).sort())) ? null : params.node.promptData.prompts.skipTags.value.map(a => a.value).join();
|
|
||||||
}
|
|
||||||
if(_.has(params, 'node.promptData.prompts.limit.value') && _.get(params, 'node.promptData.launchConf.ask_limit_on_launch')){
|
|
||||||
sendableNodeData.limit = params.node.promptData.prompts.limit.templateDefault === params.node.promptData.prompts.limit.value ? null : params.node.promptData.prompts.limit.value;
|
|
||||||
}
|
|
||||||
if(_.has(params, 'node.promptData.prompts.verbosity.value.value') && _.get(params, 'node.promptData.launchConf.ask_verbosity_on_launch')){
|
|
||||||
sendableNodeData.verbosity = params.node.promptData.prompts.verbosity.templateDefault === params.node.promptData.prompts.verbosity.value.value ? null : params.node.promptData.prompts.verbosity.value.value;
|
|
||||||
}
|
|
||||||
if(_.has(params, 'node.promptData.prompts.inventory.value') && _.get(params, 'node.promptData.launchConf.ask_inventory_on_launch')){
|
|
||||||
sendableNodeData.inventory = _.has(params, 'node.promptData.prompts.inventory.templateDefault.id') && params.node.promptData.prompts.inventory.templateDefault.id === params.node.promptData.prompts.inventory.value.id ? null : params.node.promptData.prompts.inventory.value.id;
|
|
||||||
}
|
|
||||||
if(_.has(params, 'node.promptData.prompts.diffMode.value') && _.get(params, 'node.promptData.launchConf.ask_diff_mode_on_launch')){
|
|
||||||
sendableNodeData.diff_mode = params.node.promptData.prompts.diffMode.templateDefault === params.node.promptData.prompts.diffMode.value ? null : params.node.promptData.prompts.diffMode.value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sendableNodeData;
|
return sendableNodeData;
|
||||||
@@ -1028,7 +1003,7 @@ export default ['$scope', 'WorkflowService', 'GetBasePath', 'TemplatesService',
|
|||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.$watch('promptData.surveyQuestions', () => {
|
surveyQuestionWatcher = $scope.$watch('promptData.surveyQuestions', () => {
|
||||||
let missingSurveyValue = false;
|
let missingSurveyValue = false;
|
||||||
_.each($scope.promptData.surveyQuestions, (question) => {
|
_.each($scope.promptData.surveyQuestions, (question) => {
|
||||||
if(question.required && (Empty(question.model) || question.model === [])) {
|
if(question.required && (Empty(question.model) || question.model === [])) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*************************************************/
|
*************************************************/
|
||||||
|
|
||||||
|
|
||||||
export default ['$q', 'Prompt', '$filter', 'Wait', 'Rest', '$state', 'ProcessErrors', 'InitiatePlaybookRun', '$interval', 'moment', function ($q, Prompt, $filter, Wait, Rest, $state, ProcessErrors, InitiatePlaybookRun, $interval, moment) {
|
export default ['$q', 'Prompt', '$filter', 'Wait', 'Rest', '$state', 'ProcessErrors', 'WorkflowJobModel', '$interval', 'moment', function ($q, Prompt, $filter, Wait, Rest, $state, ProcessErrors, WorkflowJob, $interval, moment) {
|
||||||
var val = {
|
var val = {
|
||||||
getCounts: function(workflowNodes){
|
getCounts: function(workflowNodes){
|
||||||
var nodeArr = [];
|
var nodeArr = [];
|
||||||
@@ -107,8 +107,13 @@ export default ['$q', 'Prompt', '$filter', 'Wait', 'Rest', '$state', 'ProcessErr
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
relaunchJob: function(scope) {
|
relaunchJob: function(scope) {
|
||||||
InitiatePlaybookRun({ scope: scope, id: scope.workflow.id,
|
const workflowJob = new WorkflowJob();
|
||||||
relaunch: true, job_type: 'workflow_job' });
|
|
||||||
|
workflowJob.postRelaunch({
|
||||||
|
id: scope.workflow.id
|
||||||
|
}).then((launchRes) => {
|
||||||
|
$state.go('workflowResults', { id: launchRes.data.id }, { reload: true });
|
||||||
|
});
|
||||||
},
|
},
|
||||||
createOneSecondTimer: function(startTime, fn) {
|
createOneSecondTimer: function(startTime, fn) {
|
||||||
return $interval(function(){
|
return $interval(function(){
|
||||||
|
|||||||
@@ -393,19 +393,6 @@ describe('Controller: jobResultsController', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('$scope.relaunchJob', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
bootstrapTest();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should relaunch the job', () => {
|
|
||||||
let scope = $scope;
|
|
||||||
$scope.relaunchJob();
|
|
||||||
expect(jobResultsService.relaunchJob)
|
|
||||||
.toHaveBeenCalledWith(scope);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('count stuff', () => {
|
describe('count stuff', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
count = {
|
count = {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ describe('Controller: workflowResults', () => {
|
|||||||
|
|
||||||
beforeEach(angular.mock.module('workflowResults', ($provide) => {
|
beforeEach(angular.mock.module('workflowResults', ($provide) => {
|
||||||
['PromptDialog', 'Prompt', 'Wait', 'Rest', '$state', 'ProcessErrors',
|
['PromptDialog', 'Prompt', 'Wait', 'Rest', '$state', 'ProcessErrors',
|
||||||
'InitiatePlaybookRun', 'jobLabels', 'workflowNodes', 'count',
|
'jobLabels', 'workflowNodes', 'count',
|
||||||
].forEach((item) => {
|
].forEach((item) => {
|
||||||
$provide.value(item, {});
|
$provide.value(item, {});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ describe('workflowResultsService', () => {
|
|||||||
let $interval;
|
let $interval;
|
||||||
|
|
||||||
beforeEach(angular.mock.module('workflowResults', ($provide) => {
|
beforeEach(angular.mock.module('workflowResults', ($provide) => {
|
||||||
['PromptDialog', 'Prompt', 'Wait', 'Rest', 'ProcessErrors', 'InitiatePlaybookRun', '$state'].forEach(function(item) {
|
['PromptDialog', 'Prompt', 'Wait', 'Rest', 'ProcessErrors', '$state'].forEach(function(item) {
|
||||||
$provide.value(item, {});
|
$provide.value(item, {});
|
||||||
});
|
});
|
||||||
$provide.value('$stateExtender', { addState: jasmine.createSpy('addState'), });
|
$provide.value('$stateExtender', { addState: jasmine.createSpy('addState'), });
|
||||||
|
|||||||
Reference in New Issue
Block a user