mirror of
https://github.com/ansible/awx.git
synced 2024-11-01 08:21:15 +03:00
Resolve fact versions before looking up fact views
This adds a step to the fact version lookup that attempts to resolve fact versions before looking up their views. Resolving a fact version means finding another version to use when there is a problem with the one the user selected. In this case, the resolution process works as follows: 1. Check if either request returned an empty list If so, request again, changing the dates to look back a year. This will almost always return something. 2. If we are requesting multiple facts for the same host, and both of the resolved versions have the same timestamp, they are duplicates and we cannot compare against them. Instead we instruct it to grab the selected and the previous versions for comparison. For host-to-host view, this also updates the timestamp in the header to reflect the actual timestamps. It _does not_ update the date picker dates yet.
This commit is contained in:
parent
0591812da6
commit
9526975318
@ -6,13 +6,36 @@
|
||||
|
||||
export default ['Rest', 'GetBasePath', 'ProcessErrors', 'lodashAsPromised',
|
||||
function (Rest, GetBasePath, ProcessErrors, _) {
|
||||
|
||||
function buildUrl (host_id, module, startDate, endDate) {
|
||||
var url = GetBasePath('hosts') + host_id + '/fact_versions/',
|
||||
params= [["module", module] , ['from', startDate.format()], ['to', endDate.format()]];
|
||||
|
||||
params = params.filter(function(p){
|
||||
return !_.isEmpty(p[1]);
|
||||
});
|
||||
params = params.map(function(p){
|
||||
return p.join("=");
|
||||
}).join("&");
|
||||
url = _.compact([url, params]).join("?");
|
||||
return url;
|
||||
}
|
||||
|
||||
return {
|
||||
getHostFacts: function(host, moduleName, date, fetchScanNumber) {
|
||||
|
||||
var version =this.getVersion(host, moduleName, date.from, date.to, fetchScanNumber);
|
||||
var getVersion = _.partial(this.getVersion, host, moduleName);
|
||||
var getFacts = this.getFacts;
|
||||
|
||||
return version
|
||||
return getVersion(date.from, date.to, fetchScanNumber)
|
||||
.then(function(versionData) {
|
||||
if (_.isEmpty(versionData)) {
|
||||
var retryStartDate = date.from.clone().subtract(1, 'year');
|
||||
return getVersion(retryStartDate, date.from, fetchScanNumber);
|
||||
} else {
|
||||
return versionData;
|
||||
}
|
||||
})
|
||||
.then(function(versionData) {
|
||||
if (_.isEmpty(versionData)) {
|
||||
return { fact: [] };
|
||||
@ -37,18 +60,21 @@ function (Rest, GetBasePath, ProcessErrors, _) {
|
||||
});
|
||||
},
|
||||
|
||||
getVersion: function(host_id, module, startDate, endDate, fetchScanNumber){
|
||||
getVersion: function(versionParams){
|
||||
//move the build url into getVersion and have the
|
||||
// parameters passed into this
|
||||
var promise,
|
||||
url = this.buildUrl(host_id, module, startDate, endDate);
|
||||
var promise;
|
||||
var hostId = versionParams.hostId;
|
||||
var startDate = versionParams.dateRange.from;
|
||||
var endDate = versionParams.dateRange.to;
|
||||
var module = versionParams.moduleName;
|
||||
|
||||
fetchScanNumber = fetchScanNumber || 0;
|
||||
var url = buildUrl(hostId, module, startDate, endDate);
|
||||
|
||||
Rest.setUrl(url);
|
||||
promise = Rest.get();
|
||||
return promise.then(function(data) {
|
||||
return data.data.results[fetchScanNumber];
|
||||
return promise.then(function(response) {
|
||||
return response.data.results;
|
||||
}).catch(function (response) {
|
||||
ProcessErrors(null, response.data, response.status, null, {
|
||||
hdr: 'Error!',
|
||||
@ -56,20 +82,6 @@ function (Rest, GetBasePath, ProcessErrors, _) {
|
||||
response.status
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
buildUrl: function(host_id, module, startDate, endDate){
|
||||
var url = GetBasePath('hosts') + host_id + '/fact_versions/',
|
||||
params= [["module", module] , ['from', startDate.format()], ['to', endDate.format()]];
|
||||
|
||||
params = params.filter(function(p){
|
||||
return !_.isEmpty(p[1]);
|
||||
});
|
||||
params = params.map(function(p){
|
||||
return p.join("=");
|
||||
}).join("&");
|
||||
url = _.compact([url, params]).join("?");
|
||||
return url;
|
||||
}
|
||||
};
|
||||
}];
|
||||
|
@ -7,8 +7,9 @@
|
||||
export default
|
||||
[ 'factScanDataService',
|
||||
'getModuleOptions',
|
||||
'resolveVersions',
|
||||
'lodashAsPromised',
|
||||
function(factScanDataService, getModuleOptions, _) {
|
||||
function(factScanDataService, getModuleOptions, resolveVersions) {
|
||||
return function(hostIds, moduleName, leftDate, rightDate) {
|
||||
|
||||
var moduleOptions;
|
||||
@ -17,39 +18,40 @@ export default
|
||||
hostIds = hostIds.concat(hostIds[0]);
|
||||
}
|
||||
|
||||
var hostVersionParams =
|
||||
[{ hostId: hostIds[0],
|
||||
dateRange: leftDate,
|
||||
moduleName: moduleName
|
||||
},
|
||||
{ hostId: hostIds[1],
|
||||
dateRange: rightDate,
|
||||
moduleName: moduleName
|
||||
}
|
||||
];
|
||||
|
||||
return getModuleOptions(hostIds[0])
|
||||
.then(function(modules) {
|
||||
moduleOptions = modules;
|
||||
return modules;
|
||||
}).then(function() {
|
||||
return hostIds;
|
||||
}).thenMap(function(hostId, index) {
|
||||
var date = leftDate;
|
||||
var fetchScanNumber;
|
||||
|
||||
if (index === 1) {
|
||||
date = rightDate;
|
||||
} else {
|
||||
if (rightDate.from.isSame(leftDate.from, 'day')) {
|
||||
fetchScanNumber = 1;
|
||||
}
|
||||
}
|
||||
|
||||
var params =
|
||||
[ hostId,
|
||||
moduleName,
|
||||
date,
|
||||
fetchScanNumber
|
||||
return hostVersionParams;
|
||||
}).thenMap(function(versionParam) {
|
||||
var versionWithRequest =
|
||||
[ versionParam,
|
||||
factScanDataService.
|
||||
getVersion(versionParam)
|
||||
];
|
||||
|
||||
return params;
|
||||
}).thenMap(function(params) {
|
||||
var getHostFacts =
|
||||
_.spread(factScanDataService.getHostFacts)
|
||||
.bind(factScanDataService);
|
||||
|
||||
return getHostFacts(params);
|
||||
}).then(function(hostFacts) {
|
||||
return versionWithRequest;
|
||||
}).thenAll(function(versions) {
|
||||
return resolveVersions(versions);
|
||||
}, true)
|
||||
.thenMap(function(versionData) {
|
||||
if (versionData) {
|
||||
return factScanDataService.getFacts(versionData);
|
||||
} else {
|
||||
return { fact: [] };
|
||||
}
|
||||
})
|
||||
.thenAll(function(hostFacts) {
|
||||
return [moduleOptions, hostFacts];
|
||||
});
|
||||
};
|
||||
|
@ -0,0 +1,75 @@
|
||||
function resolveVersions(service, _, results) {
|
||||
|
||||
function transformToObjects(versionArray) {
|
||||
|
||||
var converted = versionArray[0];
|
||||
converted.versions = versionArray[1];
|
||||
|
||||
return converted;
|
||||
|
||||
}
|
||||
|
||||
function resolveEmpties(result) {
|
||||
if (_.isEmpty(result.versions)) {
|
||||
var originalStartDate = result.dateRange.from;
|
||||
result.dateRange.from = originalStartDate.clone().subtract(1, 'year');
|
||||
result.dateRange.to = originalStartDate;
|
||||
return [result, service.getVersion(result)];
|
||||
}
|
||||
|
||||
return [result, _.promise(result.versions)];
|
||||
}
|
||||
|
||||
function resolveDuplicates(nonEmptyResults) {
|
||||
var allSameHost =
|
||||
_.every(nonEmptyResults, { 'hostId': nonEmptyResults[0].hostId });
|
||||
|
||||
if (allSameHost) {
|
||||
var firstTimestamp = nonEmptyResults[0].versions[0].timestamp;
|
||||
|
||||
var hostIdsWithDupes =
|
||||
_(nonEmptyResults)
|
||||
.pluck('versions[0]')
|
||||
.filter('timestamp', firstTimestamp)
|
||||
.map(function(version, index) {
|
||||
return nonEmptyResults[index].hostId;
|
||||
})
|
||||
.value();
|
||||
|
||||
if (hostIdsWithDupes.length === 1) {
|
||||
return _.pluck(nonEmptyResults, 'versions[0]');
|
||||
}
|
||||
|
||||
return nonEmptyResults.map(function(scan, index) {
|
||||
var hasDupe =
|
||||
_.include(hostIdsWithDupes, scan.hostId);
|
||||
|
||||
if (hasDupe && index === 1) {
|
||||
return scan.versions[1];
|
||||
} else {
|
||||
return scan.versions[0];
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
return _.pluck(nonEmptyResults, 'versions[0]');
|
||||
}
|
||||
}
|
||||
|
||||
return _(results)
|
||||
.map(transformToObjects)
|
||||
.map(resolveEmpties)
|
||||
.thenAll(function(resolved) {
|
||||
var versionObjects = resolved.map(transformToObjects);
|
||||
return resolveDuplicates(versionObjects);
|
||||
}, true)
|
||||
.value();
|
||||
}
|
||||
|
||||
export default
|
||||
[ 'factScanDataService',
|
||||
'lodashAsPromised',
|
||||
function(factScanDataService, lodash) {
|
||||
return _.partial(resolveVersions, factScanDataService, lodash);
|
||||
}
|
||||
];
|
@ -8,6 +8,7 @@ import route from './system-tracking.route';
|
||||
import factScanDataService from './data-services/fact-scan-data.service';
|
||||
import getDataForComparison from './data-services/get-data-for-comparison.factory';
|
||||
import getModuleOptions from './data-services/get-module-options.factory';
|
||||
import resolveVersions from './data-services/resolve-versions.factory';
|
||||
import controller from './system-tracking.controller';
|
||||
import stringOrDateFilter from './string-or-date.filter';
|
||||
import shared from 'tower/shared/main';
|
||||
@ -23,6 +24,7 @@ export default
|
||||
.service('factScanDataService', factScanDataService)
|
||||
.factory('getDataForComparison', getDataForComparison)
|
||||
.factory('getModuleOptions', getModuleOptions)
|
||||
.factory('resolveVersions', resolveVersions)
|
||||
.filter('stringOrDate', stringOrDateFilter)
|
||||
.controller('systemTracking', controller)
|
||||
.config(['$routeProvider', function($routeProvider) {
|
||||
|
@ -24,8 +24,8 @@ function controller($rootScope,
|
||||
$scope.hostIds = $routeParams.hosts;
|
||||
$scope.inventory = $routeParams.model.inventory;
|
||||
|
||||
$scope.factModulePickersLabelLeft = "Compare facts collected on";
|
||||
$scope.factModulePickersLabelRight = "To facts collected on";
|
||||
$scope.factModulePickersLabelLeft = "Compare facts collected on or before";
|
||||
$scope.factModulePickersLabelRight = "To facts collected on or before";
|
||||
|
||||
$scope.modules = initialFactData.moduleOptions;
|
||||
|
||||
@ -40,6 +40,9 @@ function controller($rootScope,
|
||||
$scope.leftDate = initialFactData.leftSearchRange.from;
|
||||
$scope.rightDate = initialFactData.rightSearchRange.from;
|
||||
|
||||
$scope.leftScanDate = initialFactData.leftScanDate;
|
||||
$scope.rightScanDate = initialFactData.rightScanDate;
|
||||
|
||||
function setHeaderValues(viewType) {
|
||||
if (viewType === 'singleHost') {
|
||||
$scope.comparisonLeftHeader = $scope.leftScanDate;
|
||||
@ -58,7 +61,6 @@ function controller($rootScope,
|
||||
var leftRange = searchConfig.leftRange;
|
||||
var rightRange = searchConfig.rightRange;
|
||||
var activeModule = searchConfig.module;
|
||||
var leftScanDate, rightScanDate;
|
||||
|
||||
|
||||
if (!factData) {
|
||||
@ -68,12 +70,12 @@ function controller($rootScope,
|
||||
activeModule.name,
|
||||
leftRange,
|
||||
rightRange)
|
||||
.thenAll(function(factDataAndModules) {
|
||||
.then(function(factDataAndModules) {
|
||||
var responses = factDataAndModules[1];
|
||||
var data = _.pluck(responses, 'fact');
|
||||
|
||||
leftScanDate = moment(responses[0].timestamp);
|
||||
rightScanDate = moment(responses[1].timestamp);
|
||||
$scope.leftScanDate = moment(responses[0].timestamp);
|
||||
$scope.rightScanDate = moment(responses[1].timestamp);
|
||||
|
||||
return data;
|
||||
}, true);
|
||||
@ -82,7 +84,8 @@ function controller($rootScope,
|
||||
waitIndicator('start');
|
||||
|
||||
return _(factData)
|
||||
.thenAll(function(facts) {
|
||||
.promise()
|
||||
.then(function(facts) {
|
||||
// Make sure we always start comparison against
|
||||
// a non-empty array
|
||||
//
|
||||
@ -132,7 +135,9 @@ function controller($rootScope,
|
||||
|
||||
$scope.factData = info;
|
||||
|
||||
setHeaderValues(viewType, leftScanDate, rightScanDate);
|
||||
setHeaderValues(viewType);
|
||||
|
||||
return info;
|
||||
|
||||
}).finally(function() {
|
||||
waitIndicator('stop');
|
||||
|
@ -31,10 +31,10 @@
|
||||
|
||||
<section class="FactDataError SystemTrackingContainer-main" ng-if="error" ng-switch="error.name">
|
||||
<p class="FactDataError-message" ng-switch-when="NoScanData">
|
||||
There were no facts collected on the dates you selected ({{error.dateValues.leftDate|amDateFormat:'L'}} and {{error.dateValues.rightDate|amDateFormat:'L'}}). Please pick a different range or module and try again.
|
||||
There were no facts collected on or before the dates you selected ({{error.dateValues.leftDate|amDateFormat:'L'}} and {{error.dateValues.rightDate|amDateFormat:'L'}}). Please pick a different range or module and try again.
|
||||
</p>
|
||||
<p class="FactDataError-message" ng-switch-when="InsufficientScanData">
|
||||
There were no facts collected on one of the dates you selected ({{error.dateValue|amDateFormat:'L'}}). Please select a different date and try again.
|
||||
There were no facts collected on or before one of the dates you selected ({{error.dateValue|amDateFormat:'L'}}). Please select a different date and try again.
|
||||
</p>
|
||||
<p class="FactDataError-note">
|
||||
To setup or run scan jobs, edit the "<a link-to="inventoryEdit" model="{ inventory_id: inventory }">{{inventory.name}}</a>" inventory and select "Scan Jobs Templates".
|
||||
|
@ -32,22 +32,22 @@ export default {
|
||||
|
||||
var data =
|
||||
getDataForComparison(hostIds, moduleParam, leftDate, rightDate).
|
||||
thenAll(function(factDataAndModules) {
|
||||
var moduleOptions = factDataAndModules[0];
|
||||
var factResponses = factDataAndModules[1];
|
||||
var factData = _.pluck(factResponses, 'fact');
|
||||
then(function(factDataAndModules) {
|
||||
var moduleOptions = factDataAndModules[0];
|
||||
var factResponses = factDataAndModules[1];
|
||||
var factData = _.pluck(factResponses, 'fact');
|
||||
|
||||
factData.leftSearchRange = leftDate;
|
||||
factData.rightSearchRange = rightDate;
|
||||
factData.leftSearchRange = leftDate;
|
||||
factData.rightSearchRange = rightDate;
|
||||
|
||||
factData.leftScanDate = moment(factResponses[0].timestamp);
|
||||
factData.rightScanDate = moment(factResponses[0].timestamp);
|
||||
factData.leftScanDate = moment(factResponses[0].timestamp);
|
||||
factData.rightScanDate = moment(factResponses[1].timestamp);
|
||||
|
||||
factData.moduleName = moduleParam;
|
||||
factData.moduleOptions = moduleOptions;
|
||||
factData.moduleName = moduleParam;
|
||||
factData.moduleOptions = moduleOptions;
|
||||
|
||||
return factData;
|
||||
}, true)
|
||||
return factData;
|
||||
}, true)
|
||||
.value();
|
||||
|
||||
return data;
|
||||
|
Loading…
Reference in New Issue
Block a user