mirror of
https://github.com/ansible/awx.git
synced 2026-05-08 09:57:35 -02:30
extend JobDetailService to process job_event host results, resolves #1410
This commit is contained in:
@@ -822,7 +822,6 @@ export default
|
|||||||
url += (scope.search_task_name) ? '&task__icontains=' + scope.search_task_name : '';
|
url += (scope.search_task_name) ? '&task__icontains=' + scope.search_task_name : '';
|
||||||
url += (scope.search_task_status === 'failed') ? '&failed=true' : '';
|
url += (scope.search_task_status === 'failed') ? '&failed=true' : '';
|
||||||
url += '&page_size=' + scope.tasksMaxRows + '&order=id';
|
url += '&page_size=' + scope.tasksMaxRows + '&order=id';
|
||||||
|
|
||||||
scope.plays.every(function(p, idx) {
|
scope.plays.every(function(p, idx) {
|
||||||
if (p.id === scope.selectedPlay) {
|
if (p.id === scope.selectedPlay) {
|
||||||
play = scope.plays[idx];
|
play = scope.plays[idx];
|
||||||
@@ -931,7 +930,7 @@ export default
|
|||||||
}])
|
}])
|
||||||
|
|
||||||
// Call when the selected task needs to change
|
// Call when the selected task needs to change
|
||||||
.factory('SelectTask', ['LoadHosts', function(LoadHosts) {
|
.factory('SelectTask', ['LoadHosts', 'JobDetailService', function(LoadHosts, JobDetailService) {
|
||||||
return function(params) {
|
return function(params) {
|
||||||
var scope = params.scope,
|
var scope = params.scope,
|
||||||
id = params.id,
|
id = params.id,
|
||||||
@@ -946,11 +945,16 @@ export default
|
|||||||
scope.tasks[idx].taskActiveClass = '';
|
scope.tasks[idx].taskActiveClass = '';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// /api/v1/jobs/16/job_events/?parent=832&event__startswith=runner&page_size=200&order=host_name,counte
|
||||||
LoadHosts({
|
var params = {
|
||||||
scope: scope,
|
parent: scope.selectedTask,
|
||||||
callback: callback,
|
event__startswith: 'runner',
|
||||||
clear: true
|
page_size: scope.hostResultsMaxRows,
|
||||||
|
order: 'host_name,counter',
|
||||||
|
};
|
||||||
|
JobDetailService.getRelatedJobEvents(scope.job.id, params).success(function(res){
|
||||||
|
scope.hostResults = JobDetailService.processHostResults(res.results)
|
||||||
|
scope.hostResultsLoading = false;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}])
|
}])
|
||||||
@@ -961,7 +965,6 @@ export default
|
|||||||
var scope = params.scope,
|
var scope = params.scope,
|
||||||
callback = params.callback,
|
callback = params.callback,
|
||||||
url;
|
url;
|
||||||
|
|
||||||
scope.hostResults = [];
|
scope.hostResults = [];
|
||||||
|
|
||||||
if (scope.selectedTask) {
|
if (scope.selectedTask) {
|
||||||
@@ -970,6 +973,7 @@ export default
|
|||||||
url += (scope.search_host_name) ? 'host__name__icontains=' + scope.search_host_name + '&' : '';
|
url += (scope.search_host_name) ? 'host__name__icontains=' + scope.search_host_name + '&' : '';
|
||||||
url += (scope.search_host_status === 'failed') ? 'failed=true&' : '';
|
url += (scope.search_host_status === 'failed') ? 'failed=true&' : '';
|
||||||
url += 'event__startswith=runner&page_size=' + scope.hostResultsMaxRows + '&order=host_name,counter';
|
url += 'event__startswith=runner&page_size=' + scope.hostResultsMaxRows + '&order=host_name,counter';
|
||||||
|
console.log(url)
|
||||||
scope.hostResultsLoading = true;
|
scope.hostResultsLoading = true;
|
||||||
Rest.setUrl(url);
|
Rest.setUrl(url);
|
||||||
Rest.get()
|
Rest.get()
|
||||||
@@ -1020,7 +1024,6 @@ export default
|
|||||||
msg = event.event_data.res;
|
msg = event.event_data.res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.event !== "runner_on_no_hosts") {
|
if (event.event !== "runner_on_no_hosts") {
|
||||||
scope.hostResults.push({
|
scope.hostResults.push({
|
||||||
id: event.id,
|
id: event.id,
|
||||||
@@ -1037,7 +1040,6 @@ export default
|
|||||||
});
|
});
|
||||||
|
|
||||||
scope.hostResultsLoading = false;
|
scope.hostResultsLoading = false;
|
||||||
|
|
||||||
if (callback) {
|
if (callback) {
|
||||||
scope.$emit(callback);
|
scope.$emit(callback);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,49 +1,49 @@
|
|||||||
<div class="HostEvent-details--left">
|
<div class="HostEvent-details--left">
|
||||||
<div class="HostEvent-field">
|
<div class="HostEvent-field">
|
||||||
<div class="HostEvent-title">EVENT</div>
|
<div class="HostEvent-title">EVENT</div>
|
||||||
<span class="HostEvent-field--content"></span>
|
<span class="HostEvent-field--content"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="HostEvent-field">
|
<div class="HostEvent-field">
|
||||||
<span class="HostEvent-field--label">HOST</span>
|
<span class="HostEvent-field--label">HOST</span>
|
||||||
<span class="HostEvent-field--content">
|
<span class="HostEvent-field--content">
|
||||||
<a ui-sref="jobDetail.host-events({hostName: event.host_name})">{{event.host_name || "No result found"}}</a></span>
|
<a ui-sref="jobDetail.host-events({hostName: event.host_name})">{{event.host_name || "No result found"}}</a></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="HostEvent-field">
|
<div class="HostEvent-field">
|
||||||
<span class="HostEvent-field--label">STATUS</span>
|
<span class="HostEvent-field--label">STATUS</span>
|
||||||
<span class="HostEvent-field--content">
|
<span class="HostEvent-field--content">
|
||||||
<a class="HostEvents-status">
|
<a class="HostEvents-status">
|
||||||
<i class="fa fa-circle" ng-class="processEventStatus"></i>
|
<i class="fa fa-circle" ng-class="processEventStatus(event).class"></i>
|
||||||
</a>
|
</a>
|
||||||
{{event.status || "No result found"}}
|
{{processEventStatus(event).status || "No result found"}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="HostEvent-field">
|
<div class="HostEvent-field">
|
||||||
<span class="HostEvent-field--label">ID</span>
|
<span class="HostEvent-field--label">ID</span>
|
||||||
<span class="HostEvent-field--content">{{event.id || "No result found"}}</span>
|
<span class="HostEvent-field--content">{{event.id || "No result found"}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="HostEvent-field">
|
<div class="HostEvent-field">
|
||||||
<span class="HostEvent-field--label">CREATED</span>
|
<span class="HostEvent-field--label">CREATED</span>
|
||||||
<span class="HostEvent-field--content">{{event.created || "No result found"}}</span>
|
<span class="HostEvent-field--content">{{event.created || "No result found"}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="HostEvent-field">
|
<div class="HostEvent-field">
|
||||||
<span class="HostEvent-field--label">PLAY</span>
|
<span class="HostEvent-field--label">PLAY</span>
|
||||||
<span class="HostEvent-field--content">{{event.play || "No result found"}}</span>
|
<span class="HostEvent-field--content">{{event.play || "No result found"}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="HostEvent-field">
|
<div class="HostEvent-field">
|
||||||
<span class="HostEvent-field--label">TASK</span>
|
<span class="HostEvent-field--label">TASK</span>
|
||||||
<span class="HostEvent-field--content">{{event.task || "No result found"}}</span>
|
<span class="HostEvent-field--content">{{event.task || "No result found"}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="HostEvent-field">
|
<div class="HostEvent-field">
|
||||||
<span class="HostEvent-field--label">MODULE</span>
|
<span class="HostEvent-field--label">MODULE</span>
|
||||||
<span class="HostEvent-field--content">{{event.event_data.res.invocation.module_name || "No result found"}}</span>
|
<span class="HostEvent-field--content">{{event.event_data.res.invocation.module_name || "No result found"}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="HostEvent-details--right" ng-show="event.event_data.res">
|
<div class="HostEvent-details--right" ng-show="event.event_data.res">
|
||||||
<div class="HostEvent-title">RESULTS</div>
|
<div class="HostEvent-title">RESULTS</div>
|
||||||
<!-- discard any objects in the ansible response until we decide to flatten them -->
|
<!-- discard any objects in the ansible response until we decide to flatten them -->
|
||||||
<div class="HostEvent-field" ng-repeat="(key, value) in results = event.event_data.res track by $index" ng-if="processResults(value)">
|
<div class="HostEvent-field" ng-repeat="(key, value) in results = event.event_data.res track by $index" ng-if="processResults(value)">
|
||||||
<span class="HostEvent-field--label">{{key}}</span>
|
<span class="HostEvent-field--label">{{key}}</span>
|
||||||
<span class="HostEvent-field--content">{{value}}</span>
|
<span class="HostEvent-field--content">{{value}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,7 @@
|
|||||||
<!-- view navigation buttons -->
|
<!-- view navigation buttons -->
|
||||||
<button ui-sref="jobDetail.host-event.details" type="button" class="btn btn-sm btn-default" >Details</button>
|
<button ui-sref="jobDetail.host-event.details" type="button" class="btn btn-sm btn-default" >Details</button>
|
||||||
<button ui-sref="jobDetail.host-event.json" type="button" class="btn btn-sm btn-default ">JSON</button>
|
<button ui-sref="jobDetail.host-event.json" type="button" class="btn btn-sm btn-default ">JSON</button>
|
||||||
<button ng-show="event.stdout" ui-sref="jobDetail.host-event.stdout" type="button" class="btn btn-sm btn-default ">Standard Out</button>
|
<button ng-show="stdout" ui-sref="jobDetail.host-event.stdout" type="button" class="btn btn-sm btn-default ">Standard Out</button>
|
||||||
<button ng-show="event.timing" ui-sref="jobDetail.host-event.timing" type="button" class="btn btn-sm btn-default ">Timing</button>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="HostEvent-body">
|
<div class="HostEvent-body">
|
||||||
|
|||||||
@@ -1,13 +1,2 @@
|
|||||||
<div class="EventHost-stdoutPanel Panel">
|
<textarea id="HostEvent-stdout" class="HostEvent-stdout">
|
||||||
<div class="StandardOut-panelHeader">
|
</textarea>
|
||||||
<div class="StandardOut-panelHeaderText">STANDARD OUT</div>
|
|
||||||
<div class="StandardOut-panelHeaderActions">
|
|
||||||
<a href="/api/v1/jobs/{{ job.id }}/stdout?format=txt_download&token={{ token }}">
|
|
||||||
<button class="StandardOut-actionButton" aw-tool-tip="Download Output" data-placement="top">
|
|
||||||
<i class="fa fa-download"></i>
|
|
||||||
</button>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<standard-out-log stdout-endpoint="event._stdout"></standard-out-log>
|
|
||||||
</div>
|
|
||||||
@@ -4,68 +4,78 @@
|
|||||||
* All Rights Reserved
|
* All Rights Reserved
|
||||||
*************************************************/
|
*************************************************/
|
||||||
|
|
||||||
|
|
||||||
export default
|
export default
|
||||||
['$stateParams', '$scope', '$state', 'Wait', 'JobDetailService', 'moment', 'event',
|
['$stateParams', '$scope', '$state', 'Wait', 'JobDetailService', 'moment', 'event',
|
||||||
function($stateParams, $scope, $state, Wait, JobDetailService, moment, event){
|
function($stateParams, $scope, $state, Wait, JobDetailService, moment, event){
|
||||||
// Avoid rendering objects in the details fieldset
|
|
||||||
// ng-if="processResults(value)" via host-event-details.partial.html
|
|
||||||
$scope.processResults = function(value){
|
|
||||||
if (typeof value == 'object'){return false}
|
|
||||||
else {return true}
|
|
||||||
};
|
|
||||||
|
|
||||||
var codeMirror = function(){
|
$scope.processEventStatus = JobDetailService.processEventStatus;
|
||||||
var el = $('#HostEvent-json')[0];
|
// Avoid rendering objects in the details fieldset
|
||||||
var editor = CodeMirror.fromTextArea(el, {
|
// ng-if="processResults(value)" via host-event-details.partial.html
|
||||||
lineNumbers: true,
|
$scope.processResults = function(value){
|
||||||
mode: {name: "javascript", json: true}
|
if (typeof value == 'object'){return false;}
|
||||||
});
|
else {return true;}
|
||||||
editor.getDoc().setValue(JSON.stringify($scope.json, null, 4));
|
};
|
||||||
};
|
|
||||||
|
|
||||||
$scope.getActiveHostIndex = function(){
|
var codeMirror = function(el, json){
|
||||||
var result = $scope.hostResults.filter(function( obj ) {
|
var el = $(el)[0];
|
||||||
return obj.id == $scope.event.id;
|
var editor = CodeMirror.fromTextArea(el, {
|
||||||
});
|
lineNumbers: true,
|
||||||
return $scope.hostResults.indexOf(result[0])
|
mode: {name: "javascript", json: true}
|
||||||
};
|
});
|
||||||
|
editor.getDoc().setValue(JSON.stringify(json, null, 4));
|
||||||
|
};
|
||||||
|
|
||||||
$scope.showPrev = function(){
|
$scope.getActiveHostIndex = function(){
|
||||||
return $scope.getActiveHostIndex() != 0
|
var result = $scope.hostResults.filter(function( obj ) {
|
||||||
};
|
return obj.id == $scope.event.id;
|
||||||
|
});
|
||||||
|
return $scope.hostResults.indexOf(result[0]);
|
||||||
|
};
|
||||||
|
|
||||||
$scope.showNext = function(){
|
$scope.showPrev = function(){
|
||||||
return $scope.getActiveHostIndex() < $scope.hostResults.indexOf($scope.hostResults[$scope.hostResults.length - 1])
|
return $scope.getActiveHostIndex() != 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.goNext = function(){
|
$scope.showNext = function(){
|
||||||
var index = $scope.getActiveHostIndex() + 1;
|
return $scope.getActiveHostIndex() < $scope.hostResults.indexOf($scope.hostResults[$scope.hostResults.length - 1]);
|
||||||
var id = $scope.hostResults[index].id;
|
};
|
||||||
$state.go('jobDetail.host-event.details', {eventId: id})
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.goPrev = function(){
|
$scope.goNext = function(){
|
||||||
var index = $scope.getActiveHostIndex() - 1;
|
var index = $scope.getActiveHostIndex() + 1;
|
||||||
var id = $scope.hostResults[index].id;
|
var id = $scope.hostResults[index].id;
|
||||||
$state.go('jobDetail.host-event.details', {eventId: id})
|
$state.go('jobDetail.host-event.details', {eventId: id});
|
||||||
};
|
};
|
||||||
|
|
||||||
var init = function(){
|
$scope.goPrev = function(){
|
||||||
$scope.event = event.data.results[0];
|
var index = $scope.getActiveHostIndex() - 1;
|
||||||
$scope.event.created = moment($scope.event.created).format();
|
var id = $scope.hostResults[index].id;
|
||||||
$scope.processEventStatus = JobDetailService.processEventStatus($scope.event);
|
$state.go('jobDetail.host-event.details', {eventId: id});
|
||||||
$scope.hostResults = $stateParams.hostResults;
|
};
|
||||||
$scope.json = JobDetailService.processJson($scope.event);
|
|
||||||
if ($state.current.name == 'jobDetail.host-event.json'){
|
var init = function(){
|
||||||
codeMirror();
|
console.log(event)
|
||||||
}
|
$scope.event = event.data.results[0];
|
||||||
try {
|
$scope.event.created = moment($scope.event.created).format();
|
||||||
$scope.stdout = $scope.event.event_data.res.stdout
|
$scope.hostResults = $stateParams.hostResults;
|
||||||
}
|
$scope.json = JobDetailService.processJson($scope.event);
|
||||||
catch(err){
|
if ($state.current.name == 'jobDetail.host-event.json'){
|
||||||
$scope.sdout = null;
|
codeMirror('#HostEvent-json', $scope.json);
|
||||||
}
|
}
|
||||||
$('#HostEvent').modal('show');
|
try {
|
||||||
};
|
$scope.stdout = JobDetailService.processJson($scope.event.event_data.res)
|
||||||
init();
|
console.log($scope.stdout)
|
||||||
}];
|
if ($state.current.name == 'jobDetail.host-event.stdout'){
|
||||||
|
codeMirror('#HostEvent-stdout', $scope.stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(err){
|
||||||
|
$scope.sdout = null;
|
||||||
|
}
|
||||||
|
console.log($scope)
|
||||||
|
|
||||||
|
|
||||||
|
$('#HostEvent').modal('show');
|
||||||
|
};
|
||||||
|
init();
|
||||||
|
}];
|
||||||
@@ -36,9 +36,9 @@
|
|||||||
<td class=HostEvents-table--cell>
|
<td class=HostEvents-table--cell>
|
||||||
<!-- status circles -->
|
<!-- status circles -->
|
||||||
<a class="HostEvents-status">
|
<a class="HostEvents-status">
|
||||||
<i class="fa fa-circle" ng-class="processEventStatus(event)"></i>
|
<i class="fa fa-circle" ng-class="processEventStatus(event).class"></i>
|
||||||
</a>
|
</a>
|
||||||
{{event.status}}
|
{{processEventStatus(event).status}}
|
||||||
</td>
|
</td>
|
||||||
<td class=HostEvents-table--cell>{{event.play}}</td>
|
<td class=HostEvents-table--cell>{{event.play}}</td>
|
||||||
<td class=HostEvents-table--cell>{{event.task}}</td>
|
<td class=HostEvents-table--cell>{{event.task}}</td>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export default
|
|||||||
'ProcessErrors', 'SelectPlay', 'SelectTask', 'Socket', 'GetElapsed',
|
'ProcessErrors', 'SelectPlay', 'SelectTask', 'Socket', 'GetElapsed',
|
||||||
'DrawGraph', 'LoadHostSummary', 'ReloadHostSummaryList',
|
'DrawGraph', 'LoadHostSummary', 'ReloadHostSummaryList',
|
||||||
'JobIsFinished', 'SetTaskStyles', 'DigestEvent', 'UpdateDOM', 'DeleteJob', 'PlaybookRun',
|
'JobIsFinished', 'SetTaskStyles', 'DigestEvent', 'UpdateDOM', 'DeleteJob', 'PlaybookRun',
|
||||||
'LoadPlays', 'LoadTasks', 'LoadHosts', 'HostsEdit',
|
'LoadPlays', 'LoadTasks', 'HostsEdit',
|
||||||
'ParseVariableString', 'GetChoices', 'fieldChoices', 'fieldLabels',
|
'ParseVariableString', 'GetChoices', 'fieldChoices', 'fieldLabels',
|
||||||
'EditSchedule', 'ParseTypeChange', 'JobDetailService',
|
'EditSchedule', 'ParseTypeChange', 'JobDetailService',
|
||||||
function(
|
function(
|
||||||
@@ -25,7 +25,7 @@ export default
|
|||||||
SelectPlay, SelectTask, Socket, GetElapsed, DrawGraph,
|
SelectPlay, SelectTask, Socket, GetElapsed, DrawGraph,
|
||||||
LoadHostSummary, ReloadHostSummaryList, JobIsFinished,
|
LoadHostSummary, ReloadHostSummaryList, JobIsFinished,
|
||||||
SetTaskStyles, DigestEvent, UpdateDOM, DeleteJob,
|
SetTaskStyles, DigestEvent, UpdateDOM, DeleteJob,
|
||||||
PlaybookRun, LoadPlays, LoadTasks, LoadHosts,
|
PlaybookRun, LoadPlays, LoadTasks,
|
||||||
HostsEdit, ParseVariableString, GetChoices, fieldChoices,
|
HostsEdit, ParseVariableString, GetChoices, fieldChoices,
|
||||||
fieldLabels, EditSchedule, ParseTypeChange, JobDetailService
|
fieldLabels, EditSchedule, ParseTypeChange, JobDetailService
|
||||||
) {
|
) {
|
||||||
@@ -376,64 +376,26 @@ export default
|
|||||||
var params = {
|
var params = {
|
||||||
parent: task.id,
|
parent: task.id,
|
||||||
event__startswith: 'runner',
|
event__startswith: 'runner',
|
||||||
page_size: scope.hostResultsMaxRows
|
|
||||||
};
|
};
|
||||||
JobDetailService.getRelatedJobEvents(scope.job.id, params)
|
JobDetailService.getRelatedJobEvents(scope.job.id, params)
|
||||||
.success(function(data) {
|
.success(function(data) {
|
||||||
|
console.log(data)
|
||||||
var idx, event, status, status_text, item, msg;
|
var idx, event, status, status_text, item, msg;
|
||||||
if (data.results.length > 0) {
|
if (data.results.length > 0) {$
|
||||||
lastEventId = data.results[0].id;
|
lastEventId = data.results[0].id;
|
||||||
}
|
}
|
||||||
scope.next_host_results = data.next;
|
scope.next_host_results = data.next;
|
||||||
for (idx=data.results.length - 1; idx >= 0; idx--) {
|
for (idx=data.results.length - 1; idx >= 0; idx--) {
|
||||||
event = data.results[idx];
|
event = data.results[idx];
|
||||||
if (event.event === "runner_on_skipped") {
|
event.status = JobDetailService.processEventStatus(event).status;
|
||||||
status = 'skipped';
|
msg = JobDetailService.processEventMsg(event);
|
||||||
}
|
item = JobDetailService.processEventItem(event);
|
||||||
else if (event.event === "runner_on_unreachable") {
|
|
||||||
status = 'unreachable';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
status = (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful';
|
|
||||||
}
|
|
||||||
switch(status) {
|
|
||||||
case "successful":
|
|
||||||
status_text = 'OK';
|
|
||||||
break;
|
|
||||||
case "changed":
|
|
||||||
status_text = "Changed";
|
|
||||||
break;
|
|
||||||
case "failed":
|
|
||||||
status_text = "Failed";
|
|
||||||
break;
|
|
||||||
case "unreachable":
|
|
||||||
status_text = "Unreachable";
|
|
||||||
break;
|
|
||||||
case "skipped":
|
|
||||||
status_text = "Skipped";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.event_data && event.event_data.res) {
|
if (event.event !== "runner_on$_no_hosts") {
|
||||||
item = event.event_data.res.item;
|
|
||||||
if (typeof item === "object") {
|
|
||||||
item = JSON.stringify(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
msg = '';
|
|
||||||
if (event.event_data && event.event_data.res) {
|
|
||||||
if (typeof event.event_data.res === 'object') {
|
|
||||||
msg = event.event_data.res.msg;
|
|
||||||
} else {
|
|
||||||
msg = event.event_data.res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.event !== "runner_on_no_hosts") {
|
|
||||||
task.hostResults[event.id] = {
|
task.hostResults[event.id] = {
|
||||||
id: event.id,
|
id: event.id,
|
||||||
status: status,
|
status: event.status,
|
||||||
status_text: status_text,
|
status_text: event.status.toUpperCase(),
|
||||||
host_id: event.host,
|
host_id: event.host,
|
||||||
task_id: event.parent,
|
task_id: event.parent,
|
||||||
name: event.event_data.host,
|
name: event.event_data.host,
|
||||||
@@ -1037,6 +999,16 @@ export default
|
|||||||
scope.searchTasksEnabled = true;
|
scope.searchTasksEnabled = true;
|
||||||
}
|
}
|
||||||
if (!scope.liveEventProcessing || scope.pauseLiveEvents) {
|
if (!scope.liveEventProcessing || scope.pauseLiveEvents) {
|
||||||
|
// /api/v1/jobs/15/job_tasks/?event_id=762&task__icontains=create&page_size=200&order=id
|
||||||
|
var params = {
|
||||||
|
event_id: scope.selectedPlay,
|
||||||
|
task__icontains: scope.search_task_name,
|
||||||
|
page_size: scope.tasksMaxRows,
|
||||||
|
|
||||||
|
};
|
||||||
|
if (scope.search_task_status === 'failed'){
|
||||||
|
params.failed = true;
|
||||||
|
}
|
||||||
LoadTasks({
|
LoadTasks({
|
||||||
scope: scope
|
scope: scope
|
||||||
});
|
});
|
||||||
@@ -1058,8 +1030,20 @@ export default
|
|||||||
scope.searchHostsEnabled = true;
|
scope.searchHostsEnabled = true;
|
||||||
}
|
}
|
||||||
if (!scope.liveEventProcessing || scope.pauseLiveEvents) {
|
if (!scope.liveEventProcessing || scope.pauseLiveEvents) {
|
||||||
LoadHosts({
|
scope.hostResultsLoading = true;
|
||||||
scope: scope
|
var params = {
|
||||||
|
parent: scope.selectedTask,
|
||||||
|
event__startswith: 'runner',
|
||||||
|
page_size: scope.hostResultsMaxRows,
|
||||||
|
order: 'host_name,counter',
|
||||||
|
host_name__icontains: scope.search_host_name
|
||||||
|
}
|
||||||
|
if (scope.search_host_status === 'failed'){
|
||||||
|
params.failed = true;
|
||||||
|
}
|
||||||
|
JobDetailService.getRelatedJobEvents(scope.job.id, params).success(function(res){
|
||||||
|
scope.hostResults = JobDetailService.processHostResults(res.results)
|
||||||
|
scope.hostResultsLoading = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1104,8 +1088,20 @@ export default
|
|||||||
scope.filterHostStatus = function() {
|
scope.filterHostStatus = function() {
|
||||||
scope.search_host_status = (scope.search_host_status === 'all') ? 'failed' : 'all';
|
scope.search_host_status = (scope.search_host_status === 'all') ? 'failed' : 'all';
|
||||||
if (!scope.liveEventProcessing || scope.pauseLiveEvents) {
|
if (!scope.liveEventProcessing || scope.pauseLiveEvents) {
|
||||||
LoadHosts({
|
console.log('filterHostStattus', scope)
|
||||||
scope: scope
|
var params = {
|
||||||
|
parent: scope.selectedTask,
|
||||||
|
event__startswith: 'runner',
|
||||||
|
page_size: scope.hostResultsMaxRows,
|
||||||
|
order: 'host_name,counter'
|
||||||
|
}
|
||||||
|
if (scope.search_host_status === 'failed'){
|
||||||
|
params.failed = true;
|
||||||
|
}
|
||||||
|
scope.hostResultsLoading = true;
|
||||||
|
JobDetailService.getRelatedJobEvents(scope.job.id, params).success(function(res){
|
||||||
|
scope.hostResults = JobDetailService.processHostResults(res.results)
|
||||||
|
scope.hostResultsLoading = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,18 +1,17 @@
|
|||||||
export default
|
export default
|
||||||
['$rootScope', 'Rest', 'GetBasePath', 'ProcessErrors', function($rootScope, Rest, GetBasePath, ProcessErrors){
|
['$rootScope', 'Rest', 'GetBasePath', 'ProcessErrors', function($rootScope, Rest, GetBasePath, ProcessErrors){
|
||||||
return {
|
return {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
For ES6
|
* For ES6
|
||||||
it might be useful to set some default params here, e.g.
|
* it might be useful to set some default params here, e.g.
|
||||||
getJobHostSummaries: function(id, page_size=200, order='host_name'){}
|
* getJobHostSummaries: function(id, page_size=200, order='host_name'){}
|
||||||
without ES6, we'd have to supply defaults like this:
|
* without ES6, we'd have to supply defaults like this:
|
||||||
this.page_size = params.page_size ? params.page_size : 200;
|
* this.page_size = params.page_size ? params.page_size : 200;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// the the API passes through Ansible's event_data response
|
// the the API passes through Ansible's event_data response
|
||||||
// we need to massage away the verbose and redundant properties
|
// we need to massage away the verbose and redundant properties
|
||||||
|
|
||||||
processJson: function(data){
|
processJson: function(data){
|
||||||
// a deep copy
|
// a deep copy
|
||||||
var result = $.extend(true, {}, data);
|
var result = $.extend(true, {}, data);
|
||||||
@@ -44,147 +43,195 @@ export default
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch(err){result.event_data = null;}
|
catch(err){result.event_data = undefined;}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
},
|
},
|
||||||
|
// Return Ansible's passed-through response msg on a job_event
|
||||||
|
processEventMsg: function(event){
|
||||||
|
return typeof event.event_data.res === 'object' ? event.event_data.res.msg : event.event_data.res;
|
||||||
|
},
|
||||||
|
// Return only Ansible's passed-through response item on a job_event
|
||||||
|
processEventItem: function(event){
|
||||||
|
try{
|
||||||
|
var item = event.event_data.res.item;
|
||||||
|
return typeof item === 'object' ? JSON.stringify(item) : item
|
||||||
|
}
|
||||||
|
catch(err){return;}
|
||||||
|
},
|
||||||
|
// Generate a helper class for job_event statuses
|
||||||
|
// the stack for which status to display is
|
||||||
|
// unreachable > failed > changed > ok
|
||||||
|
// uses the API's runner events and convenience properties .failed .changed to determine status.
|
||||||
|
// see: job_event_callback.py
|
||||||
processEventStatus: function(event){
|
processEventStatus: function(event){
|
||||||
// Generate a helper class for job_event statuses
|
|
||||||
// the stack for which status to display is
|
|
||||||
// unreachable > failed > changed > ok
|
|
||||||
// uses the API's runner events and convenience properties .failed .changed to determine status.
|
|
||||||
// see: job_event_callback.py
|
|
||||||
if (event.event == 'runner_on_unreachable'){
|
if (event.event == 'runner_on_unreachable'){
|
||||||
event.status = 'Unreachable';
|
return {
|
||||||
return 'HostEvents-status--unreachable'
|
class: 'HostEvents-status--unreachable',
|
||||||
|
status: 'unreachable'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// equiv to 'runner_on_error' && 'runner on failed'
|
// equiv to 'runner_on_error' && 'runner on failed'
|
||||||
if (event.failed){
|
if (event.failed){
|
||||||
event.status = 'Failed';
|
return {
|
||||||
return 'HostEvents-status--failed'
|
class: 'HostEvents-status--failed',
|
||||||
|
status: 'failed'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// catch the changed case before ok, because both can be true
|
// catch the changed case before ok, because both can be true
|
||||||
if (event.changed){
|
if (event.changed){
|
||||||
event.status = 'Changed';
|
return {
|
||||||
return 'HostEvents-status--changed'
|
class: 'HostEvents-status--changed',
|
||||||
|
status: 'changed'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (event.event == 'runner_on_ok'){
|
if (event.event == 'runner_on_ok'){
|
||||||
event.status = 'OK';
|
return {
|
||||||
return 'HostEvents-status--ok'
|
class: 'HostEvents-status--ok',
|
||||||
|
status: 'ok'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (event.event == 'runner_on_skipped'){
|
if (event.event == 'runner_on_skipped'){
|
||||||
event.status = 'Skipped';
|
return {
|
||||||
return 'HostEvents-status--skipped'
|
class: 'HostEvents-status--skipped',
|
||||||
|
status: 'skipped'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
// study a case where none of these apply
|
// study a case where none of these apply
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// GET events related to a job run
|
// Consumes a response from this.getRelatedJobEvents
|
||||||
// e.g.
|
// returns an array for view logic to iterate over to build host result rows
|
||||||
// ?event=playbook_on_stats
|
processHostResults: function(data){
|
||||||
// ?parent=206&event__startswith=runner&page_size=200&order=host_name,counter
|
var self = this;
|
||||||
getRelatedJobEvents: function(id, params){
|
var results = [];
|
||||||
var url = GetBasePath('jobs');
|
data.forEach(function(element, index, array){
|
||||||
url = url + id + '/job_events/?';
|
var event = element;
|
||||||
Object.keys(params).forEach(function(key, index) {
|
if (event.event !== 'runner_on_no_hosts'){
|
||||||
// the API is tolerant of extra ampersands
|
var status = self.processEventStatus(event);
|
||||||
// ?&event=playbook_on_start == ?event=playbook_on_stats
|
var msg = self.processEventMsg(event);
|
||||||
url = url + '&' + key + '=' + params[key];
|
var item = self.processEventItem(event);
|
||||||
});
|
results.push({
|
||||||
Rest.setUrl(url);
|
id: event.id,
|
||||||
return Rest.get()
|
status: status.status,
|
||||||
.success(function(data){
|
status_text: status.status.charAt(0).toUpperCase() + status.status.slice(1),
|
||||||
return data
|
host_id: event.host,
|
||||||
})
|
task_id: event.parent,
|
||||||
.error(function(data, status) {
|
name: event.event_data.host,
|
||||||
ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
|
created: event.created,
|
||||||
msg: 'Call to ' + url + '. GET returned: ' + status });
|
msg: typeof msg === 'undefined' ? undefined : msg,
|
||||||
});
|
item: typeof item === 'undefined' ? undefined : item
|
||||||
},
|
});
|
||||||
// GET job host summaries related to a job run
|
}
|
||||||
// e.g. ?page_size=200&order=host_name
|
});
|
||||||
getJobHostSummaries: function(id, params){
|
return results;
|
||||||
var url = GetBasePath('jobs');
|
},
|
||||||
url = url + id + '/job_host_summaries/?'
|
|
||||||
Object.keys(params).forEach(function(key, index) {
|
// GET events related to a job run
|
||||||
// the API is tolerant of extra ampersands
|
// e.g.
|
||||||
url = url + '&' + key + '=' + params[key];
|
// ?event=playbook_on_stats
|
||||||
});
|
// ?parent=206&event__startswith=runner&page_size=200&order=host_name,counter
|
||||||
Rest.setUrl(url);
|
getRelatedJobEvents: function(id, params){
|
||||||
return Rest.get()
|
var url = GetBasePath('jobs');
|
||||||
.success(function(data){
|
url = url + id + '/job_events/?';
|
||||||
return data
|
Object.keys(params).forEach(function(key, index) {
|
||||||
})
|
// the API is tolerant of extra ampersands
|
||||||
.error(function(data, status) {
|
// ?&event=playbook_on_start == ?event=playbook_on_stats
|
||||||
ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
|
url = url + '&' + key + '=' + params[key];
|
||||||
msg: 'Call to ' + url + '. GET returned: ' + status });
|
});
|
||||||
});
|
Rest.setUrl(url);
|
||||||
},
|
return Rest.get()
|
||||||
// GET job plays related to a job run
|
.success(function(data){
|
||||||
// e.g. ?page_size=200
|
return data
|
||||||
getJobPlays: function(id, params){
|
})
|
||||||
var url = GetBasePath('jobs');
|
.error(function(data, status) {
|
||||||
url = url + id + '/job_plays/?';
|
ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
|
||||||
Object.keys(params).forEach(function(key, index) {
|
msg: 'Call to ' + url + '. GET returned: ' + status });
|
||||||
// the API is tolerant of extra ampersands
|
});
|
||||||
url = url + '&' + key + '=' + params[key];
|
},
|
||||||
});
|
// GET job host summaries related to a job run
|
||||||
Rest.setUrl(url);
|
// e.g. ?page_size=200&order=host_name
|
||||||
return Rest.get()
|
getJobHostSummaries: function(id, params){
|
||||||
.success(function(data){
|
var url = GetBasePath('jobs');
|
||||||
return data
|
url = url + id + '/job_host_summaries/?'
|
||||||
})
|
Object.keys(params).forEach(function(key, index) {
|
||||||
.error(function(data, status) {
|
// the API is tolerant of extra ampersands
|
||||||
ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
|
url = url + '&' + key + '=' + params[key];
|
||||||
msg: 'Call to ' + url + '. GET returned: ' + status });
|
});
|
||||||
});
|
Rest.setUrl(url);
|
||||||
},
|
return Rest.get()
|
||||||
getJobTasks: function(id, params){
|
.success(function(data){
|
||||||
var url = GetBasePath('jobs');
|
return data
|
||||||
url = url + id + '/job_tasks/?';
|
})
|
||||||
Object.keys(params).forEach(function(key, index) {
|
.error(function(data, status) {
|
||||||
// the API is tolerant of extra ampersands
|
ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
|
||||||
url = url + '&' + key + '=' + params[key];
|
msg: 'Call to ' + url + '. GET returned: ' + status });
|
||||||
});
|
});
|
||||||
Rest.setUrl(url);
|
},
|
||||||
return Rest.get()
|
// GET job plays related to a job run
|
||||||
.success(function(data){
|
// e.g. ?page_size=200
|
||||||
return data
|
getJobPlays: function(id, params){
|
||||||
})
|
var url = GetBasePath('jobs');
|
||||||
.error(function(data, status) {
|
url = url + id + '/job_plays/?';
|
||||||
ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
|
Object.keys(params).forEach(function(key, index) {
|
||||||
msg: 'Call to ' + url + '. GET returned: ' + status });
|
// the API is tolerant of extra ampersands
|
||||||
});
|
url = url + '&' + key + '=' + params[key];
|
||||||
},
|
});
|
||||||
getJob: function(id){
|
Rest.setUrl(url);
|
||||||
var url = GetBasePath('jobs');
|
return Rest.get()
|
||||||
url = url + id;
|
.success(function(data){
|
||||||
Rest.setUrl(url);
|
return data
|
||||||
return Rest.get()
|
})
|
||||||
.success(function(data){
|
.error(function(data, status) {
|
||||||
return data
|
ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
|
||||||
})
|
msg: 'Call to ' + url + '. GET returned: ' + status });
|
||||||
.error(function(data, status) {
|
});
|
||||||
ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
|
},
|
||||||
msg: 'Call to ' + url + '. GET returned: ' + status });
|
getJobTasks: function(id, params){
|
||||||
});
|
var url = GetBasePath('jobs');
|
||||||
},
|
url = url + id + '/job_tasks/?';
|
||||||
// GET next set of paginated results
|
Object.keys(params).forEach(function(key, index) {
|
||||||
// expects 'next' param returned by the API e.g.
|
// the API is tolerant of extra ampersands
|
||||||
// "/api/v1/jobs/51/job_plays/?order_by=id&page=2&page_size=1"
|
url = url + '&' + key + '=' + params[key];
|
||||||
getNextPage: function(url){
|
});
|
||||||
return Rest.get()
|
Rest.setUrl(url);
|
||||||
.success(function(data){
|
return Rest.get()
|
||||||
return data
|
.success(function(data){
|
||||||
})
|
return data
|
||||||
.error(function(data, status) {
|
})
|
||||||
ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
|
.error(function(data, status) {
|
||||||
msg: 'Call to ' + url + '. GET returned: ' + status });
|
ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
|
||||||
});
|
msg: 'Call to ' + url + '. GET returned: ' + status });
|
||||||
}
|
});
|
||||||
}
|
},
|
||||||
}
|
getJob: function(id){
|
||||||
];
|
var url = GetBasePath('jobs');
|
||||||
|
url = url + id;
|
||||||
|
Rest.setUrl(url);
|
||||||
|
return Rest.get()
|
||||||
|
.success(function(data){
|
||||||
|
return data
|
||||||
|
})
|
||||||
|
.error(function(data, status) {
|
||||||
|
ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
|
||||||
|
msg: 'Call to ' + url + '. GET returned: ' + status });
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// GET next set of paginated results
|
||||||
|
// expects 'next' param returned by the API e.g.
|
||||||
|
// "/api/v1/jobs/51/job_plays/?order_by=id&page=2&page_size=1"
|
||||||
|
getNextPage: function(url){
|
||||||
|
return Rest.get()
|
||||||
|
.success(function(data){
|
||||||
|
return data
|
||||||
|
})
|
||||||
|
.error(function(data, status) {
|
||||||
|
ProcessErrors($rootScope, data, status, null, { hdr: 'Error!',
|
||||||
|
msg: 'Call to ' + url + '. GET returned: ' + status });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
Reference in New Issue
Block a user