updates to getting host counts

This commit is contained in:
John Mitchell 2016-09-30 14:47:08 -04:00 committed by jaredevantabor
parent e31bfa2f1c
commit 11592047d6
6 changed files with 179 additions and 106 deletions

View File

@ -4,90 +4,21 @@
* All Rights Reserved
*************************************************/
export default [function(){
export default ['jobResultsService', function(jobResultsService){
var val = {};
// the playbook_on_stats event returns the count data in a weird format.
// format to what we need!
var getCountsFromStatsEvent = function(event_data) {
var hosts = {},
hostsArr;
// iterate over the event_data and populate an object with hosts
// and their status data
Object.keys(event_data).forEach(key => {
// failed passes boolean not integer
if (key === "failed") {
// array of hosts from failed type
hostsArr = Object.keys(event_data[key]);
hostsArr.forEach(host => {
if (!hosts[host]) {
// host has not been added to hosts object
// add now
hosts[host] = {};
}
hosts[host][key] = event_data[key][host];
});
} else {
// array of hosts from each type ("changed", "dark", etc.)
hostsArr = Object.keys(event_data[key]);
hostsArr.forEach(host => {
if (!hosts[host]) {
// host has not been added to hosts object
// add now
hosts[host] = {};
}
if (!hosts[host][key]) {
// host doesn't have key
hosts[host][key] = 0;
}
hosts[host][key] += event_data[key][host];
});
}
});
// use the hosts data populate above to get the count
var count = {
ok : _.filter(hosts, function(o){
return !o.failures && !o.changed && o.ok > 0;
}),
skipped : _.filter(hosts, function(o){
return o.skipped > 0;
}),
unreachable : _.filter(hosts, function(o){
return o.dark > 0;
}),
failures : _.filter(hosts, function(o){
return o.failed === true;
}),
changed : _.filter(hosts, function(o){
return o.changed > 0;
})
};
// turn the count into an actual count, rather than a list of host
// names
Object.keys(count).forEach(key => {
count[key] = count[key].length;
});
return count;
};
// Get the count of the last event
var getPreviousCount = function(id) {
var getPreviousCount = function(counter) {
// get the ids of all the queue
var ids = Object.keys(val.queue).map(id => parseInt(id));
var counters = Object.keys(val.queue).map(counter => parseInt(counter));
// iterate backwards to find the last count
while(ids.indexOf(id - 1) > -1) {
id = id - 1;
if (val.queue[id].count) {
while(counters.indexOf(counter - 1) > -1) {
counter = counter - 1;
if (val.queue[counter].count) {
// need to create a new copy of count when returning
// so that it is accurate for the particular event
return _.clone(val.queue[id].count);
return _.clone(val.queue[counter].count);
}
}
@ -104,33 +35,39 @@ export default [function(){
// munge the raw event from the backend into the event_queue's format
var mungeEvent = function(event) {
var mungedEvent = {
counter: event.counter,
id: event.id,
processed: false,
name: event.event_name,
count: getPreviousCount(event.id)
name: event.event_name
};
if (event.event_name === 'playbook_on_start') {
// sets count initially so this is a change
mungedEvent.count = getPreviousCount(mungedEvent.counter);
mungedEvent.changes = ['count'];
} else if (event.event_name === 'runner_on_ok' ||
event.event_name === 'runner_on_async_ok') {
mungedEvent.count = getPreviousCount(mungedEvent.counter);
mungedEvent.count.ok++;
mungedEvent.changes = ['count'];
} else if (event.event_name === 'runner_on_skipped') {
mungedEvent.count = getPreviousCount(mungedEvent.counter);
mungedEvent.count.skipped++;
mungedEvent.changes = ['count'];
} else if (event.event_name === 'runner_on_unreachable') {
mungedEvent.count = getPreviousCount(mungedEvent.counter);
mungedEvent.count.unreachable++;
mungedEvent.changes = ['count'];
} else if (event.event_name === 'runner_on_error' ||
event.event_name === 'runner_on_async_failed') {
mungedEvent.count = getPreviousCount(mungedEvent.counter);
mungedEvent.count.failed++;
mungedEvent.changes = ['count'];
} else if (event.event_name === 'playbook_on_stats') {
// get the data for populating the host status bar
mungedEvent.count = getCountsFromStatsEvent(event.event_data);
mungedEvent.changes = ['count'];
mungedEvent.count = jobResultsService
.getCountsFromStatsEvent(event.event_data);
mungedEvent.changes = ['count', 'countFinished'];
}
return mungedEvent;
};
@ -143,15 +80,19 @@ export default [function(){
},
// populates the event queue
populate: function(event) {
var mungedEvent = mungeEvent(event);
val.queue[event.id] = mungedEvent;
// don't populate the event if it's already been added either
// by rest or by websocket event
if (!val.queue[event.counter]) {
var mungedEvent = mungeEvent(event);
val.queue[mungedEvent.counter] = mungedEvent;
return mungedEvent;
return mungedEvent;
}
},
// the event has been processed in the view and should be marked as
// completed in the queue
markProcessed: function(event) {
val.queue[event.id].processed = true;
val.queue[event.counter].processed = true;
}
};

View File

@ -7,41 +7,46 @@
margin-top: 10px;
}
.HostStatusBar-ok,
.HostStatusBar-changed,
.HostStatusBar-unreachable,
.HostStatusBar-failures,
.HostStatusBar-skipped,
.HostStatusBar-noData {
height: 15px;
border-top: 5px solid @default-bg;
border-bottom: 5px solid @default-bg;
}
.HostStatusBar-ok {
background-color: @default-succ;
display: flex;
flex: 0 0 auto;
height: 5px;
}
.HostStatusBar-changed {
background-color: @default-warning;
flex: 0 0 auto;
height: 5px;
}
.HostStatusBar-unreachable {
background-color: @default-unreachable;
flex: 0 0 auto;
height: 5px;
}
.HostStatusBar-failures {
background-color: @default-err;
flex: 0 0 auto;
height: 5px;
}
.HostStatusBar-skipped {
background-color: @default-link;
flex: 0 0 auto;
height: 5px;
}
.HostStatusBar-noData {
background-color: @default-icon-hov;
flex: 1 0 auto;
height: 5px;
}
.HostStatusBar-tooltipLabel {

View File

@ -1,4 +1,4 @@
export default ['jobData', 'jobDataOptions', 'jobLabels', '$scope', 'ParseTypeChange', 'ParseVariableString', 'jobResultsService', '$rootScope', 'eventQueue', function(jobData, jobDataOptions, jobLabels, $scope, ParseTypeChange, ParseVariableString, jobResultsService, $rootScope, eventQueue) {
export default ['jobData', 'jobDataOptions', 'jobLabels', 'count', '$scope', 'ParseTypeChange', 'ParseVariableString', 'jobResultsService', '$rootScope', 'eventQueue', function(jobData, jobDataOptions, jobLabels, count, $scope, ParseTypeChange, ParseVariableString, jobResultsService, $rootScope, eventQueue) {
var getTowerLinks = function() {
var getTowerLink = function(key) {
if ($scope.job.related[key]) {
@ -34,6 +34,11 @@ export default ['jobData', 'jobDataOptions', 'jobLabels', '$scope', 'ParseTypeCh
$scope.verbosity_label = getTowerLabel('verbosity');
};
var getTotalHostCount = function(count) {
return Object
.keys(count).reduce((acc, i) => acc += count[i], 0);
};
// put initially resolved request data on scope
$scope.job = jobData;
$scope.jobOptions = jobDataOptions.actions.GET;
@ -66,6 +71,11 @@ export default ['jobData', 'jobDataOptions', 'jobLabels', '$scope', 'ParseTypeCh
jobResultsService.cancelJob($scope.job);
};
// get initial count from resolve
$scope.count = count.val;
$scope.hostCount = getTotalHostCount(count.val);
$scope.countFinished = count.countFinished;
// EVENT STUFF BELOW
// just putting the event queue on scope so it can be inspected in the
@ -79,8 +89,14 @@ export default ['jobData', 'jobDataOptions', 'jobLabels', '$scope', 'ParseTypeCh
// make changes to ui based on the event returned from the queue
if (mungedEvent.changes) {
mungedEvent.changes.forEach(change => {
if (change === 'count') {
if (change === 'count' && !$scope.countFinished) {
$scope.count = mungedEvent.count;
$scope.hostCount = getTotalHostCount(mungedEvent
.count);
}
if (change === 'countFnished') {
$scope.countFinished = true;
}
});
}
@ -90,15 +106,21 @@ export default ['jobData', 'jobDataOptions', 'jobLabels', '$scope', 'ParseTypeCh
};
// grab completed event data and process each event
jobResultsService.getEvents($scope.job)
.then(events => {
events.forEach(event => {
// get the name in the same format as the data
// coming over the websocket
event.event_name = event.event;
processEvent(event);
var getEvents = function(url) {
jobResultsService.getEvents(url)
.then(events => {
events.results.forEach(event => {
// get the name in the same format as the data
// coming over the websocket
event.event_name = event.event;
processEvent(event);
});
if (events.next) {
getEvents(events.next);
}
});
});
};
getEvents($scope.job.related.job_events);
// process incoming job events
$rootScope.event_socket.on("job_events-" + $scope.job.id, function(data) {

View File

@ -459,7 +459,7 @@
Plays
</div>
<span class="badge List-titleBadge">
{{jobData.playCount || 0}}
{{ playCount || 0}}
</span>
<!-- TASKS COUNT -->
@ -467,7 +467,7 @@
Tasks
</div>
<span class="badge List-titleBadge">
{{jobData.taskCount || 0}}
{{ taskCount || 0}}
</span>
<!-- HOSTS COUNT -->
@ -475,7 +475,7 @@
Hosts
</div>
<span class="badge List-titleBadge">
{{jobData.hostCount || 0}}
{{ hostCount || 0}}
</span>
<!-- ELAPSED TIME -->

View File

@ -35,6 +35,43 @@ export default {
});
return val.promise;
}],
count: ['jobData', 'jobResultsService', 'Rest', '$q', function(jobData, jobResultsService, Rest, $q) {
var defer = $q.defer();
if (jobData.finished) {
// if the job is finished, grab the playbook_on_stats
// role to get the final count
Rest.setUrl(jobData.related.job_events +
"?event=playbook_on_stats");
Rest.get()
.success(function(data) {
defer.resolve({
val: jobResultsService
.getCountsFromStatsEvent(data
.results[0].event_data),
countFinished: true});
})
.error(function() {
defer.resolve({val: {
ok: 0,
skipped: 0,
unreachable: 0,
failures: 0,
changed: 0
}, countFinished: false});
});
} else {
// job isn't finished so just send an empty count and read
// from events
defer.resolve({val: {
ok: 0,
skipped: 0,
unreachable: 0,
failures: 0,
changed: 0
}, countFinished: false});
}
return defer.promise;
}],
jobLabels: ['Rest', 'GetBasePath', '$stateParams', '$q', function(Rest, GetBasePath, $stateParams, $q) {
var getNext = function(data, arr, resolve) {
Rest.setUrl(data.next);

View File

@ -7,13 +7,81 @@
export default ['$q', 'Prompt', '$filter', 'Wait', 'Rest', '$state', 'ProcessErrors', function ($q, Prompt, $filter, Wait, Rest, $state, ProcessErrors) {
var val = {
getEvents: function(job) {
// the playbook_on_stats event returns the count data in a weird format.
// format to what we need!
getCountsFromStatsEvent: function(event_data) {
var hosts = {},
hostsArr;
// iterate over the event_data and populate an object with hosts
// and their status data
Object.keys(event_data).forEach(key => {
// failed passes boolean not integer
if (key === "failed") {
// array of hosts from failed type
hostsArr = Object.keys(event_data[key]);
hostsArr.forEach(host => {
if (!hosts[host]) {
// host has not been added to hosts object
// add now
hosts[host] = {};
}
hosts[host][key] = event_data[key][host];
});
} else {
// array of hosts from each type ("changed", "dark", etc.)
hostsArr = Object.keys(event_data[key]);
hostsArr.forEach(host => {
if (!hosts[host]) {
// host has not been added to hosts object
// add now
hosts[host] = {};
}
if (!hosts[host][key]) {
// host doesn't have key
hosts[host][key] = 0;
}
hosts[host][key] += event_data[key][host];
});
}
});
// use the hosts data populate above to get the count
var count = {
ok : _.filter(hosts, function(o){
return !o.failures && !o.changed && o.ok > 0;
}),
skipped : _.filter(hosts, function(o){
return o.skipped > 0;
}),
unreachable : _.filter(hosts, function(o){
return o.dark > 0;
}),
failures : _.filter(hosts, function(o){
return o.failed === true;
}),
changed : _.filter(hosts, function(o){
return o.changed > 0;
})
};
// turn the count into an actual count, rather than a list of host
// names
Object.keys(count).forEach(key => {
count[key] = count[key].length;
});
return count;
},
getEvents: function(url) {
var val = $q.defer();
Rest.setUrl(job.related.job_events);
Rest.setUrl(url);
Rest.get()
.success(function(data) {
val.resolve(data.results);
val.resolve({results: data.results, next: data.next});
})
.error(function(obj, status) {
ProcessErrors(null, obj, status, null, {