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 * All Rights Reserved
*************************************************/ *************************************************/
export default [function(){ export default ['jobResultsService', function(jobResultsService){
var val = {}; 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 // Get the count of the last event
var getPreviousCount = function(id) { var getPreviousCount = function(counter) {
// get the ids of all the queue // 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 // iterate backwards to find the last count
while(ids.indexOf(id - 1) > -1) { while(counters.indexOf(counter - 1) > -1) {
id = id - 1; counter = counter - 1;
if (val.queue[id].count) { if (val.queue[counter].count) {
// need to create a new copy of count when returning // need to create a new copy of count when returning
// so that it is accurate for the particular event // 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 // munge the raw event from the backend into the event_queue's format
var mungeEvent = function(event) { var mungeEvent = function(event) {
var mungedEvent = { var mungedEvent = {
counter: event.counter,
id: event.id, id: event.id,
processed: false, processed: false,
name: event.event_name, name: event.event_name
count: getPreviousCount(event.id)
}; };
if (event.event_name === 'playbook_on_start') { if (event.event_name === 'playbook_on_start') {
// sets count initially so this is a change // sets count initially so this is a change
mungedEvent.count = getPreviousCount(mungedEvent.counter);
mungedEvent.changes = ['count']; mungedEvent.changes = ['count'];
} else if (event.event_name === 'runner_on_ok' || } else if (event.event_name === 'runner_on_ok' ||
event.event_name === 'runner_on_async_ok') { event.event_name === 'runner_on_async_ok') {
mungedEvent.count = getPreviousCount(mungedEvent.counter);
mungedEvent.count.ok++; mungedEvent.count.ok++;
mungedEvent.changes = ['count']; mungedEvent.changes = ['count'];
} else if (event.event_name === 'runner_on_skipped') { } else if (event.event_name === 'runner_on_skipped') {
mungedEvent.count = getPreviousCount(mungedEvent.counter);
mungedEvent.count.skipped++; mungedEvent.count.skipped++;
mungedEvent.changes = ['count']; mungedEvent.changes = ['count'];
} else if (event.event_name === 'runner_on_unreachable') { } else if (event.event_name === 'runner_on_unreachable') {
mungedEvent.count = getPreviousCount(mungedEvent.counter);
mungedEvent.count.unreachable++; mungedEvent.count.unreachable++;
mungedEvent.changes = ['count']; mungedEvent.changes = ['count'];
} else if (event.event_name === 'runner_on_error' || } else if (event.event_name === 'runner_on_error' ||
event.event_name === 'runner_on_async_failed') { event.event_name === 'runner_on_async_failed') {
mungedEvent.count = getPreviousCount(mungedEvent.counter);
mungedEvent.count.failed++; mungedEvent.count.failed++;
mungedEvent.changes = ['count']; mungedEvent.changes = ['count'];
} else if (event.event_name === 'playbook_on_stats') { } else if (event.event_name === 'playbook_on_stats') {
// get the data for populating the host status bar // get the data for populating the host status bar
mungedEvent.count = getCountsFromStatsEvent(event.event_data); mungedEvent.count = jobResultsService
mungedEvent.changes = ['count']; .getCountsFromStatsEvent(event.event_data);
mungedEvent.changes = ['count', 'countFinished'];
} }
return mungedEvent; return mungedEvent;
}; };
@@ -143,15 +80,19 @@ export default [function(){
}, },
// populates the event queue // populates the event queue
populate: function(event) { populate: function(event) {
var mungedEvent = mungeEvent(event); // don't populate the event if it's already been added either
val.queue[event.id] = mungedEvent; // 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 // the event has been processed in the view and should be marked as
// completed in the queue // completed in the queue
markProcessed: function(event) { markProcessed: function(event) {
val.queue[event.id].processed = true; val.queue[event.counter].processed = true;
} }
}; };

View File

@@ -7,41 +7,46 @@
margin-top: 10px; 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 { .HostStatusBar-ok {
background-color: @default-succ; background-color: @default-succ;
display: flex; display: flex;
flex: 0 0 auto; flex: 0 0 auto;
height: 5px;
} }
.HostStatusBar-changed { .HostStatusBar-changed {
background-color: @default-warning; background-color: @default-warning;
flex: 0 0 auto; flex: 0 0 auto;
height: 5px;
} }
.HostStatusBar-unreachable { .HostStatusBar-unreachable {
background-color: @default-unreachable; background-color: @default-unreachable;
flex: 0 0 auto; flex: 0 0 auto;
height: 5px;
} }
.HostStatusBar-failures { .HostStatusBar-failures {
background-color: @default-err; background-color: @default-err;
flex: 0 0 auto; flex: 0 0 auto;
height: 5px;
} }
.HostStatusBar-skipped { .HostStatusBar-skipped {
background-color: @default-link; background-color: @default-link;
flex: 0 0 auto; flex: 0 0 auto;
height: 5px;
} }
.HostStatusBar-noData { .HostStatusBar-noData {
background-color: @default-icon-hov; background-color: @default-icon-hov;
flex: 1 0 auto; flex: 1 0 auto;
height: 5px;
} }
.HostStatusBar-tooltipLabel { .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 getTowerLinks = function() {
var getTowerLink = function(key) { var getTowerLink = function(key) {
if ($scope.job.related[key]) { if ($scope.job.related[key]) {
@@ -34,6 +34,11 @@ export default ['jobData', 'jobDataOptions', 'jobLabels', '$scope', 'ParseTypeCh
$scope.verbosity_label = getTowerLabel('verbosity'); $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 // put initially resolved request data on scope
$scope.job = jobData; $scope.job = jobData;
$scope.jobOptions = jobDataOptions.actions.GET; $scope.jobOptions = jobDataOptions.actions.GET;
@@ -66,6 +71,11 @@ export default ['jobData', 'jobDataOptions', 'jobLabels', '$scope', 'ParseTypeCh
jobResultsService.cancelJob($scope.job); 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 // EVENT STUFF BELOW
// just putting the event queue on scope so it can be inspected in the // 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 // make changes to ui based on the event returned from the queue
if (mungedEvent.changes) { if (mungedEvent.changes) {
mungedEvent.changes.forEach(change => { mungedEvent.changes.forEach(change => {
if (change === 'count') { if (change === 'count' && !$scope.countFinished) {
$scope.count = mungedEvent.count; $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 // grab completed event data and process each event
jobResultsService.getEvents($scope.job) var getEvents = function(url) {
.then(events => { jobResultsService.getEvents(url)
events.forEach(event => { .then(events => {
// get the name in the same format as the data events.results.forEach(event => {
// coming over the websocket // get the name in the same format as the data
event.event_name = event.event; // coming over the websocket
processEvent(event); event.event_name = event.event;
processEvent(event);
});
if (events.next) {
getEvents(events.next);
}
}); });
}); };
getEvents($scope.job.related.job_events);
// process incoming job events // process incoming job events
$rootScope.event_socket.on("job_events-" + $scope.job.id, function(data) { $rootScope.event_socket.on("job_events-" + $scope.job.id, function(data) {

View File

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

View File

@@ -35,6 +35,43 @@ export default {
}); });
return val.promise; 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) { jobLabels: ['Rest', 'GetBasePath', '$stateParams', '$q', function(Rest, GetBasePath, $stateParams, $q) {
var getNext = function(data, arr, resolve) { var getNext = function(data, arr, resolve) {
Rest.setUrl(data.next); 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) { export default ['$q', 'Prompt', '$filter', 'Wait', 'Rest', '$state', 'ProcessErrors', function ($q, Prompt, $filter, Wait, Rest, $state, ProcessErrors) {
var val = { 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(); var val = $q.defer();
Rest.setUrl(job.related.job_events); Rest.setUrl(url);
Rest.get() Rest.get()
.success(function(data) { .success(function(data) {
val.resolve(data.results); val.resolve({results: data.results, next: data.next});
}) })
.error(function(obj, status) { .error(function(obj, status) {
ProcessErrors(null, obj, status, null, { ProcessErrors(null, obj, status, null, {