diff --git a/awx/ui/static/js/controllers/JobDetail.js b/awx/ui/static/js/controllers/JobDetail.js index d17e24ef6f..ceed30f3b3 100644 --- a/awx/ui/static/js/controllers/JobDetail.js +++ b/awx/ui/static/js/controllers/JobDetail.js @@ -135,7 +135,7 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log, } scope.removeHostSummaries = scope.$on('LoadHostSummaries', function() { var url = scope.job.related.job_host_summaries + '?'; - url += '&page_size=' + scope.hostSummariesMaxRows + '&order_by=host__name'; + url += '&host__name__isnull=false&page_size=' + scope.hostSummariesMaxRows + '&order_by=host__name'; scope.jobData.hostSummaries = {}; @@ -245,7 +245,12 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log, .success(function(data) { if (data.results.length > 0) { lastEventId = data.results[data.results.length - 1].id; - scope.activeTask = data.results[0].id; + if (scope.liveEventProcessing) { + scope.activeTask = data.results[data.results.length - 1].id; + } + else { + scope.activeTask = data.results[0].id; + } } data.results.forEach(function(event, idx) { var end, elapsed, status, status_text; @@ -294,6 +299,7 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log, failedCount: (event.failed_count) ? event.failed_count : 0, changedCount: (event.changed_count) ? event.changed_count : 0, skippedCount: (event.skipped_count) ? event.skipped_count : 0, + unreachableCount: (event.unreachable_count) ? event.unreachable_count : 0, taskActiveClass: '', hostResults: {} }; @@ -338,7 +344,12 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log, .success( function(data) { if (data.results.length > 0) { lastEventId = data.results[data.results.length - 1].id; - scope.activePlay = data.results[0].id; + if (scope.liveEventProcessing) { + scope.activePlay = data.results[data.results.length - 1].id; + } + else { + scope.activePlay = data.results[0].id; + } } data.results.forEach(function(event, idx) { var status, status_text, start, end, elapsed, ok, changed, failed, skipped; @@ -472,9 +483,16 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log, scope.job_status.status = (data.status === 'waiting' || data.status === 'new') ? 'pending' : data.status; scope.job_status.started = data.started; scope.job_status.status_class = ((data.status === 'error' || data.status === 'failed') && data.job_explanation) ? "alert alert-danger" : ""; - scope.job_status.finished = (data.status === 'successful' || data.status === 'failed' || data.status === 'error') ? data.finished : null; scope.job_status.explanation = data.job_explanation; + if (data.status === 'successful' || data.status === 'failed' || data.status === 'error' || data.status === 'canceled') { + scope.job_status.finished = data.finsished; + scope.liveEventProcessing = false; + } + else { + scope.job_status.finished = null; + } + if (data.started && data.finished) { scope.job_status.elapsed = GetElapsed({ start: data.started, @@ -484,7 +502,7 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log, else { scope.job_status.elapsed = '00:00:00'; } - scope.setSearchAll('host'); + //scope.setSearchAll('host'); scope.$emit('LoadPlays', data.related.job_events); if (!scope.credential_name) { scope.$emit('GetCredentialNames', data); @@ -604,20 +622,6 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log, scope.adjustSize(); }, 500)); - scope.setSearchAll = function(search) { - if (search === 'host') { - scope.search_all_label = 'Host'; - scope.searchAllDisabled = false; - scope.search_all_placeholder = 'Search all by host name'; - } - else { - scope.search_all_label = 'Failures'; - scope.search_all_placeholder = 'Show failed events'; - scope.searchAllDisabled = true; - scope.search_all_placeholder = ''; - } - }; - scope.selectPlay = function(id) { scope.auto_scroll_plays = false; SelectPlay({ @@ -1139,13 +1143,15 @@ function JobDetailController ($rootScope, $scope, $compile, $routeParams, $log, scope.searchAllStatus = ''; nxtPlay = (scope.plays.length > 0) ? scope.plays[0].id : null; } - SelectPlay({ - scope: scope, - id: nxtPlay - }); - ReloadHostSummaryList({ - scope: scope - }); + if (!scope.liveEventProcessing) { + SelectPlay({ + scope: scope, + id: nxtPlay + }); + ReloadHostSummaryList({ + scope: scope + }); + } }; scope.viewHostResults = function(id) { diff --git a/awx/ui/static/js/helpers/JobDetail.js b/awx/ui/static/js/helpers/JobDetail.js index e204a37d4b..f9272559a8 100644 --- a/awx/ui/static/js/helpers/JobDetail.js +++ b/awx/ui/static/js/helpers/JobDetail.js @@ -169,20 +169,6 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge modified: event.modified, message: (event.event_data && event.event_data.res) ? event.event_data.res.msg : '' }); - break; - - // We will respond to the job status change event. No need to do this 2x. - /*case 'playbook_on_stats': - scope.job_status.finished = event.modified; - scope.job_status.elapsed = GetElapsed({ - start: scope.job_status.started, - end: scope.job_status.finished - }); - scope.job_status.status = (event.failed) ? 'failed' : 'successful'; - scope.job_status.status_class = ""; - //LoadHostSummary({ scope: scope, data: event.event_data }); - //DrawGraph({ scope: scope, resize: true }); - break;*/ } }; }]) @@ -417,6 +403,9 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge scope.jobData.hostSummaries[host_id].changed += (status === 'changed') ? 1 : 0; scope.jobData.hostSummaries[host_id].unreachable += (status === 'unreachable') ? 1 : 0; scope.jobData.hostSummaries[host_id].failed += (status === 'failed') ? 1 : 0; + if (status === 'failed' || status === 'unreachable') { + scope.jobData.hostSummaries[host_id].status = 'failed'; + } } else { scope.jobData.hostSummaries[host_id] = { @@ -426,7 +415,7 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge changed: (status === 'changed') ? 1 : 0, unreachable: (status === 'unreachable') ? 1 : 0, failed: (status === 'failed') ? 1 : 0, - status: (status === 'failed') ? 'failed' : 'successful' + status: (status === 'failed' || status === 'unreachable') ? 'failed' : 'successful' }; } @@ -503,7 +492,7 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge if (scope.jobData.plays[scope.activePlay].tasks[task_id] !== undefined) { task = scope.jobData.plays[scope.activePlay].tasks[task_id]; - if (task_id === scope.jobData.plays[scope.activePlay].firstTask && status !== 'unreachable') { + if (task_id === scope.jobData.plays[scope.activePlay].firstTask) { scope.jobData.plays[scope.activePlay].hostCount++; task.hostCount++; } @@ -513,6 +502,8 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge task.changedCount += (status === 'changed') ? 1 : 0; task.successfulCount += (status === 'successful') ? 1 : 0; task.skippedCount += (status === 'skipped') ? 1 : 0; + task.unreachableCount += (status === 'unreachable') ? 1 : 0; + SetTaskStyles({ task: task }); @@ -525,14 +516,13 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge var task = params.task, diff; - //task = scope.jobData.plays[scope.activePlay].tasks[task_id]; - //task.hostCount = task.failedCount + task.changedCount + task.skippedCount + task.successfulCount; 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.skippedPct = (task.hostCount > 0) ? Math.ceil((100 * (task.skippedCount / task.hostCount))) : 0; task.successfulPct = (task.hostCount > 0) ? Math.ceil((100 * (task.successfulCount / task.hostCount))) : 0; + task.unreachablePct = (task.hostCount > 0) ? Math.ceil((100 * (task.unreachableCount / task.hostCount))) : 0; - diff = (task.failedPct + task.changedPct + task.skippedPct + task.successfulPct) - 100; + diff = (task.failedPct + task.changedPct + task.skippedPct + task.successfulPct + task.unreachablePct) - 100; if (diff > 0) { if (task.failedPct > diff) { task.failedPct = task.failedPct - diff; @@ -546,11 +536,15 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge else if (task.successfulPct > diff) { task.successfulPct = task.successfulPct - diff; } + else if (task.unreachablePct > diff) { + task.unreachablePct = task.unreachablePct - diff; + } } task.successfulStyle = (task.successfulPct > 0) ? { 'display': 'inline-block', 'width': task.successfulPct + "%" } : { 'display': 'none' }; task.changedStyle = (task.changedPct > 0) ? { 'display': 'inline-block', 'width': task.changedPct + "%" } : { 'display': 'none' }; task.skippedStyle = (task.skippedPct > 0) ? { 'display': 'inline-block', 'width': task.skippedPct + "%" } : { 'display': 'none' }; task.failedStyle = (task.failedPct > 0) ? { 'display': 'inline-block', 'width': task.failedPct + "%" } : { 'display': 'none' }; + task.unreachableStyle = (task.unreachablePct > 0) ? { 'display': 'inline-block', 'width': task.unreachablePct + "%" } : { 'display': 'none' }; }; }]) @@ -667,6 +661,7 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge failedCount: (event.failed_count) ? event.failed_count : 0, changedCount: (event.changed_count) ? event.changed_count : 0, skippedCount: (event.skipped_count) ? event.skipped_count : 0, + unreachableCount: (event.unreachable_count) ? event.unreachable_count : 0, taskActiveClass: '' }); @@ -823,7 +818,7 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge url = scope.job.related.job_host_summaries + '?'; url += (scope.search_all_hosts_name) ? 'host__name__icontains=' + scope.search_all_hosts_name + '&': ''; url += (scope.searchAllStatus === 'failed') ? 'failed=true&' : ''; - url += 'page_size=' + scope.hostSummariesMaxRows + '&order_by=host__name'; + url += '&page_size=' + scope.hostSummariesMaxRows + '&order_by=host__name'; scope.hosts = []; @@ -904,7 +899,7 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge graph_data.push({ label: 'Unreachable', value: (scope.host_summary.unreachable === scope.host_summary.total) ? 1 : scope.host_summary.unreachable, - color: '#A9A9A9' + color: '#FF3366' }); } if (scope.host_summary.failed) { @@ -975,7 +970,7 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge keys = Object.keys(tasks); keys.reverse(); newKeys = []; - for (idx=0; idx < scope.tasksMaxRows && idx < keys.length; idx++) { + for (idx=0; result.length < scope.tasksMaxRows && idx < keys.length; idx++) { newKeys.push(keys[idx]); } newKeys.sort(); @@ -1012,8 +1007,15 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge // a must be equal to b return 0; }); - while (idx < keys.length && idx < scope.hostResultsMaxRows) { - result.unshift(hostResults[keys[idx]]); + while (idx < keys.length && result.length < scope.hostResultsMaxRows) { + if (scope.searchAllStatus === 'failed') { + if (hostResults[keys[idx]].status === 'failed') { + result.unshift(hostResults[keys[idx]]); + } + } + else { + result.unshift(hostResults[keys[idx]]); + } idx++; } } @@ -1045,8 +1047,17 @@ function($rootScope, $log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, Ge return 0; }); - while (idx < keys.length && idx < scope.hostSummariesMaxRows) { - result.push(hostSummaries[keys[idx]]); + console.log(hostSummaries); + + while (idx < keys.length && result.length < scope.hostSummariesMaxRows) { + if (scope.searchAllStatus === 'failed') { + if (hostSummaries[keys[idx]].status === 'failed') { + result.push(hostSummaries[keys[idx]]); + } + } + else { + result.push(hostSummaries[keys[idx]]); + } idx++; } } diff --git a/awx/ui/static/less/ansible-ui.less b/awx/ui/static/less/ansible-ui.less index 8813fefc91..4f026634ad 100644 --- a/awx/ui/static/less/ansible-ui.less +++ b/awx/ui/static/less/ansible-ui.less @@ -18,8 +18,9 @@ @info: #d9edf7; /* alert info background color */ @info-border: #bce8f1; /* alert info border color */ @info-color: #3a87ad; -@red: #aa0000; // Ansible Unreachable +@red: #aa0000; // Ansible Failed @red-hover: #AE3F3A; +@unreachable: #FF3366; @changed: #FF9900; // Ansible Changed @skipped: #00aaaa; // Ansible Skipped @warning: #FF9900; @@ -1022,11 +1023,14 @@ input[type="checkbox"].checkbox-no-label { .icon-job-stopped, .icon-job-error, .icon-job-failed, - .icon-job-canceled, - .icon-job-unreachable { + .icon-job-canceled { color: @red; } + .icon-job-unreachable { + color: @unreachable; + } + .icon-job-none, .icon-job-pending, .icon-job-waiting, diff --git a/awx/ui/static/less/job-details.less b/awx/ui/static/less/job-details.less index a0740e42ff..76a801df07 100644 --- a/awx/ui/static/less/job-details.less +++ b/awx/ui/static/less/job-details.less @@ -11,7 +11,7 @@ @successful-hosts-color: @green; @changed-hosts-color: @changed; @skipped-hosts-color: @skipped; -@unreachable-hosts-color: #A9A9A9; +@unreachable-hosts-color: @unreachable; .job_summary { .table { @@ -73,7 +73,7 @@ background-color: @unreachable-hosts-color; } .unreachable-hosts-color { - color: @grey; + color: @unreachable-hosts-color; } .job_well { diff --git a/awx/ui/static/lib/ansible/filters.js b/awx/ui/static/lib/ansible/filters.js index 066ec54397..1334237370 100644 --- a/awx/ui/static/lib/ansible/filters.js +++ b/awx/ui/static/lib/ansible/filters.js @@ -67,4 +67,24 @@ angular.module('AWFilters', []) } return input; }; + }]) + + .filter('FilterFailedEvents', [ function() { + return function(input, liveEventProcessing, searchAllStatus) { + var results = []; + if (liveEventProcessing) { + // while live events are happening, we don't want angular to filter out anything + return input; + } + else if (searchAllStatus === 'failed') { + // filter by failed + input.forEach(function(row) { + if (row.status === 'failed') { + results.push(row); + } + }); + return results; + } + return input; + }; }]); \ No newline at end of file diff --git a/awx/ui/static/partials/job_detail.html b/awx/ui/static/partials/job_detail.html index 177cf1b3e0..a65c5d2097 100644 --- a/awx/ui/static/partials/job_detail.html +++ b/awx/ui/static/partials/job_detail.html @@ -83,7 +83,7 @@
-