mirror of
https://github.com/ansible/awx.git
synced 2026-05-08 01:47:35 -02:30
Merge pull request #6334 from mabashian/5815-inventory-sync
Inventory sync fixes
This commit is contained in:
3
awx/ui/client/src/inventories/inventories.block.less
Normal file
3
awx/ui/client/src/inventories/inventories.block.less
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
.Inventories-hostStatus {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
@@ -22,16 +22,22 @@ export default ['i18n', function(i18n) {
|
|||||||
fields: {
|
fields: {
|
||||||
status: {
|
status: {
|
||||||
label: '',
|
label: '',
|
||||||
columnClass: 'col-md-1 col-sm-2 col-xs-2 List-staticColumn--smallStatus',
|
columnClass: 'List-staticColumn--mediumStatus',
|
||||||
nosort: true,
|
nosort: true,
|
||||||
ngClick: "null",
|
ngClick: "null",
|
||||||
iconOnly: true,
|
iconOnly: true,
|
||||||
excludeModal: true,
|
excludeModal: true,
|
||||||
icons: [{
|
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 }}",
|
icon: "{{ 'icon-job-' + inventory.hostsStatus }}",
|
||||||
awToolTip: false,
|
awToolTip: false,
|
||||||
ngClick: "showHostSummary($event, inventory.id)",
|
ngClick: "showHostSummary($event, inventory.id)",
|
||||||
ngClass: ""
|
ngClass: "inventory.host_status_class"
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
@@ -87,6 +93,13 @@ export default ['i18n', function(i18n) {
|
|||||||
|
|
||||||
columnClass: 'col-md-2 col-sm-3 col-xs-4',
|
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: {
|
edit: {
|
||||||
label: i18n._('Edit'),
|
label: i18n._('Edit'),
|
||||||
ngClick: 'editInventory(inventory)',
|
ngClick: 'editInventory(inventory)',
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
|
|
||||||
function InventoriesList($scope, $rootScope, $location,
|
function InventoriesList($scope, $rootScope, $location,
|
||||||
$compile, $filter, Rest, InventoryList, Prompt,
|
$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,
|
let list = InventoryList,
|
||||||
defaultUrl = GetBasePath('inventory');
|
defaultUrl = GetBasePath('inventory');
|
||||||
@@ -37,7 +38,6 @@ function InventoriesList($scope, $rootScope, $location,
|
|||||||
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
|
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
|
||||||
|
|
||||||
$rootScope.flashMessage = null;
|
$rootScope.flashMessage = null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function processInventoryRow(inventory) {
|
function processInventoryRow(inventory) {
|
||||||
@@ -47,10 +47,12 @@ function InventoriesList($scope, $rootScope, $location,
|
|||||||
|
|
||||||
function buildStatusIndicators(inventory){
|
function buildStatusIndicators(inventory){
|
||||||
inventory.launch_class = "";
|
inventory.launch_class = "";
|
||||||
|
inventory.host_status_class = "Inventories-hostStatus";
|
||||||
|
|
||||||
if (inventory.has_inventory_sources) {
|
if (inventory.has_inventory_sources) {
|
||||||
if (inventory.inventory_sources_with_failures > 0) {
|
if (inventory.inventory_sources_with_failures > 0) {
|
||||||
inventory.syncStatus = 'error';
|
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 {
|
else {
|
||||||
inventory.syncStatus = 'successful';
|
inventory.syncStatus = 'successful';
|
||||||
@@ -62,6 +64,7 @@ function InventoriesList($scope, $rootScope, $location,
|
|||||||
inventory.syncTip = 'Not configured for inventory sync.';
|
inventory.syncTip = 'Not configured for inventory sync.';
|
||||||
inventory.launch_class = "btn-disabled";
|
inventory.launch_class = "btn-disabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inventory.has_active_failures) {
|
if (inventory.has_active_failures) {
|
||||||
inventory.hostsStatus = 'error';
|
inventory.hostsStatus = 'error';
|
||||||
inventory.hostsTip = inventory.hosts_with_active_failures + ' hosts with failures. Click for details.';
|
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);
|
attachElem(event, html, title);
|
||||||
});
|
});
|
||||||
|
|
||||||
if ($scope.removeGroupSummaryReady) {
|
if ($scope.removeSourceSummaryReady) {
|
||||||
$scope.removeGroupSummaryReady();
|
$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;
|
var html, title;
|
||||||
|
|
||||||
Wait('stop');
|
Wait('stop');
|
||||||
@@ -162,7 +165,7 @@ function InventoriesList($scope, $rootScope, $location,
|
|||||||
html += "<tr>";
|
html += "<tr>";
|
||||||
html += "<th>Status</th>";
|
html += "<th>Status</th>";
|
||||||
html += "<th>Last Sync</th>";
|
html += "<th>Last Sync</th>";
|
||||||
html += "<th>Group</th>";
|
html += "<th>Source</th>";
|
||||||
html += "</tr>";
|
html += "</tr>";
|
||||||
html += "</thead>\n";
|
html += "</thead>\n";
|
||||||
html += "<tbody>\n";
|
html += "<tbody>\n";
|
||||||
@@ -171,14 +174,14 @@ function InventoriesList($scope, $rootScope, $location,
|
|||||||
html += "<tr>";
|
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><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>" + ($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";
|
html += "</tr>\n";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
html += "<tr>";
|
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><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>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";
|
html += "</tr>\n";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -188,7 +191,7 @@ function InventoriesList($scope, $rootScope, $location,
|
|||||||
attachElem(event, html, title);
|
attachElem(event, html, title);
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.showGroupSummary = function(event, id) {
|
$scope.showSourceSummary = function(event, id) {
|
||||||
try{
|
try{
|
||||||
var elem = $(event.target).parent();
|
var elem = $(event.target).parent();
|
||||||
// if the popover is visible already, then exit the function here
|
// 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 });
|
inventory = Find({ list: $scope.inventories, key: 'id', val: id });
|
||||||
if (inventory.syncStatus !== 'na') {
|
if (inventory.syncStatus !== 'na') {
|
||||||
Wait('start');
|
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()
|
Rest.get()
|
||||||
.success(function(data) {
|
.success(function(data) {
|
||||||
$scope.$emit('GroupSummaryReady', event, inventory, data);
|
$scope.$emit('SourceSummaryReady', event, inventory, data);
|
||||||
})
|
})
|
||||||
.error(function(data, status) {
|
.error(function(data, status) {
|
||||||
ProcessErrors( $scope, data, status, null, { hdr: 'Error!',
|
ProcessErrors( $scope, data, status, null, { hdr: 'Error!',
|
||||||
@@ -310,9 +313,18 @@ function InventoriesList($scope, $rootScope, $location,
|
|||||||
$scope.viewFailedJobs = function (id) {
|
$scope.viewFailedJobs = function (id) {
|
||||||
$location.url('/jobs/?inventory__int=' + id + '&status=failed');
|
$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',
|
export default ['$scope', '$rootScope', '$location',
|
||||||
'$compile', '$filter', 'Rest', 'InventoryList',
|
'$compile', '$filter', 'Rest', 'InventoryList', 'Prompt',
|
||||||
'Prompt', 'ProcessErrors', 'GetBasePath', 'Wait', 'Find', 'Empty', '$state', 'rbacUiControlService', 'Dataset', InventoriesList
|
'ProcessErrors', 'GetBasePath', 'Wait', 'Find', 'Empty',
|
||||||
|
'$state', 'rbacUiControlService', 'Dataset', 'InventoryUpdate', InventoriesList
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -8,12 +8,12 @@
|
|||||||
'InventoryUpdate', 'GroupManageService', 'CancelSourceUpdate',
|
'InventoryUpdate', 'GroupManageService', 'CancelSourceUpdate',
|
||||||
'ViewUpdateStatus', 'rbacUiControlService', 'GetBasePath',
|
'ViewUpdateStatus', 'rbacUiControlService', 'GetBasePath',
|
||||||
'GetSyncStatusMsg', 'Dataset', 'Find', 'QuerySet',
|
'GetSyncStatusMsg', 'Dataset', 'Find', 'QuerySet',
|
||||||
'inventoryData', '$filter', 'Prompt', 'Wait', 'SourcesService',
|
'inventoryData', '$filter', 'Prompt', 'Wait', 'SourcesService', 'inventorySourceOptions',
|
||||||
function($scope, $rootScope, $state, $stateParams, SourcesListDefinition,
|
function($scope, $rootScope, $state, $stateParams, SourcesListDefinition,
|
||||||
InventoryUpdate, GroupManageService, CancelSourceUpdate,
|
InventoryUpdate, GroupManageService, CancelSourceUpdate,
|
||||||
ViewUpdateStatus, rbacUiControlService, GetBasePath, GetSyncStatusMsg,
|
ViewUpdateStatus, rbacUiControlService, GetBasePath, GetSyncStatusMsg,
|
||||||
Dataset, Find, qs, inventoryData, $filter, Prompt,
|
Dataset, Find, qs, inventoryData, $filter, Prompt,
|
||||||
Wait, SourcesService){
|
Wait, SourcesService, inventorySourceOptions){
|
||||||
|
|
||||||
let list = SourcesListDefinition;
|
let list = SourcesListDefinition;
|
||||||
|
|
||||||
@@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
$scope.inventory_id = $stateParams.inventory_id;
|
$scope.inventory_id = $stateParams.inventory_id;
|
||||||
_.forEach($scope[list.name], buildStatusIndicators);
|
_.forEach($scope[list.name], buildStatusIndicators);
|
||||||
|
optionsRequestDataProcessing();
|
||||||
|
|
||||||
$scope.$on(`ws-jobs`, function(e, data){
|
$scope.$on(`ws-jobs`, function(e, data){
|
||||||
var inventory_source = Find({ list: $scope.inventory_sources, key: 'id', val: data.inventory_source_id });
|
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.iterator}_dataset`] = searchResponse.data;
|
||||||
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
|
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
|
||||||
_.forEach($scope[list.name], buildStatusIndicators);
|
_.forEach($scope[list.name], buildStatusIndicators);
|
||||||
|
optionsRequestDataProcessing();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
var status = GetSyncStatusMsg({
|
var status = GetSyncStatusMsg({
|
||||||
@@ -64,6 +66,28 @@
|
|||||||
inventory_source.launch_class = status.launch_class;
|
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){
|
function buildStatusIndicators(inventory_source){
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
|
inventorySourceOptions: ['SourcesService', (SourcesService) => {
|
||||||
|
return SourcesService.options().then(res => res.data.actions.GET);
|
||||||
|
}],
|
||||||
Dataset: ['SourcesListDefinition', 'QuerySet', '$stateParams', 'GetBasePath', '$interpolate', '$rootScope',
|
Dataset: ['SourcesListDefinition', 'QuerySet', '$stateParams', 'GetBasePath', '$interpolate', '$rootScope',
|
||||||
(list, qs, $stateParams, GetBasePath, $interpolate, $rootScope) => {
|
(list, qs, $stateParams, GetBasePath, $interpolate, $rootScope) => {
|
||||||
// allow related list definitions to use interpolated $rootScope / $stateParams in basePath field
|
// allow related list definitions to use interpolated $rootScope / $stateParams in basePath field
|
||||||
|
|||||||
@@ -33,8 +33,13 @@ export default {
|
|||||||
label: 'Sources',
|
label: 'Sources',
|
||||||
key: true,
|
key: true,
|
||||||
ngClick: "editSource(inventory_source.id)",
|
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',
|
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: {
|
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: {
|
group_update: {
|
||||||
//label: 'Sync',
|
//label: 'Sync',
|
||||||
|
|||||||
@@ -54,6 +54,13 @@ export default
|
|||||||
.error(this.error.bind(this))
|
.error(this.error.bind(this))
|
||||||
.finally(Wait('stop'));
|
.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){
|
getCredential: function(id){
|
||||||
Wait('start');
|
Wait('start');
|
||||||
this.url = GetBasePath('credentials') + id;
|
this.url = GetBasePath('credentials') + id;
|
||||||
|
|||||||
@@ -43,19 +43,33 @@ export default
|
|||||||
Rest.setUrl(url);
|
Rest.setUrl(url);
|
||||||
Rest.get()
|
Rest.get()
|
||||||
.success(function (data) {
|
.success(function (data) {
|
||||||
inventory_source = data;
|
if(params.updateAllSources) {
|
||||||
if (data.can_update) {
|
let userCanUpdateAllSources = true;
|
||||||
if (data.passwords_needed_to_update) {
|
_.forEach(data, function(inventory_source){
|
||||||
Wait('stop');
|
if (!inventory_source.can_update) {
|
||||||
scope.$emit('PromptForPasswords');
|
userCanUpdateAllSources = false;
|
||||||
}
|
}
|
||||||
else {
|
});
|
||||||
|
|
||||||
|
if(userCanUpdateAllSources) {
|
||||||
scope.$emit('StartTheUpdate', {});
|
scope.$emit('StartTheUpdate', {});
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
Wait('stop');
|
else {
|
||||||
Alert('Permission Denied', 'You do not have access to run the inventory sync. Please contact your system administrator.',
|
inventory_source = data;
|
||||||
'alert-danger');
|
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) {
|
.error(function (data, status) {
|
||||||
|
|||||||
@@ -134,6 +134,9 @@ angular.module('GeneratorHelpers', [systemStatus.name])
|
|||||||
case 'group_update':
|
case 'group_update':
|
||||||
icon = 'fa-refresh';
|
icon = 'fa-refresh';
|
||||||
break;
|
break;
|
||||||
|
case 'inventory_update':
|
||||||
|
icon = 'fa-refresh';
|
||||||
|
break;
|
||||||
case 'scm_update':
|
case 'scm_update':
|
||||||
icon = 'fa-cloud-download';
|
icon = 'fa-cloud-download';
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user