Job detail page refactor

First pass at aggregating all incoming events without any DOM updates. Lets see if we can just perform simple aggregration in memory without a CPU meltdown.
This commit is contained in:
Chris Houseknecht
2014-06-19 16:08:55 -04:00
parent 4eddd692fb
commit 958e806ddc
2 changed files with 254 additions and 219 deletions

View File

@@ -8,8 +8,8 @@
'use strict'; 'use strict';
function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log, ClearScope, Breadcrumbs, LoadBreadCrumbs, GetBasePath, Wait, Rest, function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log, ClearScope, Breadcrumbs, LoadBreadCrumbs, GetBasePath, Wait, Rest,
ProcessErrors, ProcessEventQueue, SelectPlay, SelectTask, Socket, GetElapsed, FilterAllByHostName, DrawGraph, LoadHostSummary, ReloadHostSummaryList, ProcessErrors, SelectPlay, SelectTask, Socket, GetElapsed, FilterAllByHostName, DrawGraph, LoadHostSummary, ReloadHostSummaryList,
JobIsFinished, SetTaskStyles) { JobIsFinished, SetTaskStyles, DigestEvent) {
ClearScope(); ClearScope();
@@ -18,8 +18,7 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
scope = $scope, scope = $scope,
api_complete = false, api_complete = false,
refresh_count = 0, refresh_count = 0,
lastEventId = 0, lastEventId = 0;
queue = [];
scope.plays = []; scope.plays = [];
scope.playsMap = {}; scope.playsMap = {};
@@ -31,8 +30,8 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
scope.hostResultsMap = {}; scope.hostResultsMap = {};
api_complete = false; api_complete = false;
scope.hostTableRows = 75; scope.hostResultsMaxRows = 75;
scope.hostSummaryTableRows = 75; scope.hostSummariesMaxRows = 75;
scope.tasksMaxRows = 75; scope.tasksMaxRows = 75;
scope.playsMaxRows = 75; scope.playsMaxRows = 75;
@@ -54,6 +53,8 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
scope.host_summary.failed = 0; scope.host_summary.failed = 0;
scope.host_summary.total = 0; scope.host_summary.total = 0;
scope.jobData = {};
scope.eventsHelpText = "<p><i class=\"fa fa-circle successful-hosts-color\"></i> Successful</p>\n" + scope.eventsHelpText = "<p><i class=\"fa fa-circle successful-hosts-color\"></i> Successful</p>\n" +
"<p><i class=\"fa fa-circle changed-hosts-color\"></i> Changed</p>\n" + "<p><i class=\"fa fa-circle changed-hosts-color\"></i> Changed</p>\n" +
"<p><i class=\"fa fa-circle unreachable-hosts-color\"></i> Unreachable</p>\n" + "<p><i class=\"fa fa-circle unreachable-hosts-color\"></i> Unreachable</p>\n" +
@@ -68,23 +69,9 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
event_socket.init(); event_socket.init();
event_socket.on("job_events-" + job_id, function(data) { event_socket.on("job_events-" + job_id, function(data) {
data.event = data.event_name;
if (api_complete && data.id > lastEventId) { if (api_complete && data.id > lastEventId) {
if (queue.length < 25) { data.event = data.event_name;
$log.debug('received event: ' + data.id); DigestEvent({ scope: scope, event: data });
queue.unshift(data);
}
else {
api_complete = false; // stop more events from hitting the queue
window.clearInterval($rootScope.jobDetailInterval);
$log.debug('halting queue. reloading...');
setTimeout(function() {
$log.debug('reload');
scope.haltEventQueue = true;
queue = [];
scope.$emit('LoadJob');
}, 300);
}
} }
}); });
@@ -99,37 +86,17 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
if (data.status === 'failed' || data.status === 'canceled' || if (data.status === 'failed' || data.status === 'canceled' ||
data.status === 'error' || data.status === 'successful') { data.status === 'error' || data.status === 'successful') {
$log.debug('Job completed!'); $log.debug('Job completed!');
api_complete = false; $log.debug(scope.jobData);
scope.haltEventQueue = true;
window.clearInterval($rootScope.jobDetailInterval);
queue = [];
scope.$emit('LoadJob');
} }
} }
}); });
if (scope.removeAPIComplete) { if (scope.removeInitialLoadComplete) {
scope.removeAPIComplete(); scope.removeInitialLoadComplete();
} }
scope.removeAPIComplete = scope.$on('APIComplete', function() { scope.removeInitialLoadComplete = scope.$on('InitialLoadComplete', function() {
// process any events sitting in the queue var url;
var keys, url, hostId = 0, taskId = 0, playId = 0;
// Find the max event.id value in memory
hostId = (scope.hostResults.length > 0) ? scope.hostResults[scope.hostResults.length - 1].id : 0;
if (scope.hostResults.length > 0) {
keys = Object.keys(scope.hostResults);
keys.sort();
hostId = keys[keys.length - 1];
}
taskId = (scope.tasks.length > 0) ? scope.tasks[scope.tasks.length - 1].id : 0;
playId = (scope.plays.length > 0) ? scope.plays[scope.plays.length - 1].id : 0;
lastEventId = Math.max(hostId, taskId, playId);
Wait('stop');
// Draw the graph
if (JobIsFinished(scope)) { if (JobIsFinished(scope)) {
url = scope.job.related.job_events + '?event=playbook_on_stats'; url = scope.job.related.job_events + '?event=playbook_on_stats';
Rest.setUrl(url); Rest.setUrl(url);
@@ -141,58 +108,182 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
data: data.results[0].event_data data: data.results[0].event_data
}); });
DrawGraph({ scope: scope, resize: true }); DrawGraph({ scope: scope, resize: true });
Wait('stop');
} }
}) })
.error(function(data, status) { .error(function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!', ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + '. GET returned: ' + status }); msg: 'Call to ' + url + '. GET returned: ' + status });
}); });
$log.debug(scope.jobData);
}
else {
if (scope.host_summary.total > 0) {
// Draw the graph based on summary values in memory
DrawGraph({ scope: scope, resize: true });
}
api_complete = true; //trigger events to start processing
}
});
if (scope.removeLoadHostSummaries) {
scope.removeLoadHostSummaries();
}
scope.removeHostSummaries = scope.$on('LoadHostSummaries', function() {
var url = scope.job.related.job_host_summaries + '?';
url += '&page_size=' + scope.hostSummariesMaxRows + '&order_by=host__name';
scope.jobData.hostSummaries = {};
Rest.setUrl(url);
Rest.get()
.success(function(data) {
data.results.forEach(function(event) {
scope.jobData.hostSummaries[event.id] = {
id: event.host,
name: event.summary_fields.host.name,
ok: event.ok,
changed: event.changed,
unreachable: event.dark,
failed: event.failures
};
});
scope.$emit('InitialLoadComplete');
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + '. GET returned: ' + status });
});
});
if (scope.removeLoadHosts) {
scope.removeLoadHosts();
}
scope.removeLoadHosts = scope.$on('LoadHosts', function() {
if (scope.activeTask) {
var play = scope.jobData.plays[scope.activePlay],
task = play.tasks[scope.activeTask],
url;
url = scope.job.related.job_events + '?parent=' + task.id + '&';
url += 'host__isnull=false&page_size=' + scope.hostResultsMaxRows + '&order_by=-host__name';
Rest.setUrl(url);
Rest.get()
.success(function(data) {
var idx, event;
if (data.results.length > 0) {
lastEventId = data.results[0].id;
}
for (idx=data.results.length - 1; idx >= 0; idx--) {
event = data.results[idx];
task.hostResults[event.id] = {
id: event.id,
status: ( (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful' ),
host_id: event.host,
task_id: event.parent,
name: event.event_data.host,
created: event.created,
msg: ( (event.event_data && event.event_data.res) ? event.event_data.res.msg : '' )
};
}
scope.$emit('LoadHostSummaries');
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + '. GET returned: ' + status });
});
} }
else { else {
if (scope.host_summary.total > 0) { scope.jobData.hostSummaries = {};
// Draw the graph based on summary values in memory scope.$emit('InitialLoadComplete');
DrawGraph({ scope: scope, resize: true });
}
api_complete = true;
scope.haltEventQueue = false;
ProcessEventQueue({
scope: scope,
eventQueue: queue
});
} }
}); });
if (scope.removeInitialDataLoaded) { if (scope.removeLoadTasks) {
scope.removeInitialDataLoaded(); scope.removeLoadTasks();
} }
scope.removeInitialDataLoaded = scope.$on('InitialDataLoaded', function() { scope.removeLoadTasks = scope.$on('LoadTasks', function() {
// Load data for the host summary table if (scope.activePlay) {
if (!api_complete) { var play = scope.jobData.plays[scope.activePlay], url;
ReloadHostSummaryList({
scope: scope, url = scope.job.url + 'job_tasks/?event_id=' + play.id;
callback: 'APIComplete' url += '&page_size=' + scope.tasksMaxRows + '&order_by=-id';
});
Rest.setUrl(url);
Rest.get()
.success(function(data) {
var idx, end, elapsed, event;
if (data.results.length > 0) {
lastEventId = data.results[0].id;
scope.activeTask = data.results[0].id;
}
for (idx=data.results.length - 1; idx >= 0; idx--) {
event = data.results[idx];
if (play.firstTask === null) {
play.firstTask = event.id;
play.hostCount = (event.host_count) ? event.host_count : 0;
}
if (idx < data.length - 1) {
// end date = starting date of the next event
end = data[idx + 1].created;
}
else {
// no next event (task), get the end time of the play
end = scope.jobData.plays[scope.activePlay].finished;
}
if (end) {
elapsed = GetElapsed({
start: event.created,
end: end
});
}
else {
elapsed = '00:00:00';
}
play.tasks[event.id] = {
id: event.id,
play_id: scope.activePlay,
name: event.name,
status: ( (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful' ),
created: event.created,
modified: event.modified,
finished: end,
elapsed: elapsed,
hostCount: (event.host_count) ? event.host_count : 0,
reportedHosts: (event.reported_hosts) ? event.reported_hosts : 0,
successfulCount: (event.successful_count) ? event.successful_count : 0,
failedCount: (event.failed_count) ? event.failed_count : 0,
changedCount: (event.changed_count) ? event.changed_count : 0,
skippedCount: (event.skipped_count) ? event.skipped_count : 0,
taskActiveClass: '',
hostResults: {}
};
SetTaskStyles({
scope: scope,
task_id: event.id
});
}
scope.jobData.plays[scope.activePlay].tasks[scope.activeTask].taskActiveClass = 'active';
scope.$emit('LoadHosts');
})
.error(function(data) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + '. GET returned: ' + status });
});
}
else {
scope.jobData.hostSummaries = {};
scope.$emit('InitialLoadComplete');
} }
}); });
if (scope.removePlaysReady) { if (scope.removeLoadPlays) {
scope.removePlaysReady(); scope.removeLoadPlays();
} }
scope.removePlaysReady = scope.$on('PlaysReady', function() { scope.removeLoadPlays = scope.$on('LoadPlays', function(e, events_url) {
// Select the most recent play, which will trigger tasks and hosts to load
SelectPlay({
scope: scope,
id: ((scope.plays.length > 0) ? scope.plays[scope.plays.length - 1].id : null ),
callback: 'InitialDataLoaded'
});
});
if (scope.removeLoadJobDetails) {
scope.removeLoadJobDetails();
}
scope.removeRefreshJobDetails = scope.$on('LoadJobDetails', function(e, events_url) {
// Call to load all the job bits including, plays, tasks, hosts results and host summary
scope.host_summary.ok = 0; scope.host_summary.ok = 0;
scope.host_summary.changed = 0; scope.host_summary.changed = 0;
@@ -200,14 +291,22 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
scope.host_summary.failed = 0; scope.host_summary.failed = 0;
scope.host_summary.total = 0; scope.host_summary.total = 0;
scope.jobData.plays = {};
var url = scope.job.url + 'job_plays/?order_by=id'; var url = scope.job.url + 'job_plays/?order_by=id';
url += '&page_size=' + scope.playsMaxRows + '&order_by=-id';
Rest.setUrl(url); Rest.setUrl(url);
Rest.get() Rest.get()
.success( function(data) { .success( function(data) {
data.forEach(function(event, idx) { var idx, event, status, start, end, elapsed;
var status = (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful', if (data.length > 0) {
start = event.started, scope.activePlay = data[0].id;
end, elapsed, play; }
for (idx=data.length - 1; idx >= 0; idx--) {
event = data[idx];
status = (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful';
start = event.started;
if (idx < data.length - 1) { if (idx < data.length - 1) {
// end date = starting date of the next event // end date = starting date of the next event
@@ -227,29 +326,17 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
elapsed = '00:00:00'; elapsed = '00:00:00';
} }
if (scope.playsMap[event.id] !== undefined) { scope.jobData.plays[event.id] = {
play = scope.plays[scope.playsMap[event.id]]; id: event.id,
play.finished = end; name: event.play,
play.status = status; created: start,
play.elapsed = elapsed; finished: end,
play.playActiveClass = ''; status: status,
} elapsed: elapsed,
else { hostCount: 0,
scope.plays.push({ fistTask: null,
id: event.id, tasks: {}
name: event.play, };
created: start,
finished: end,
status: status,
elapsed: elapsed,
playActiveClass: '',
hostCount: 0,
fistTask: null
});
if (scope.plays.length > scope.playsMaxRows) {
scope.plays.shift();
}
}
scope.host_summary.ok += (data.ok_count) ? data.ok_count : 0; scope.host_summary.ok += (data.ok_count) ? data.ok_count : 0;
scope.host_summary.changed += (data.changed_count) ? data.changed_count : 0; scope.host_summary.changed += (data.changed_count) ? data.changed_count : 0;
@@ -257,16 +344,9 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
scope.host_summary.failed += (data.failed_count) ? data.failed_count : 0; scope.host_summary.failed += (data.failed_count) ? data.failed_count : 0;
scope.host_summary.total = scope.host_summary.ok + scope.host_summary.changed + scope.host_summary.total = scope.host_summary.ok + scope.host_summary.changed +
scope.host_summary.unreachable + scope.host_summary.failed; scope.host_summary.unreachable + scope.host_summary.failed;
}); }
scope.$emit('LoadTasks', events_url);
//rebuild the index //scope.$emit('FixPlaysScroll');
scope.playsMap = {};
scope.plays.forEach(function(play, idx) {
scope.playsMap[play.id] = idx;
});
scope.$emit('PlaysReady', events_url);
scope.$emit('FixPlaysScroll');
}) })
.error( function(data, status) { .error( function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!', ProcessErrors(scope, data, status, null, { hdr: 'Error!',
@@ -352,7 +432,7 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
scope.job_status.elapsed = '00:00:00'; scope.job_status.elapsed = '00:00:00';
} }
scope.setSearchAll('host'); scope.setSearchAll('host');
scope.$emit('LoadJobDetails', data.related.job_events); scope.$emit('LoadPlays', data.related.job_events);
if (!scope.credential_name) { if (!scope.credential_name) {
scope.$emit('GetCredentialNames', data); scope.$emit('GetCredentialNames', data);
} }
@@ -972,6 +1052,6 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log,
} }
JobDetailController.$inject = [ '$rootScope', '$scope', '$compile', '$routeParams', '$log', 'ClearScope', 'Breadcrumbs', 'LoadBreadCrumbs', 'GetBasePath', JobDetailController.$inject = [ '$rootScope', '$scope', '$compile', '$routeParams', '$log', 'ClearScope', 'Breadcrumbs', 'LoadBreadCrumbs', 'GetBasePath',
'Wait', 'Rest', 'ProcessErrors', 'ProcessEventQueue', 'SelectPlay', 'SelectTask', 'Socket', 'GetElapsed', 'FilterAllByHostName', 'DrawGraph', 'Wait', 'Rest', 'ProcessErrors', 'SelectPlay', 'SelectTask', 'Socket', 'GetElapsed', 'FilterAllByHostName', 'DrawGraph',
'LoadHostSummary', 'ReloadHostSummaryList', 'JobIsFinished', 'SetTaskStyles' 'LoadHostSummary', 'ReloadHostSummaryList', 'JobIsFinished', 'SetTaskStyles', 'DigestEvent'
]; ];

View File

@@ -72,6 +72,8 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
var scope = params.scope, var scope = params.scope,
event = params.event; event = params.event;
$log.debug('processing event: ' + event.id);
switch (event.event) { switch (event.event) {
case 'playbook_on_start': case 'playbook_on_start':
if (!JobIsFinished(scope)) { if (!JobIsFinished(scope)) {
@@ -81,28 +83,20 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
break; break;
case 'playbook_on_play_start': case 'playbook_on_play_start':
scope.plays.push({ scope.jobData.plays[event.id] = {
id: event.id, id: event.id,
name: event.play, name: event.play,
created: event.created, created: event.created,
status: (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful', status: (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful',
elapsed: '00:00:00', elapsed: '00:00:00',
hostCount: 0, hostCount: 0,
fistTask: null fistTask: null,
}); tasks: {}
scope.playsMap[event.id] = scope.plays.length -1; };
if (scope.playsMap[scope.activePlay] !== undefined) { if (scope.activePlay) {
scope.plays[scope.playsMap[scope.activePlay]].playActiveClass = ''; scope.jobData.plays[scope.activePlay].tasks = {};
} }
scope.activePlay = event.id; scope.activePlay = event.id;
scope.plays[scope.playsMap[event.id]].playActiveClass = 'active';
scope.tasks = [];
scope.tasksMap = {};
scope.hostResults = [];
scope.hostResultsMap = {};
$('#hosts-table-detail').mCustomScrollbar("update");
$('#tasks-table-detail').mCustomScrollbar("update");
scope.$emit('FixPlaysScroll');
break; break;
case 'playbook_on_setup': case 'playbook_on_setup':
@@ -201,8 +195,8 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
}); });
scope.job_status.status = (event.failed) ? 'failed' : 'successful'; scope.job_status.status = (event.failed) ? 'failed' : 'successful';
scope.job_status.status_class = ""; scope.job_status.status_class = "";
LoadHostSummary({ scope: scope, data: event.event_data }); //LoadHostSummary({ scope: scope, data: event.event_data });
DrawGraph({ scope: scope, resize: true }); //DrawGraph({ scope: scope, resize: true });
break; break;
} }
}; };
@@ -246,14 +240,14 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
var scope = params.scope, var scope = params.scope,
event = params.event; event = params.event;
scope.tasks.push({ scope.jobData.plays[scope.activePlay].tasks[event.id] = {
id: event.id, id: event.id,
play_id: event.parent, play_id: event.parent,
name: event.event_display, name: event.event_display,
status: ( (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful' ), status: ( (event.failed) ? 'failed' : (event.changed) ? 'changed' : 'successful' ),
created: event.created, created: event.created,
modified: event.modified, modified: event.modified,
hostCount: scope.plays[scope.playsMap[scope.activePlay]].hostCount, hostCount: scope.jobData.plays[scope.activePlay].hostCount,
reportedHosts: 0, reportedHosts: 0,
successfulCount: 0, successfulCount: 0,
failedCount: 0, failedCount: 0,
@@ -262,31 +256,21 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
successfulStyle: { display: 'none'}, successfulStyle: { display: 'none'},
failedStyle: { display: 'none' }, failedStyle: { display: 'none' },
changedStyle: { display: 'none' }, changedStyle: { display: 'none' },
skippedStyle: { display: 'none' } skippedStyle: { display: 'none' },
}); hostResults: {}
scope.tasksMap[event.id] = scope.tasks.length - 1; };
if (scope.tasks.length > scope.tasksMaxRows) {
scope.tasks.shift(); if (!scope.jobData.plays[scope.activePlay].firstTask) {
} scope.jobData.plays[scope.activePlay].firstTask = event.id;
if (!scope.plays[scope.playsMap[scope.activePlay]].firstTask) {
scope.plays[scope.playsMap[scope.activePlay]].firstTask = event.id;
} }
if (scope.activeTask && scope.tasksMap[scope.activeTask] !== undefined) { if (scope.activeTask && scope.jobData.plays[scope.activePlay].tasks[scope.activeTask] !== undefined) {
scope.tasks[scope.tasksMap[scope.activeTask]].taskActiveClass = ''; scope.jobData.plays[scope.activePlay].tasks[scope.activeTask].taskActiveClass = '';
scope.jobData.plays[scope.activePlay].tasks[scope.activeTask].hostResults = {};
} }
scope.activeTask = event.id; scope.activeTask = event.id;
scope.tasks[scope.tasksMap[event.id]].taskActiveClass = 'active'; scope.jobData.plays[scope.activePlay].tasks[scope.activeTask].taskActiveClass = 'active';
scope.hostResults = [];
scope.hostResultsMap = {};
// Not sure if this still works
scope.hasRoles = (event.role) ? true : false;
$('#hosts-table-detail').mCustomScrollbar("update");
scope.$emit('FixTasksScroll');
// Record the first task id
UpdatePlayStatus({ UpdatePlayStatus({
scope: scope, scope: scope,
play_id: event.parent, play_id: event.parent,
@@ -295,9 +279,9 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
modified: event.modified modified: event.modified
}); });
if (scope.host_summary.total > 0) { /*if (scope.host_summary.total > 0) {
DrawGraph({ scope: scope, resize: true }); DrawGraph({ scope: scope, resize: true });
} }*/
}; };
}]) }])
@@ -339,8 +323,8 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
status_text = params.status_text, status_text = params.status_text,
play; play;
if (scope.playsMap[id] !== undefined) { if (scope.jobData.plays[scope.activePlay] !== undefined) {
play = scope.plays[scope.playsMap[id]]; play = scope.jobData.plays[scope.activePlay];
if (failed) { if (failed) {
play.status = 'failed'; play.status = 'failed';
} }
@@ -379,8 +363,8 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
no_hosts = params.no_hosts, no_hosts = params.no_hosts,
task; task;
if (scope.tasksMap[id] !== undefined) { if (scope.jobData.plays[scope.activePlay].tasks[scope.activeTask] !== undefined) {
task = scope.tasks[scope.tasksMap[id]]; task = scope.jobData.plays[scope.activePlay].tasks[scope.activeTask];
if (no_hosts){ if (no_hosts){
task.status = 'no-matching-hosts'; task.status = 'no-matching-hosts';
} }
@@ -430,35 +414,21 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
scope.host_summary.total = scope.host_summary.ok + scope.host_summary.changed + scope.host_summary.unreachable + scope.host_summary.total = scope.host_summary.ok + scope.host_summary.changed + scope.host_summary.unreachable +
scope.host_summary.failed; scope.host_summary.failed;
if (scope.hostsMap[host_id] !== undefined) { if (scope.jobData.hostSummaries[host_id] !== undefined) {
scope.hosts[scope.hostsMap[host_id]].ok += (status === 'successful') ? 1 : 0; scope.jobData.hostSummaries[host_id].ok += (status === 'successful') ? 1 : 0;
scope.hosts[scope.hostsMap[host_id]].changed += (status === 'changed') ? 1 : 0; scope.jobData.hostSummaries[host_id].changed += (status === 'changed') ? 1 : 0;
scope.hosts[scope.hostsMap[host_id]].unreachable += (status === 'unreachable') ? 1 : 0; scope.jobData.hostSummaries[host_id].unreachable += (status === 'unreachable') ? 1 : 0;
scope.hosts[scope.hostsMap[host_id]].failed += (status === 'failed') ? 1 : 0; scope.jobData.hostSummaries[host_id].failed += (status === 'failed') ? 1 : 0;
} }
else if (scope.hosts.length < scope.hostSummaryTableRows) { else {
scope.hosts.push({ scope.jobData.hostSummaries[host_id] = {
id: host_id, id: host_id,
name: name, name: name,
ok: (status === 'successful') ? 1 : 0, ok: (status === 'successful') ? 1 : 0,
changed: (status === 'changed') ? 1 : 0, changed: (status === 'changed') ? 1 : 0,
unreachable: (status === 'unreachable') ? 1 : 0, unreachable: (status === 'unreachable') ? 1 : 0,
failed: (status === 'failed') ? 1 : 0 failed: (status === 'failed') ? 1 : 0
}); };
scope.hosts.sort(function (a, b) {
if (a.name > b.name)
return 1;
if (a.name < b.name)
return -1;
// a must be equal to b
return 0;
});
scope.hostsMap = {};
scope.hosts.forEach(function(host, idx){
scope.hostsMap[host.id] = idx;
});
$('#hosts-table-detail').mCustomScrollbar("update");
} }
UpdateTaskStatus({ UpdateTaskStatus({
@@ -495,40 +465,25 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
msg = params.message, msg = params.message,
task; task;
if (scope.hostResultsMap[host_id] === undefined && scope.hostResults.length < scope.hostTableRows) { scope.jobData.plays[scope.activePlay].tasks[scope.activeTask].hostResults[event_id] = {
scope.hostResults.push({ id: event_id,
id: event_id, status: status,
status: status, host_id: host_id,
host_id: host_id, task_id: task_id,
task_id: task_id, name: name,
name: name, created: created,
created: created, msg: msg
msg: msg
});
scope.hostResults.sort(function(a,b) {
if (a.name < b.name) {
return -1;
}
if (a.name > b.name) {
return 1;
}
return 0;
});
// Refresh the map
scope.hostResultsMap = {};
scope.hostResults.forEach(function(result, idx) {
scope.hostResultsMap[result.id] = idx;
});
scope.$emit('FixHostResultsScroll');
} }
// update the task status bar // update the task status bar
if (scope.tasksMap[task_id] !== undefined) { if (scope.jobData.plays[scope.activePlay].tasks[task_id] !== undefined) {
task = scope.tasks[scope.tasksMap[task_id]]; task = scope.jobData.plays[scope.activePlay].tasks[task_id];
if (task_id === scope.plays[scope.playsMap[scope.activePlay]].firstTask) {
scope.plays[scope.playsMap[scope.activePlay]].hostCount++; if (task_id === scope.jobData.plays[scope.activePlay].firstTask) {
scope.jobData.plays[scope.activePlay].hostCount++;
task.hostCount++; task.hostCount++;
} }
task.reportedHosts += 1; task.reportedHosts += 1;
task.failedCount += (status === 'failed' || status === 'unreachable') ? 1 : 0; task.failedCount += (status === 'failed' || status === 'unreachable') ? 1 : 0;
task.changedCount += (status === 'changed') ? 1 : 0; task.changedCount += (status === 'changed') ? 1 : 0;
@@ -548,7 +503,7 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge
scope = params.scope, scope = params.scope,
diff, task; diff, task;
task = scope.tasks[scope.tasksMap[task_id]]; task = scope.jobData.plays[scope.activePlay].tasks[task_id];
task.failedPct = (task.hostCount > 0) ? Math.ceil((100 * (task.failedCount / task.hostCount))) : 0; task.failedPct = (task.hostCount > 0) ? Math.ceil((100 * (task.failedCount / task.hostCount))) : 0;
task.changedPct = (task.hostCount > 0) ? Math.ceil((100 * (task.changedCount / task.hostCount))) : 0; task.changedPct = (task.hostCount > 0) ? Math.ceil((100 * (task.changedCount / task.hostCount))) : 0;
task.skippedPct = (task.hostCount > 0) ? Math.ceil((100 * (task.skippedCount / task.hostCount))) : 0; task.skippedPct = (task.hostCount > 0) ? Math.ceil((100 * (task.skippedCount / task.hostCount))) : 0;