Merge pull request #6334 from mabashian/5815-inventory-sync

Inventory sync fixes
This commit is contained in:
Michael Abashian 2017-05-24 17:48:15 -04:00 committed by GitHub
commit 606a47c324
9 changed files with 115 additions and 31 deletions

View File

@ -0,0 +1,3 @@
.Inventories-hostStatus {
margin-left: 5px;
}

View File

@ -22,16 +22,22 @@ export default ['i18n', function(i18n) {
fields: {
status: {
label: '',
columnClass: 'col-md-1 col-sm-2 col-xs-2 List-staticColumn--smallStatus',
columnClass: 'List-staticColumn--mediumStatus',
nosort: true,
ngClick: "null",
iconOnly: true,
excludeModal: true,
icons: [{
icon: "{{ 'icon-cloud-' + inventory.syncStatus }}",
awToolTip: "{{ inventory.syncTip }}",
awTipPlacement: "right",
ngClick: "showSourceSummary($event, inventory.id)",
ngClass: "inventory.launch_class"
},{
icon: "{{ 'icon-job-' + inventory.hostsStatus }}",
awToolTip: false,
ngClick: "showHostSummary($event, inventory.id)",
ngClass: ""
ngClass: "inventory.host_status_class"
}]
},
name: {
@ -87,6 +93,13 @@ export default ['i18n', function(i18n) {
columnClass: 'col-md-2 col-sm-3 col-xs-4',
inventory_update: {
mode: 'all',
ngClick: 'syncInventory(inventory)',
awToolTip: i18n._('Sync all inventory sources'),
ngShow: "inventory.kind === '' && inventory.has_inventory_sources",
dataPlacement: "top",
},
edit: {
label: i18n._('Edit'),
ngClick: 'editInventory(inventory)',

View File

@ -12,7 +12,8 @@
function InventoriesList($scope, $rootScope, $location,
$compile, $filter, Rest, InventoryList, Prompt,
ProcessErrors, GetBasePath, Wait, Find, Empty, $state, rbacUiControlService, Dataset) {
ProcessErrors, GetBasePath, Wait, Find, Empty, $state,
rbacUiControlService, Dataset, InventoryUpdate) {
let list = InventoryList,
defaultUrl = GetBasePath('inventory');
@ -37,7 +38,6 @@ function InventoriesList($scope, $rootScope, $location,
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
$rootScope.flashMessage = null;
}
function processInventoryRow(inventory) {
@ -47,10 +47,12 @@ function InventoriesList($scope, $rootScope, $location,
function buildStatusIndicators(inventory){
inventory.launch_class = "";
inventory.host_status_class = "Inventories-hostStatus";
if (inventory.has_inventory_sources) {
if (inventory.inventory_sources_with_failures > 0) {
inventory.syncStatus = 'error';
inventory.syncTip = inventory.inventory_sources_with_failures + ' groups with sync failures. Click for details';
inventory.syncTip = inventory.inventory_sources_with_failures + ' sources with sync failures. Click for details';
}
else {
inventory.syncStatus = 'successful';
@ -62,6 +64,7 @@ function InventoriesList($scope, $rootScope, $location,
inventory.syncTip = 'Not configured for inventory sync.';
inventory.launch_class = "btn-disabled";
}
if (inventory.has_active_failures) {
inventory.hostsStatus = 'error';
inventory.hostsTip = inventory.hosts_with_active_failures + ' hosts with failures. Click for details.';
@ -148,10 +151,10 @@ function InventoriesList($scope, $rootScope, $location,
attachElem(event, html, title);
});
if ($scope.removeGroupSummaryReady) {
$scope.removeGroupSummaryReady();
if ($scope.removeSourceSummaryReady) {
$scope.removeSourceSummaryReady();
}
$scope.removeGroupSummaryReady = $scope.$on('GroupSummaryReady', function(e, event, inventory, data) {
$scope.removeSourceSummaryReady = $scope.$on('SourceSummaryReady', function(e, event, inventory, data) {
var html, title;
Wait('stop');
@ -162,7 +165,7 @@ function InventoriesList($scope, $rootScope, $location,
html += "<tr>";
html += "<th>Status</th>";
html += "<th>Last Sync</th>";
html += "<th>Group</th>";
html += "<th>Source</th>";
html += "</tr>";
html += "</thead>\n";
html += "<tbody>\n";
@ -171,14 +174,14 @@ function InventoriesList($scope, $rootScope, $location,
html += "<tr>";
html += `<td><a href="" ng-click="viewJob('${row.related.last_update}')" aw-tool-tip="${row.status.charAt(0).toUpperCase() + row.status.slice(1)}. Click for details" aw-tip-placement="top"><i class="SmartStatus-tooltip--${row.status} fa icon-job-${row.status}"></i></a></td>`;
html += "<td>" + ($filter('longDate')(row.last_updated)).replace(/ /,'<br />') + "</td>";
html += "<td><a href=\"\" ng-click=\"viewJob('" + row.related.last_update + "')\">" + $filter('sanitize')(ellipsis(row.summary_fields.group.name)) + "</a></td>";
html += "<td><a href=\"\" ng-click=\"viewJob('" + row.related.last_update + "')\">" + $filter('sanitize')(ellipsis(row.name)) + "</a></td>";
html += "</tr>\n";
}
else {
html += "<tr>";
html += "<td><a href=\"\" aw-tool-tip=\"No sync data\" aw-tip-placement=\"top\"><i class=\"fa icon-job-none\"></i></a></td>";
html += "<td>NA</td>";
html += "<td><a href=\"\">" + $filter('sanitize')(ellipsis(row.summary_fields.group.name)) + "</a></td>";
html += "<td><a href=\"\">" + $filter('sanitize')(ellipsis(row.name)) + "</a></td>";
html += "</tr>\n";
}
});
@ -188,7 +191,7 @@ function InventoriesList($scope, $rootScope, $location,
attachElem(event, html, title);
});
$scope.showGroupSummary = function(event, id) {
$scope.showSourceSummary = function(event, id) {
try{
var elem = $(event.target).parent();
// if the popover is visible already, then exit the function here
@ -202,10 +205,10 @@ function InventoriesList($scope, $rootScope, $location,
inventory = Find({ list: $scope.inventories, key: 'id', val: id });
if (inventory.syncStatus !== 'na') {
Wait('start');
Rest.setUrl(inventory.related.inventory_sources + '?or__source=ec2&or__source=rax&order_by=-last_job_run&page_size=5');
Rest.setUrl(inventory.related.inventory_sources + '?order_by=-last_job_run&page_size=5');
Rest.get()
.success(function(data) {
$scope.$emit('GroupSummaryReady', event, inventory, data);
$scope.$emit('SourceSummaryReady', event, inventory, data);
})
.error(function(data, status) {
ProcessErrors( $scope, data, status, null, { hdr: 'Error!',
@ -310,9 +313,18 @@ function InventoriesList($scope, $rootScope, $location,
$scope.viewFailedJobs = function (id) {
$location.url('/jobs/?inventory__int=' + id + '&status=failed');
};
$scope.syncInventory = function(inventory) {
InventoryUpdate({
scope: $scope,
url: inventory.related.update_inventory_sources,
updateAllSources: true
});
};
}
export default ['$scope', '$rootScope', '$location',
'$compile', '$filter', 'Rest', 'InventoryList',
'Prompt', 'ProcessErrors', 'GetBasePath', 'Wait', 'Find', 'Empty', '$state', 'rbacUiControlService', 'Dataset', InventoriesList
'$compile', '$filter', 'Rest', 'InventoryList', 'Prompt',
'ProcessErrors', 'GetBasePath', 'Wait', 'Find', 'Empty',
'$state', 'rbacUiControlService', 'Dataset', 'InventoryUpdate', InventoriesList
];

View File

@ -8,12 +8,12 @@
'InventoryUpdate', 'GroupManageService', 'CancelSourceUpdate',
'ViewUpdateStatus', 'rbacUiControlService', 'GetBasePath',
'GetSyncStatusMsg', 'Dataset', 'Find', 'QuerySet',
'inventoryData', '$filter', 'Prompt', 'Wait', 'SourcesService',
'inventoryData', '$filter', 'Prompt', 'Wait', 'SourcesService', 'inventorySourceOptions',
function($scope, $rootScope, $state, $stateParams, SourcesListDefinition,
InventoryUpdate, GroupManageService, CancelSourceUpdate,
ViewUpdateStatus, rbacUiControlService, GetBasePath, GetSyncStatusMsg,
Dataset, Find, qs, inventoryData, $filter, Prompt,
Wait, SourcesService){
Wait, SourcesService, inventorySourceOptions){
let list = SourcesListDefinition;
@ -36,6 +36,7 @@
$scope.inventory_id = $stateParams.inventory_id;
_.forEach($scope[list.name], buildStatusIndicators);
optionsRequestDataProcessing();
$scope.$on(`ws-jobs`, function(e, data){
var inventory_source = Find({ list: $scope.inventory_sources, key: 'id', val: data.inventory_source_id });
@ -52,6 +53,7 @@
$scope[`${list.iterator}_dataset`] = searchResponse.data;
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
_.forEach($scope[list.name], buildStatusIndicators);
optionsRequestDataProcessing();
});
} else {
var status = GetSyncStatusMsg({
@ -64,6 +66,28 @@
inventory_source.launch_class = status.launch_class;
}
});
$scope.$watchCollection(`${$scope.list.name}`, function() {
_.forEach($scope[list.name], buildStatusIndicators);
optionsRequestDataProcessing();
});
}
function optionsRequestDataProcessing(){
if ($scope[list.name] !== undefined) {
$scope[list.name].forEach(function(item, item_idx) {
var itm = $scope[list.name][item_idx];
// Set the item source label
if (list.fields.source && inventorySourceOptions && inventorySourceOptions.hasOwnProperty('source')) {
inventorySourceOptions.source.choices.forEach(function(choice) {
if (choice[0] === item.source) {
itm.source_label = choice[1];
}
});
}
});
}
}
function buildStatusIndicators(inventory_source){

View File

@ -42,6 +42,9 @@ export default {
}
},
resolve: {
inventorySourceOptions: ['SourcesService', (SourcesService) => {
return SourcesService.options().then(res => res.data.actions.GET);
}],
Dataset: ['SourcesListDefinition', 'QuerySet', '$stateParams', 'GetBasePath', '$interpolate', '$rootScope',
(list, qs, $stateParams, GetBasePath, $interpolate, $rootScope) => {
// allow related list definitions to use interpolated $rootScope / $stateParams in basePath field

View File

@ -33,8 +33,13 @@ export default {
label: 'Sources',
key: true,
ngClick: "editSource(inventory_source.id)",
columnClass: 'col-lg-6 col-md-6 col-sm-6 col-xs-6',
columnClass: 'col-lg-4 col-md-4 col-sm-4 col-xs-4',
class: 'InventoryManage-breakWord',
},
source: {
label: 'Type',
ngBind: 'inventory_source.source_label',
columnClass: 'col-lg-4 col-md-4 col-sm-4 col-xs-4'
}
},
@ -60,7 +65,7 @@ export default {
fieldActions: {
columnClass: 'col-lg-6 col-md-6 col-sm-6 col-xs-6 text-right',
columnClass: 'col-lg-4 col-md-4 col-sm-4 col-xs-4 text-right',
group_update: {
//label: 'Sync',

View File

@ -54,6 +54,13 @@ export default
.error(this.error.bind(this))
.finally(Wait('stop'));
},
options: function(){
this.url = GetBasePath('inventory_sources');
Rest.setUrl(this.url);
return Rest.options()
.success(this.success.bind(this))
.error(this.error.bind(this));
},
getCredential: function(id){
Wait('start');
this.url = GetBasePath('credentials') + id;

View File

@ -43,19 +43,33 @@ export default
Rest.setUrl(url);
Rest.get()
.success(function (data) {
inventory_source = data;
if (data.can_update) {
if (data.passwords_needed_to_update) {
Wait('stop');
scope.$emit('PromptForPasswords');
}
else {
if(params.updateAllSources) {
let userCanUpdateAllSources = true;
_.forEach(data, function(inventory_source){
if (!inventory_source.can_update) {
userCanUpdateAllSources = false;
}
});
if(userCanUpdateAllSources) {
scope.$emit('StartTheUpdate', {});
}
} else {
Wait('stop');
Alert('Permission Denied', 'You do not have access to run the inventory sync. Please contact your system administrator.',
'alert-danger');
}
else {
inventory_source = data;
if (data.can_update) {
if (data.passwords_needed_to_update) {
Wait('stop');
scope.$emit('PromptForPasswords');
}
else {
scope.$emit('StartTheUpdate', {});
}
} else {
Wait('stop');
Alert('Permission Denied', 'You do not have access to run the inventory sync. Please contact your system administrator.',
'alert-danger');
}
}
})
.error(function (data, status) {

View File

@ -134,6 +134,9 @@ angular.module('GeneratorHelpers', [systemStatus.name])
case 'group_update':
icon = 'fa-refresh';
break;
case 'inventory_update':
icon = 'fa-refresh';
break;
case 'scm_update':
icon = 'fa-cloud-download';
break;