diff --git a/awx/ui/static/js/controllers/Inventories.js b/awx/ui/static/js/controllers/Inventories.js
index a4b237fb6a..acf62cf560 100644
--- a/awx/ui/static/js/controllers/Inventories.js
+++ b/awx/ui/static/js/controllers/Inventories.js
@@ -471,11 +471,11 @@ InventoriesAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log
-function InventoriesEdit($scope, $location, $routeParams, $compile, GenerateList, ClearScope, InventoryGroups, InventoryHosts, BuildTree, Wait,
+function InventoriesEdit($scope, $location, $routeParams, $compile, $log, GenerateList, ClearScope, InventoryGroups, InventoryHosts, BuildTree, Wait,
GetSyncStatusMsg, InjectHosts, HostsReload, GroupsEdit, GroupsDelete, Breadcrumbs, LoadBreadCrumbs, Empty, Rest, ProcessErrors,
InventoryUpdate, Alert, ToggleChildren, ViewUpdateStatus, GroupsCancelUpdate, Find, EditInventoryProperties, HostsEdit,
HostsDelete, ToggleHostEnabled, CopyMoveGroup, CopyMoveHost, Stream, GetBasePath, ShowJobSummary, ApplyEllipsis, WatchInventoryWindowResize,
- HelpDialog, InventoryGroupsHelp, Store, ViewJob) {
+ HelpDialog, InventoryGroupsHelp, Store, ViewJob, Socket) {
ClearScope();
@@ -643,6 +643,38 @@ function InventoriesEdit($scope, $location, $routeParams, $compile, GenerateList
}
};
+ if ($scope.removeWatchUpdateStatus) {
+ $scope.removeWatchUpdateStatus();
+ }
+ $scope.removeWatchUpdateStatus = $scope.$on('WatchUpdateStatus', function(e, job_id, group_id, tree_id) {
+ var io = Socket({ scope: $scope, endpoint: "jobs" }),
+ group = Find({ list: $scope.groups, key: 'id', val: tree_id }),
+ stat;
+ $log.debug('Watching for updates to job: ' + job_id + ' for group: ' + group_id + ' ' + group.name);
+ io.init();
+ io.on("status_changed", function(data) {
+ Wait('stop');
+ if (data.status === "failed" || data.status === "successful") {
+ $log.debug('Update completed. Refreshing the tree.');
+ $scope.refreshGroups(tree_id, group_id);
+ }
+ else {
+ $log.debug('Status changed to: ' + data.status);
+ stat = GetSyncStatusMsg({
+ status: data.status,
+ has_inventory_sources: group.has_inventory_sources,
+ source: group.source
+ });
+ $log.debug('changing tooltip to: ' + stat.tooltip);
+ group.status = data.status;
+ group.status_class = stat['class'];
+ group.status_tooltip = stat.tooltip;
+ group.launch_tooltip = stat.launch_tip;
+ group.launch_class = stat.launch_class;
+ }
+ });
+ });
+
$scope.createGroup = function () {
GroupsEdit({
scope: $scope,
@@ -813,10 +845,10 @@ function InventoriesEdit($scope, $location, $routeParams, $compile, GenerateList
}
-InventoriesEdit.$inject = ['$scope', '$location', '$routeParams', '$compile', 'GenerateList', 'ClearScope', 'InventoryGroups', 'InventoryHosts',
+InventoriesEdit.$inject = ['$scope', '$location', '$routeParams', '$compile', '$log', 'GenerateList', 'ClearScope', 'InventoryGroups', 'InventoryHosts',
'BuildTree', 'Wait', 'GetSyncStatusMsg', 'InjectHosts', 'HostsReload', 'GroupsEdit', 'GroupsDelete', 'Breadcrumbs',
'LoadBreadCrumbs', 'Empty', 'Rest', 'ProcessErrors', 'InventoryUpdate', 'Alert', 'ToggleChildren', 'ViewUpdateStatus', 'GroupsCancelUpdate',
'Find', 'EditInventoryProperties', 'HostsEdit', 'HostsDelete', 'ToggleHostEnabled', 'CopyMoveGroup', 'CopyMoveHost',
'Stream', 'GetBasePath', 'ShowJobSummary', 'ApplyEllipsis', 'WatchInventoryWindowResize', 'HelpDialog', 'InventoryGroupsHelp', 'Store',
- 'ViewJob'
+ 'ViewJob', 'Socket'
];
diff --git a/awx/ui/static/js/controllers/JobDetail.js b/awx/ui/static/js/controllers/JobDetail.js
index 166817435c..b418305453 100644
--- a/awx/ui/static/js/controllers/JobDetail.js
+++ b/awx/ui/static/js/controllers/JobDetail.js
@@ -46,7 +46,7 @@ function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadc
}
});
return results;
- }
+ };
// Reduce an array of objects down to just the bits we want from each object by
// passing in a function that returns just those parts.
@@ -59,7 +59,7 @@ function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadc
results.push(parameterFunction(row));
});
return results;
- }
+ };
// Apply each event to the view
@@ -67,8 +67,6 @@ function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadc
scope.removeEventsReady();
}
scope.removeEventsReady = scope.$on('EventsReady', function(e, events) {
- console.log('Inside EventsReady!');
- console.log(events);
DigestEvents({
scope: scope,
events: events
@@ -78,17 +76,14 @@ function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadc
event_socket.on("job_events-" + job_id, function(data) {
var matches;
data.id = data.event_id;
- console.log(data);
if (api_complete) {
- matches = processed_events.find(function(x) { return x === data.id });
+ matches = processed_events.find(function(x) { return x === data.id; });
if (matches.length === 0) {
// event not processed
- console.log('process event: ' + data.id);
scope.$emit('EventsReady', [ data ]);
}
}
else {
- console.log('queue event: ' + data.id);
event_queue.push(data);
}
});
@@ -113,8 +108,6 @@ function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadc
});
return (!matched); //return true when event.id not in the list of processed_events
});
- console.log('processing queued events: ');
- console.log(events.reduce(function(x) { return x.id }));
if (events.length > 0) {
scope.$emit('EventsReady', events);
api_complete = true;
@@ -133,7 +126,7 @@ function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadc
Rest.setUrl(next);
Rest.get()
.success(function(data) {
- processed_events = processed_events.concat( data.results.reduce(function(x) { return x.id }) );
+ processed_events = processed_events.concat( data.results.reduce(function(x) { return x.id; }) );
scope.$emit('EventsReady', data.results);
if (data.next) {
scope.$emit('JobReady', data.next);
@@ -206,7 +199,7 @@ function JobDetailController ($scope, $compile, $routeParams, ClearScope, Breadc
// In the case that the job is already completed, or an error already happened,
// populate scope.job_status info
- scope.job_status.status = data.status;
+ scope.job_status.status = 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.finished;
diff --git a/awx/ui/static/js/helpers/Groups.js b/awx/ui/static/js/helpers/Groups.js
index acba13de3a..82415f5ece 100644
--- a/awx/ui/static/js/helpers/Groups.js
+++ b/awx/ui/static/js/helpers/Groups.js
@@ -137,9 +137,8 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
has_inventory_sources = params.has_inventory_sources,
launch_class = '',
launch_tip = 'Start sync process',
-
stat, stat_class, status_tip;
-
+
stat = status;
stat_class = stat;
@@ -157,14 +156,25 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
status_tip = 'Cloud source not configured. Click to update.';
launch_tip = 'Cloud source not configured.';
break;
+ case 'canceled':
+ status_tip = 'Sync canceled. Click to view log.';
+ break;
case 'failed':
status_tip = 'Sync failed. Click to view log.';
break;
case 'successful':
status_tip = 'Sync completed. Click to view log.';
break;
+ case 'pending':
+ status_tip = 'Sync pending.';
+ launch_class = "btn-disabled";
+ launch_tip = "Sync pending";
+ break;
case 'updating':
- status_tip = 'Sync running';
+ case 'running':
+ launch_class = "btn-disabled";
+ launch_tip = "Sync running";
+ status_tip = "Sync running. Click to view log.";
break;
}
@@ -268,13 +278,11 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
Rest.post()
.success(function () {
Wait('stop');
- Alert('Inventory Sync Cancelled', 'Request to cancel the sync process was submitted to the task manger. ' +
- 'Click the button to monitor the status.', 'alert-info');
+ //Alert('Inventory Sync Cancelled', 'Request to cancel the sync process was submitted to the task manger. ' +
+ // 'Click the button to monitor the status.', 'alert-info');
})
.error(function (data, status) {
- Wait('stop');
- ProcessErrors(scope, data, status, null, {
- hdr: 'Error!',
+ ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. POST status: ' + status
});
});
@@ -292,16 +300,17 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
.success(function (data) {
if (data.can_cancel) {
scope.$emit('CancelUpdate', url);
- } else {
+ //} else {
+ // Wait('stop');
+ // Alert('Cancel Inventory Sync', 'The sync process completed. Click the button to view ' +
+ // 'the latest status.', 'alert-info');
+ }
+ else {
Wait('stop');
- Alert('Cancel Inventory Sync', 'The sync process completed. Click the button to view ' +
- 'the latest status.', 'alert-info');
}
})
.error(function (data, status) {
- Wait('stop');
- ProcessErrors(scope, data, status, null, {
- hdr: 'Error!',
+ ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. GET status: ' + status
});
});
@@ -323,17 +332,11 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
scope.$emit('CheckCancel', data.related.last_update, data.related.current_update);
})
.error(function (data, status) {
- Wait('stop');
- ProcessErrors(scope, data, status, null, {
- hdr: 'Error!',
+ ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + group.related.inventory_source + ' failed. GET status: ' + status
});
});
- } else {
- Alert('Cancel Inventory Sync', 'The sync process completed. Click the to' +
- ' view the latest status.', 'alert-info');
}
-
};
}
])
diff --git a/awx/ui/static/js/helpers/JobDetail.js b/awx/ui/static/js/helpers/JobDetail.js
index f1de3a9230..ee75ef91ee 100644
--- a/awx/ui/static/js/helpers/JobDetail.js
+++ b/awx/ui/static/js/helpers/JobDetail.js
@@ -40,9 +40,8 @@
angular.module('JobDetailHelper', ['Utilities', 'RestServices'])
.factory('DigestEvents', ['UpdatePlayStatus', 'UpdatePlayNoHostsMatched', 'UpdateHostStatus', 'UpdatePlayChild', 'AddHostResult', 'SelectPlay', 'SelectTask',
- 'GetHostCount', 'GetElapsed', 'UpdateJobStatus',
-function(UpdatePlayStatus, UpdatePlayNoHostsMatched, UpdateHostStatus, UpdatePlayChild, AddHostResult, SelectPlay, SelectTask, GetHostCount, GetElapsed,
- UpdateJobStatus) {
+ 'GetHostCount', 'GetElapsed',
+function(UpdatePlayStatus, UpdatePlayNoHostsMatched, UpdateHostStatus, UpdatePlayChild, AddHostResult, SelectPlay, SelectTask, GetHostCount, GetElapsed) {
return function(params) {
var scope = params.scope,
@@ -89,7 +88,7 @@ function(UpdatePlayStatus, UpdatePlayNoHostsMatched, UpdateHostStatus, UpdatePla
failedCount: 0,
changedCount: 0,
skippedCount: 0,
- successfulStyle: { display: 'none'},
+ successfulStyle: { display: 'none'},
failedStyle: { display: 'none' },
changedStyle: { display: 'none' },
skippedStyle: { display: 'none' }
@@ -125,7 +124,7 @@ function(UpdatePlayStatus, UpdatePlayNoHostsMatched, UpdateHostStatus, UpdatePla
failedCount: 0,
changedCount: 0,
skippedCount: 0,
- successfulStyle: { display: 'none'},
+ successfulStyle: { display: 'none'},
failedStyle: { display: 'none' },
changedStyle: { display: 'none' },
skippedStyle: { display: 'none' }
@@ -338,27 +337,24 @@ function(UpdatePlayStatus, UpdatePlayNoHostsMatched, UpdateHostStatus, UpdatePla
return function(params) {
var scope = params.scope,
failed = params.failed,
- modified = params.modified;
+ modified = params.modified,
started = params.started;
- if (failed && scope.job_status.status !== 'failed' && scope.job_status.status !== 'error'
- && scope.job_status.status !== 'canceled') {
+ if (failed && scope.job_status.status !== 'failed' && scope.job_status.status !== 'error' &&
+ scope.job_status.status !== 'canceled') {
scope.job_status.status = 'error';
}
if (!Empty(modified)) {
scope.job_status.finished = modified;
}
if (!Empty(started) && Empty(scope.job_status.started)) {
- scope.job_status.started = started;
- }
+ scope.job_status.started = started;
+ }
if (!Empty(scope.job_status.finished) && !Empty(scope.job_status.started)) {
- console.log('scope.job_status.started: ' + scope.job_status.started);
- console.log('scope.job_status.finished: ' + scope.job_status.finished);
scope.job_status.elapsed = GetElapsed({
start: scope.job_status.started,
end: scope.job_status.finished
});
- console.log('elapsed: ' + scope.job_status.elapsed);
}
};
}])
@@ -385,11 +381,11 @@ function(UpdatePlayStatus, UpdatePlayNoHostsMatched, UpdateHostStatus, UpdatePla
start: play.created,
end: modified
});
- /*UpdateJobStatus({
+ UpdateJobStatus({
scope: scope,
failed: failed,
modified: modified
- });*/
+ });
return false;
}
return true;
@@ -407,7 +403,7 @@ function(UpdatePlayStatus, UpdatePlayNoHostsMatched, UpdateHostStatus, UpdatePla
scope.tasks.every(function (task, i) {
if (task.id === id) {
if (failed) {
- scope.tasks[i].status = 'failed';
+ scope.tasks[i].status = 'failed';
}
else if (task.status !== 'changed' && task.status !== 'failed') {
// once the status becomes 'changed' or 'failed' don't modify it
diff --git a/awx/ui/static/js/helpers/JobSubmission.js b/awx/ui/static/js/helpers/JobSubmission.js
index 5ca4bcfd33..38dfb169e9 100644
--- a/awx/ui/static/js/helpers/JobSubmission.js
+++ b/awx/ui/static/js/helpers/JobSubmission.js
@@ -20,8 +20,8 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential
Wait('start');
Rest.setUrl(url);
Rest.post(passwords)
- .success(function () {
- scope.$emit(callback);
+ .success(function(data) {
+ scope.$emit(callback, data);
})
.error(function (data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
@@ -445,10 +445,10 @@ function($location, Wait, GetBasePath, LookUpInit, JobTemplateForm, CredentialLi
url = params.url,
group_id = params.group_id,
tree_id = params.tree_id,
- base = $location.path().replace(/^\//, '').split('/')[0],
+ //base = $location.path().replace(/^\//, '').split('/')[0],
inventory_source;
- if (scope.removeHostReloadComplete) {
+ /*if (scope.removeHostReloadComplete) {
scope.removeHostReloadComplete();
}
scope.removeHostReloadComplete = scope.$on('HostReloadComplete', function () {
@@ -458,13 +458,44 @@ function($location, Wait, GetBasePath, LookUpInit, JobTemplateForm, CredentialLi
if (scope.removeHostReloadComplete) {
scope.removeHostReloadComplete();
}
- });
+ });*/
+
+ function getJobID(url) {
+ var result='';
+ url.split(/\//).every(function(path) {
+ if (/^\d+$/.test(path)) {
+ result = path;
+ return false;
+ }
+ return true;
+ });
+ return result;
+ }
if (scope.removeUpdateSubmitted) {
scope.removeUpdateSubmitted();
}
scope.removeUpdateSubmitted = scope.$on('UpdateSubmitted', function () {
- setTimeout(function() {
+ // Get the current job
+ var path = url.replace(/update\/$/,'');
+ Rest.setUrl(path);
+ Rest.get()
+ .success(function(data) {
+ if (data.related.current_job) {
+ scope.$emit('WatchUpdateStatus', getJobID(data.related.current_job), group_id, tree_id);
+ }
+ else {
+ Wait('stop');
+ }
+ })
+ .error(function(data, status) {
+ ProcessErrors(scope, data, status, null, { hdr: 'Error!',
+ msg: 'Failed to get inventory source ' + url + ' GET returned: ' + status });
+ });
+
+ //console.log('job submitted. callback returned: ');
+ //console.log(data);
+ /*setTimeout(function() {
if (base === 'jobs') {
scope.refreshJobs();
}
@@ -476,7 +507,7 @@ function($location, Wait, GetBasePath, LookUpInit, JobTemplateForm, CredentialLi
scope.refresh();
}
scope.$emit('HostReloadComplete');
- }, 300);
+ }, 300);*/
});
if (scope.removePromptForPasswords) {
diff --git a/awx/ui/static/js/lists/InventoryGroups.js b/awx/ui/static/js/lists/InventoryGroups.js
index a41084db04..e2bbdd3616 100644
--- a/awx/ui/static/js/lists/InventoryGroups.js
+++ b/awx/ui/static/js/lists/InventoryGroups.js
@@ -51,11 +51,11 @@ angular.module('InventoryGroupsDefinition', [])
awToolTip: "Edit inventory properties",
ngClick: 'editInventoryProperties()'
},
- refresh: {
+ /*refresh: {
mode: 'all',
awToolTip: "Refresh the page",
ngClick: "refreshGroups()"
- },
+ },*/
stream: {
ngClick: "showGroupActivity()",
awToolTip: "View Activity Stream",
@@ -75,9 +75,9 @@ angular.module('InventoryGroupsDefinition', [])
ngClick: "viewUpdateStatus(group.id, group.group_id)",
ngShow: "group.id > 1", // hide for all hosts
awToolTip: "{{ group.status_tooltip }}",
- dataTipWatch: "group.launch_tooltip",
+ dataTipWatch: "group.status_tooltip",
iconClass: "{{ 'fa icon-cloud-' + group.status_class }}",
- ngClass: "group.launch_class",
+ ngClass: "group.status_class",
dataPlacement: "top"
},
failed_hosts: {
diff --git a/awx/ui/static/less/ansible-ui.less b/awx/ui/static/less/ansible-ui.less
index 218b35f6fd..71968627e6 100644
--- a/awx/ui/static/less/ansible-ui.less
+++ b/awx/ui/static/less/ansible-ui.less
@@ -1126,7 +1126,9 @@ input[type="checkbox"].checkbox-no-label {
.icon-cloud-updating:before,
.icon-cloud-running:before,
.icon-cloud-successful:before,
+ .icon-cloud-pending:before,
.icon-cloud-failed:before,
+ .icon-cloud-canceled:before,
.icon-cloud-error:before {
content: "\f0c2";
}
@@ -1146,6 +1148,7 @@ input[type="checkbox"].checkbox-no-label {
.icon-cloud-updating,
.icon-cloud-running,
.icon-cloud-successful,
+ .icon-cloud-pending,
a.icon-cloud-updating:hover,
a.icon-cloud-successful:hover {
color: @green;
@@ -1153,12 +1156,14 @@ input[type="checkbox"].checkbox-no-label {
.icon-cloud-failed,
.icon-cloud-error,
+ .icon-cloud-canceled,
a.icon-cloud-failed:hover {
color: @red;
}
.icon-cloud-updating,
- .icon-cloud-running {
+ .icon-cloud-running,
+ .icon-cloud-pending {
.pulsate();
}