Refactor capabilities
Rename the 'capabilities' endpoint to 'guidelines' to align more with DefCore terminology. Several references to 'capabilities' were thus updated to 'guidelines'. Split out the actual requests to the DefCore repository so that it can be used by other components. Also, the cache expiration time was increased to 12 hours from 10 minutes. Change-Id: I031798ffc32cdd66428af83a1ee610f00385c524
This commit is contained in:
parent
59af5daa2d
commit
48d36fa26f
@ -43,10 +43,10 @@
|
|||||||
url: '/about',
|
url: '/about',
|
||||||
templateUrl: '/components/about/about.html'
|
templateUrl: '/components/about/about.html'
|
||||||
}).
|
}).
|
||||||
state('capabilities', {
|
state('guidelines', {
|
||||||
url: '/capabilities',
|
url: '/guidelines',
|
||||||
templateUrl: '/components/capabilities/capabilities.html',
|
templateUrl: '/components/guidelines/guidelines.html',
|
||||||
controller: 'CapabilitiesController as ctrl'
|
controller: 'GuidelinesController as ctrl'
|
||||||
}).
|
}).
|
||||||
state('communityResults', {
|
state('communityResults', {
|
||||||
url: '/community_results',
|
url: '/community_results',
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<h3>DefCore Guidelines</h3>
|
<h3>DefCore Guidelines</h3>
|
||||||
|
|
||||||
<!-- Capability Filters -->
|
<!-- Guideline Filters -->
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<strong>Version:</strong>
|
<strong>Version:</strong>
|
||||||
@ -21,15 +21,15 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
<div ng-if="ctrl.capabilities">
|
<div ng-if="ctrl.guidelines">
|
||||||
<strong>Guideline Status:</strong>
|
<strong>Guideline Status:</strong>
|
||||||
{{ctrl.capabilities.status | capitalize}}
|
{{ctrl.guidelines.status | capitalize}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ng-show="ctrl.capabilities">
|
<div ng-show="ctrl.guidelines">
|
||||||
<strong>Corresponding OpenStack Releases:</strong>
|
<strong>Corresponding OpenStack Releases:</strong>
|
||||||
<ul class="list-inline">
|
<ul class="list-inline">
|
||||||
<li ng-repeat="release in ctrl.capabilities.releases">
|
<li ng-repeat="release in ctrl.guidelines.releases">
|
||||||
{{release | capitalize}}
|
{{release | capitalize}}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
@ -17,16 +17,16 @@
|
|||||||
|
|
||||||
angular
|
angular
|
||||||
.module('refstackApp')
|
.module('refstackApp')
|
||||||
.controller('CapabilitiesController', CapabilitiesController);
|
.controller('GuidelinesController', GuidelinesController);
|
||||||
|
|
||||||
CapabilitiesController.$inject = ['$http', '$uibModal', 'refstackApiUrl'];
|
GuidelinesController.$inject = ['$http', '$uibModal', 'refstackApiUrl'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RefStack Capabilities Controller
|
* RefStack Guidelines Controller
|
||||||
* This controller is for the '/capabilities' page where a user can browse
|
* This controller is for the '/guidelines' page where a user can browse
|
||||||
* through tests belonging to DefCore-defined capabilities.
|
* through tests belonging to DefCore-defined capabilities.
|
||||||
*/
|
*/
|
||||||
function CapabilitiesController($http, $uibModal, refstackApiUrl) {
|
function GuidelinesController($http, $uibModal, refstackApiUrl) {
|
||||||
var ctrl = this;
|
var ctrl = this;
|
||||||
|
|
||||||
ctrl.getVersionList = getVersionList;
|
ctrl.getVersionList = getVersionList;
|
||||||
@ -51,11 +51,11 @@
|
|||||||
/**
|
/**
|
||||||
* The template to load for displaying capability details.
|
* The template to load for displaying capability details.
|
||||||
*/
|
*/
|
||||||
ctrl.detailsTemplate = 'components/capabilities/partials/' +
|
ctrl.detailsTemplate = 'components/guidelines/partials/' +
|
||||||
'capabilityDetails.html';
|
'guidelineDetails.html';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve an array of available capability files from the Refstack
|
* Retrieve an array of available guideline files from the Refstack
|
||||||
* API server, sort this array reverse-alphabetically, and store it in
|
* API server, sort this array reverse-alphabetically, and store it in
|
||||||
* a scoped variable. The scope's selected version is initialized to
|
* a scoped variable. The scope's selected version is initialized to
|
||||||
* the latest (i.e. first) version here as well. After a successful API
|
* the latest (i.e. first) version here as well. After a successful API
|
||||||
@ -63,7 +63,7 @@
|
|||||||
* Sample API return array: ["2015.03.json", "2015.04.json"]
|
* Sample API return array: ["2015.03.json", "2015.04.json"]
|
||||||
*/
|
*/
|
||||||
function getVersionList() {
|
function getVersionList() {
|
||||||
var content_url = refstackApiUrl + '/capabilities';
|
var content_url = refstackApiUrl + '/guidelines';
|
||||||
ctrl.versionsRequest =
|
ctrl.versionsRequest =
|
||||||
$http.get(content_url).success(function (data) {
|
$http.get(content_url).success(function (data) {
|
||||||
ctrl.versionList = data.sort().reverse();
|
ctrl.versionList = data.sort().reverse();
|
||||||
@ -78,19 +78,19 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This will contact the Refstack API server to retrieve the JSON
|
* This will contact the Refstack API server to retrieve the JSON
|
||||||
* content of the capability file corresponding to the selected
|
* content of the guideline file corresponding to the selected
|
||||||
* version.
|
* version.
|
||||||
*/
|
*/
|
||||||
function update() {
|
function update() {
|
||||||
var content_url = refstackApiUrl + '/capabilities/' + ctrl.version;
|
var content_url = refstackApiUrl + '/guidelines/' + ctrl.version;
|
||||||
ctrl.capsRequest =
|
ctrl.capsRequest =
|
||||||
$http.get(content_url).success(function (data) {
|
$http.get(content_url).success(function (data) {
|
||||||
ctrl.capabilities = data;
|
ctrl.guidelines = data;
|
||||||
ctrl.updateTargetCapabilities();
|
ctrl.updateTargetCapabilities();
|
||||||
}).error(function (error) {
|
}).error(function (error) {
|
||||||
ctrl.showError = true;
|
ctrl.showError = true;
|
||||||
ctrl.capabilities = null;
|
ctrl.guidelines = null;
|
||||||
ctrl.error = 'Error retrieving capabilities: ' +
|
ctrl.error = 'Error retrieving guideline content: ' +
|
||||||
angular.toJson(error);
|
angular.toJson(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -103,14 +103,14 @@
|
|||||||
*/
|
*/
|
||||||
function updateTargetCapabilities() {
|
function updateTargetCapabilities() {
|
||||||
ctrl.targetCapabilities = {};
|
ctrl.targetCapabilities = {};
|
||||||
var components = ctrl.capabilities.components;
|
var components = ctrl.guidelines.components;
|
||||||
var targetCaps = ctrl.targetCapabilities;
|
var targetCaps = ctrl.targetCapabilities;
|
||||||
|
|
||||||
// The 'platform' target is comprised of multiple components, so
|
// The 'platform' target is comprised of multiple components, so
|
||||||
// we need to get the capabilities belonging to each of its
|
// we need to get the capabilities belonging to each of its
|
||||||
// components.
|
// components.
|
||||||
if (ctrl.target === 'platform') {
|
if (ctrl.target === 'platform') {
|
||||||
var platform_components = ctrl.capabilities.platform.required;
|
var platform_components = ctrl.guidelines.platform.required;
|
||||||
|
|
||||||
// This will contain status priority values, where lower
|
// This will contain status priority values, where lower
|
||||||
// values mean higher priorities.
|
// values mean higher priorities.
|
||||||
@ -189,12 +189,12 @@
|
|||||||
* the selected status(es).
|
* the selected status(es).
|
||||||
*/
|
*/
|
||||||
function getTestList() {
|
function getTestList() {
|
||||||
var caps = ctrl.capabilities.capabilities;
|
var caps = ctrl.guidelines.capabilities;
|
||||||
var tests = [];
|
var tests = [];
|
||||||
angular.forEach(ctrl.targetCapabilities,
|
angular.forEach(ctrl.targetCapabilities,
|
||||||
function (status, cap) {
|
function (status, cap) {
|
||||||
if (ctrl.status[status]) {
|
if (ctrl.status[status]) {
|
||||||
if (ctrl.capabilities.schema === '1.2') {
|
if (ctrl.guidelines.schema === '1.2') {
|
||||||
tests.push.apply(tests, caps[cap].tests);
|
tests.push.apply(tests, caps[cap].tests);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -214,7 +214,7 @@
|
|||||||
*/
|
*/
|
||||||
function openTestListModal() {
|
function openTestListModal() {
|
||||||
$uibModal.open({
|
$uibModal.open({
|
||||||
templateUrl: '/components/capabilities/partials' +
|
templateUrl: '/components/guidelines/partials' +
|
||||||
'/testListModal.html',
|
'/testListModal.html',
|
||||||
backdrop: true,
|
backdrop: true,
|
||||||
windowClass: 'modal',
|
windowClass: 'modal',
|
||||||
@ -249,7 +249,7 @@
|
|||||||
/**
|
/**
|
||||||
* Test List Modal Controller
|
* Test List Modal Controller
|
||||||
* This controller is for the modal that appears if a user wants to see the
|
* This controller is for the modal that appears if a user wants to see the
|
||||||
* ftest list corresponding to DefCore capabilities with the selected
|
* test list corresponding to DefCore capabilities with the selected
|
||||||
* statuses.
|
* statuses.
|
||||||
*/
|
*/
|
||||||
function TestListModalController($uibModalInstance, $window, tests,
|
function TestListModalController($uibModalInstance, $window, tests,
|
@ -1,11 +1,11 @@
|
|||||||
<!--
|
<!--
|
||||||
HTML for capabilites page for all Defcore capabilities schemas
|
HTML for guidelines page for all Defcore guideline schemas
|
||||||
This expects the JSON data of the capability file to be stored in scope
|
This expects the JSON data of the guidelines file to be stored in scope
|
||||||
variable 'capabilities'.
|
variable 'guidelines'.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<ol ng-show="ctrl.capabilities" class="capabilities">
|
<ol ng-show="ctrl.guidelines" class="capabilities">
|
||||||
<li class="capability-list-item" ng-repeat="capability in ctrl.capabilities.capabilities | arrayConverter | filter:ctrl.filterStatus | orderBy:'id'">
|
<li class="capability-list-item" ng-repeat="capability in ctrl.guidelines.capabilities | arrayConverter | filter:ctrl.filterStatus | orderBy:'id'">
|
||||||
<span class="capability-name">{{capability.id}}</span><br />
|
<span class="capability-name">{{capability.id}}</span><br />
|
||||||
<em>{{capability.description}}</em><br />
|
<em>{{capability.description}}</em><br />
|
||||||
Status: <span class="{{ctrl.targetCapabilities[capability.id]}}">{{ctrl.targetCapabilities[capability.id]}}</span><br />
|
Status: <span class="{{ctrl.targetCapabilities[capability.id]}}">{{ctrl.targetCapabilities[capability.id]}}</span><br />
|
||||||
@ -19,11 +19,11 @@ variable 'capabilities'.
|
|||||||
|
|
||||||
<a ng-click="showTests = !showTests">Tests ({{ctrl.getObjectLength(capability.tests)}})</a>
|
<a ng-click="showTests = !showTests">Tests ({{ctrl.getObjectLength(capability.tests)}})</a>
|
||||||
<ul uib-collapse="!showTests">
|
<ul uib-collapse="!showTests">
|
||||||
<li ng-if="ctrl.capabilities.schema === '1.2'" ng-repeat="test in capability.tests">
|
<li ng-if="ctrl.guidelines.schema === '1.2'" ng-repeat="test in capability.tests">
|
||||||
<span ng-class="{'glyphicon glyphicon-flag text-warning': capability.flagged.indexOf(test) > -1}"></span>
|
<span ng-class="{'glyphicon glyphicon-flag text-warning': capability.flagged.indexOf(test) > -1}"></span>
|
||||||
{{test}}
|
{{test}}
|
||||||
</li>
|
</li>
|
||||||
<li ng-if="ctrl.capabilities.schema > '1.2'" ng-repeat="(testName, testDetails) in capability.tests">
|
<li ng-if="ctrl.guidelines.schema > '1.2'" ng-repeat="(testName, testDetails) in capability.tests">
|
||||||
<span ng-class="{'glyphicon glyphicon-flag text-warning': testDetails.flagged}" title="{{testDetails.flagged.reason}}"></span>
|
<span ng-class="{'glyphicon glyphicon-flag text-warning': testDetails.flagged}" title="{{testDetails.flagged.reason}}"></span>
|
||||||
{{testName}}
|
{{testName}}
|
||||||
<div class="test-detail" ng-if="testDetails.aliases">
|
<div class="test-detail" ng-if="testDetails.aliases">
|
||||||
@ -35,12 +35,12 @@ variable 'capabilities'.
|
|||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<div ng-show="ctrl.capabilities" class="criteria">
|
<div ng-show="ctrl.guidelines" class="criteria">
|
||||||
<hr>
|
<hr>
|
||||||
<h4><a ng-click="showCriteria = !showCriteria">Criteria</a></h4>
|
<h4><a ng-click="showCriteria = !showCriteria">Criteria</a></h4>
|
||||||
<div uib-collapse="showCriteria">
|
<div uib-collapse="showCriteria">
|
||||||
<ul>
|
<ul>
|
||||||
<li ng-repeat="(key, criterion) in ctrl.capabilities.criteria">
|
<li ng-repeat="(key, criterion) in ctrl.guidelines.criteria">
|
||||||
<span class="criterion-name">{{criterion.name}}</span><br />
|
<span class="criterion-name">{{criterion.name}}</span><br />
|
||||||
<em>{{criterion.Description}}</em><br />
|
<em>{{criterion.Description}}</em><br />
|
||||||
Weight: {{criterion.weight}}
|
Weight: {{criterion.weight}}
|
@ -21,7 +21,7 @@ report page.
|
|||||||
ng-if="ctrl.isCapabilityShown(capability)">
|
ng-if="ctrl.isCapabilityShown(capability)">
|
||||||
|
|
||||||
<a ng-click="showTests = !showTests"
|
<a ng-click="showTests = !showTests"
|
||||||
title="{{ctrl.capabilityData.capabilities[capability.id].description}}">
|
title="{{ctrl.guidelineData.capabilities[capability.id].description}}">
|
||||||
{{capability.id}}
|
{{capability.id}}
|
||||||
</a>
|
</a>
|
||||||
<span ng-class="{'text-success': ctrl.testStatus === 'passed',
|
<span ng-class="{'text-success': ctrl.testStatus === 'passed',
|
||||||
@ -50,8 +50,8 @@ report page.
|
|||||||
aria-hidden="true">
|
aria-hidden="true">
|
||||||
</span>
|
</span>
|
||||||
<span ng-class="{'glyphicon glyphicon-flag text-warning':
|
<span ng-class="{'glyphicon glyphicon-flag text-warning':
|
||||||
ctrl.isTestFlagged(test, ctrl.capabilityData.capabilities[capability.id])}"
|
ctrl.isTestFlagged(test, ctrl.guidelineData.capabilities[capability.id])}"
|
||||||
title="{{ctrl.getFlaggedReason(test, ctrl.capabilityData.capabilities[capability.id])}}">
|
title="{{ctrl.getFlaggedReason(test, ctrl.guidelineData.capabilities[capability.id])}}">
|
||||||
</span>
|
</span>
|
||||||
{{test}}
|
{{test}}
|
||||||
</li>
|
</li>
|
||||||
@ -63,8 +63,8 @@ report page.
|
|||||||
|
|
||||||
<span class="glyphicon glyphicon-remove text-danger" aria-hidden="true"></span>
|
<span class="glyphicon glyphicon-remove text-danger" aria-hidden="true"></span>
|
||||||
<span ng-class="{'glyphicon glyphicon-flag text-warning':
|
<span ng-class="{'glyphicon glyphicon-flag text-warning':
|
||||||
ctrl.isTestFlagged(test, ctrl.capabilityData.capabilities[capability.id])}"
|
ctrl.isTestFlagged(test, ctrl.guidelineData.capabilities[capability.id])}"
|
||||||
title="{{ctrl.getFlaggedReason(test, ctrl.capabilityData.capabilities[capability.id])}}">
|
title="{{ctrl.getFlaggedReason(test, ctrl.guidelineData.capabilities[capability.id])}}">
|
||||||
</span>
|
</span>
|
||||||
{{test}}
|
{{test}}
|
||||||
</li>
|
</li>
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
<strong>Guideline Version:</strong>
|
<strong>Guideline Version:</strong>
|
||||||
<!-- Slicing the version file name here gets rid of the '.json' file extension -->
|
<!-- Slicing the version file name here gets rid of the '.json' file extension -->
|
||||||
<select ng-model="ctrl.version"
|
<select ng-model="ctrl.version"
|
||||||
ng-change="ctrl.updateCapabilities()"
|
ng-change="ctrl.updateGuidelines()"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
ng-options="versionFile.slice(0,-5) for versionFile in ctrl.versionList">
|
ng-options="versionFile.slice(0,-5) for versionFile in ctrl.versionList">
|
||||||
</select>
|
</select>
|
||||||
@ -53,20 +53,20 @@
|
|||||||
<!-- End User Options -->
|
<!-- End User Options -->
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
<div ng-if="ctrl.capabilityData">
|
<div ng-if="ctrl.guidelineData">
|
||||||
<strong>Guideline Status:</strong>
|
<strong>Guideline Status:</strong>
|
||||||
{{ctrl.capabilityData.status | capitalize}}
|
{{ctrl.guidelineData.status | capitalize}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<strong>Corresponding OpenStack Releases:</strong>
|
<strong>Corresponding OpenStack Releases:</strong>
|
||||||
<ul class="list-inline">
|
<ul class="list-inline">
|
||||||
<li ng-repeat="release in ctrl.capabilityData.releases">
|
<li ng-repeat="release in ctrl.guidelineData.releases">
|
||||||
{{release | capitalize}}
|
{{release | capitalize}}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<hr >
|
<hr >
|
||||||
|
|
||||||
<div ng-show="ctrl.capabilityData">
|
<div ng-show="ctrl.guidelineData">
|
||||||
<strong>Status:</strong>
|
<strong>Status:</strong>
|
||||||
<p>This cloud passes <strong>{{ctrl.requiredPassPercent | number:1}}% </strong>
|
<p>This cloud passes <strong>{{ctrl.requiredPassPercent | number:1}}% </strong>
|
||||||
({{ctrl.caps.required.passedCount}}/{{ctrl.caps.required.count}})
|
({{ctrl.caps.required.passedCount}}/{{ctrl.caps.required.count}})
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
ctrl.isShared = isShared;
|
ctrl.isShared = isShared;
|
||||||
ctrl.shareTestRun = shareTestRun;
|
ctrl.shareTestRun = shareTestRun;
|
||||||
ctrl.deleteTestRun = deleteTestRun;
|
ctrl.deleteTestRun = deleteTestRun;
|
||||||
ctrl.updateCapabilities = updateCapabilities;
|
ctrl.updateGuidelines = updateGuidelines;
|
||||||
ctrl.getTargetCapabilities = getTargetCapabilities;
|
ctrl.getTargetCapabilities = getTargetCapabilities;
|
||||||
ctrl.buildCapabilityV1_2 = buildCapabilityV1_2;
|
ctrl.buildCapabilityV1_2 = buildCapabilityV1_2;
|
||||||
ctrl.buildCapabilityV1_3 = buildCapabilityV1_3;
|
ctrl.buildCapabilityV1_3 = buildCapabilityV1_3;
|
||||||
@ -66,7 +66,7 @@
|
|||||||
'object': 'OpenStack Powered Object Storage'
|
'object': 'OpenStack Powered Object Storage'
|
||||||
};
|
};
|
||||||
|
|
||||||
/** The schema version of the currently selected capabilities data. */
|
/** The schema version of the currently selected guideline data. */
|
||||||
ctrl.schemaVersion = null;
|
ctrl.schemaVersion = null;
|
||||||
|
|
||||||
/** The selected test status used for test filtering. */
|
/** The selected test status used for test filtering. */
|
||||||
@ -77,7 +77,7 @@
|
|||||||
'reportDetails.html';
|
'reportDetails.html';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve an array of available capability files from the Refstack
|
* Retrieve an array of available guideline files from the Refstack
|
||||||
* API server, sort this array reverse-alphabetically, and store it in
|
* API server, sort this array reverse-alphabetically, and store it in
|
||||||
* a scoped variable. The scope's selected version is initialized to
|
* a scoped variable. The scope's selected version is initialized to
|
||||||
* the latest (i.e. first) version here as well. After a successful API
|
* the latest (i.e. first) version here as well. After a successful API
|
||||||
@ -85,14 +85,14 @@
|
|||||||
* Sample API return array: ["2015.03.json", "2015.04.json"]
|
* Sample API return array: ["2015.03.json", "2015.04.json"]
|
||||||
*/
|
*/
|
||||||
function getVersionList() {
|
function getVersionList() {
|
||||||
var content_url = refstackApiUrl + '/capabilities';
|
var content_url = refstackApiUrl + '/guidelines';
|
||||||
ctrl.versionsRequest =
|
ctrl.versionsRequest =
|
||||||
$http.get(content_url).success(function (data) {
|
$http.get(content_url).success(function (data) {
|
||||||
ctrl.versionList = data.sort().reverse();
|
ctrl.versionList = data.sort().reverse();
|
||||||
if (!ctrl.version) {
|
if (!ctrl.version) {
|
||||||
ctrl.version = ctrl.versionList[0];
|
ctrl.version = ctrl.versionList[0];
|
||||||
}
|
}
|
||||||
ctrl.updateCapabilities();
|
ctrl.updateGuidelines();
|
||||||
}).error(function (error) {
|
}).error(function (error) {
|
||||||
ctrl.showError = true;
|
ctrl.showError = true;
|
||||||
ctrl.error = 'Error retrieving version list: ' +
|
ctrl.error = 'Error retrieving version list: ' +
|
||||||
@ -189,24 +189,24 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This will contact the Refstack API server to retrieve the JSON
|
* This will contact the Refstack API server to retrieve the JSON
|
||||||
* content of the capability file corresponding to the selected
|
* content of the guideline file corresponding to the selected
|
||||||
* version. A function to construct an object from the capability
|
* version. A function to construct an object from the capability
|
||||||
* date will be called upon successful retrieval.
|
* data will be called upon successful retrieval.
|
||||||
*/
|
*/
|
||||||
function updateCapabilities() {
|
function updateGuidelines() {
|
||||||
ctrl.capabilityData = null;
|
ctrl.guidelineData = null;
|
||||||
ctrl.showError = false;
|
ctrl.showError = false;
|
||||||
var content_url = refstackApiUrl + '/capabilities/' +
|
var content_url = refstackApiUrl + '/guidelines/' +
|
||||||
ctrl.version;
|
ctrl.version;
|
||||||
ctrl.capsRequest =
|
ctrl.capsRequest =
|
||||||
$http.get(content_url).success(function (data) {
|
$http.get(content_url).success(function (data) {
|
||||||
ctrl.capabilityData = data;
|
ctrl.guidelineData = data;
|
||||||
ctrl.schemaVersion = data.schema;
|
ctrl.schemaVersion = data.schema;
|
||||||
ctrl.buildCapabilitiesObject();
|
ctrl.buildCapabilitiesObject();
|
||||||
}).error(function (error) {
|
}).error(function (error) {
|
||||||
ctrl.showError = true;
|
ctrl.showError = true;
|
||||||
ctrl.capabilityData = null;
|
ctrl.guidelineData = null;
|
||||||
ctrl.error = 'Error retrieving capabilities: ' +
|
ctrl.error = 'Error retrieving guideline date: ' +
|
||||||
angular.toJson(error);
|
angular.toJson(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -217,7 +217,7 @@
|
|||||||
* @returns {Object} Object containing each capability and their status
|
* @returns {Object} Object containing each capability and their status
|
||||||
*/
|
*/
|
||||||
function getTargetCapabilities() {
|
function getTargetCapabilities() {
|
||||||
var components = ctrl.capabilityData.components;
|
var components = ctrl.guidelineData.components;
|
||||||
var targetCaps = {};
|
var targetCaps = {};
|
||||||
|
|
||||||
// The 'platform' target is comprised of multiple components, so
|
// The 'platform' target is comprised of multiple components, so
|
||||||
@ -225,7 +225,7 @@
|
|||||||
// components.
|
// components.
|
||||||
if (ctrl.target === 'platform') {
|
if (ctrl.target === 'platform') {
|
||||||
var platform_components =
|
var platform_components =
|
||||||
ctrl.capabilityData.platform.required;
|
ctrl.guidelineData.platform.required;
|
||||||
|
|
||||||
// This will contain status priority values, where lower
|
// This will contain status priority values, where lower
|
||||||
// values mean higher priorities.
|
// values mean higher priorities.
|
||||||
@ -285,7 +285,7 @@
|
|||||||
'passedFlagged': [],
|
'passedFlagged': [],
|
||||||
'notPassedFlagged': []
|
'notPassedFlagged': []
|
||||||
};
|
};
|
||||||
var capDetails = ctrl.capabilityData.capabilities[capId];
|
var capDetails = ctrl.guidelineData.capabilities[capId];
|
||||||
// Loop through each test belonging to the capability.
|
// Loop through each test belonging to the capability.
|
||||||
angular.forEach(capDetails.tests,
|
angular.forEach(capDetails.tests,
|
||||||
function (testId) {
|
function (testId) {
|
||||||
@ -322,7 +322,7 @@
|
|||||||
'notPassedFlagged': []
|
'notPassedFlagged': []
|
||||||
};
|
};
|
||||||
// Loop through each test belonging to the capability.
|
// Loop through each test belonging to the capability.
|
||||||
angular.forEach(ctrl.capabilityData.capabilities[capId].tests,
|
angular.forEach(ctrl.guidelineData.capabilities[capId].tests,
|
||||||
function (details, testId) {
|
function (details, testId) {
|
||||||
var passed = false;
|
var passed = false;
|
||||||
|
|
||||||
@ -390,8 +390,8 @@
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ctrl.showError = true;
|
ctrl.showError = true;
|
||||||
ctrl.capabilityData = null;
|
ctrl.guidelineData = null;
|
||||||
ctrl.error = 'The schema version for the capabilities ' +
|
ctrl.error = 'The schema version for the guideline ' +
|
||||||
'file selected (' + ctrl.schemaVersion +
|
'file selected (' + ctrl.schemaVersion +
|
||||||
') is currently not supported.';
|
') is currently not supported.';
|
||||||
return;
|
return;
|
||||||
|
@ -196,7 +196,7 @@
|
|||||||
if (ctrl.versionList) {
|
if (ctrl.versionList) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var content_url = refstackApiUrl + '/capabilities';
|
var content_url = refstackApiUrl + '/guidelines';
|
||||||
ctrl.versionsRequest =
|
ctrl.versionsRequest =
|
||||||
$http.get(content_url).success(function (data) {
|
$http.get(content_url).success(function (data) {
|
||||||
ctrl.versionList = data.sort().reverse();
|
ctrl.versionList = data.sort().reverse();
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
<!-- Controllers -->
|
<!-- Controllers -->
|
||||||
<script src="shared/header/headerController.js"></script>
|
<script src="shared/header/headerController.js"></script>
|
||||||
<script src="shared/alerts/alertModalFactory.js"></script>
|
<script src="shared/alerts/alertModalFactory.js"></script>
|
||||||
<script src="components/capabilities/capabilitiesController.js"></script>
|
<script src="components/guidelines/guidelinesController.js"></script>
|
||||||
<script src="components/results/resultsController.js"></script>
|
<script src="components/results/resultsController.js"></script>
|
||||||
<script src="components/results-report/resultsReportController.js"></script>
|
<script src="components/results-report/resultsReportController.js"></script>
|
||||||
<script src="components/profile/profileController.js"></script>
|
<script src="components/profile/profileController.js"></script>
|
||||||
|
@ -17,7 +17,7 @@ RefStack
|
|||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li ng-class="{ active: header.isActive('/')}"><a ui-sref="home">Home</a></li>
|
<li ng-class="{ active: header.isActive('/')}"><a ui-sref="home">Home</a></li>
|
||||||
<li ng-class="{ active: header.isActive('/about')}"><a ui-sref="about">About</a></li>
|
<li ng-class="{ active: header.isActive('/about')}"><a ui-sref="about">About</a></li>
|
||||||
<li ng-class="{ active: header.isActive('/capabilities')}"><a ui-sref="capabilities">DefCore Guidelines</a></li>
|
<li ng-class="{ active: header.isActive('/guidelines')}"><a ui-sref="guidelines">DefCore Guidelines</a></li>
|
||||||
<li ng-class="{ active: header.isActive('/community_results')}"><a ui-sref="communityResults">Community Results</a></li>
|
<li ng-class="{ active: header.isActive('/community_results')}"><a ui-sref="communityResults">Community Results</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<ul class="nav navbar-nav navbar-right">
|
||||||
|
@ -58,11 +58,11 @@ describe('Refstack controllers', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('CapabilitiesController', function () {
|
describe('GuidelinesController', function () {
|
||||||
var ctrl;
|
var ctrl;
|
||||||
|
|
||||||
beforeEach(inject(function ($controller) {
|
beforeEach(inject(function ($controller) {
|
||||||
ctrl = $controller('CapabilitiesController', {});
|
ctrl = $controller('GuidelinesController', {});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should set default states', function () {
|
it('should set default states', function () {
|
||||||
@ -91,17 +91,17 @@ describe('Refstack controllers', function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
$httpBackend.expectGET(fakeApiUrl +
|
$httpBackend.expectGET(fakeApiUrl +
|
||||||
'/capabilities').respond(['2015.03.json', '2015.04.json']);
|
'/guidelines').respond(['2015.03.json', '2015.04.json']);
|
||||||
// Should call request with latest version.
|
// Should call request with latest version.
|
||||||
$httpBackend.expectGET(fakeApiUrl +
|
$httpBackend.expectGET(fakeApiUrl +
|
||||||
'/capabilities/2015.04.json').respond(fakeCaps);
|
'/guidelines/2015.04.json').respond(fakeCaps);
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
// The version list should be sorted latest first.
|
// The version list should be sorted latest first.
|
||||||
expect(ctrl.versionList).toEqual(['2015.04.json',
|
expect(ctrl.versionList).toEqual(['2015.04.json',
|
||||||
'2015.03.json']);
|
'2015.03.json']);
|
||||||
expect(ctrl.capabilities).toEqual(fakeCaps);
|
expect(ctrl.guidelines).toEqual(fakeCaps);
|
||||||
// The guideline status should be approved.
|
// The guideline status should be approved.
|
||||||
expect(ctrl.capabilities.status).toEqual('approved');
|
expect(ctrl.guidelines.status).toEqual('approved');
|
||||||
var expectedTargetCaps = {
|
var expectedTargetCaps = {
|
||||||
'cap_id_1': 'required',
|
'cap_id_1': 'required',
|
||||||
'cap_id_2': 'advisory',
|
'cap_id_2': 'advisory',
|
||||||
@ -158,8 +158,8 @@ describe('Refstack controllers', function () {
|
|||||||
function () {
|
function () {
|
||||||
ctrl.targetCapabilities = {'cap-1': 'required',
|
ctrl.targetCapabilities = {'cap-1': 'required',
|
||||||
'cap-2': 'advisory'};
|
'cap-2': 'advisory'};
|
||||||
ctrl.capabilities = {
|
ctrl.guidelines = {
|
||||||
'schema': 1.4,
|
'schema': '1.4',
|
||||||
'capabilities' : {
|
'capabilities' : {
|
||||||
'cap-1': {
|
'cap-1': {
|
||||||
'tests': {
|
'tests': {
|
||||||
@ -175,8 +175,8 @@ describe('Refstack controllers', function () {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
expect(ctrl.getTestList()).toEqual(['test_1', 'test_2']);
|
expect(ctrl.getTestList()).toEqual(['test_1', 'test_2']);
|
||||||
ctrl.capabilities = {
|
ctrl.guidelines = {
|
||||||
'schema': 1.2,
|
'schema': '1.2',
|
||||||
'capabilities' : {
|
'capabilities' : {
|
||||||
'cap-1': {
|
'cap-1': {
|
||||||
'tests': ['test_1', 'test_2']
|
'tests': ['test_1', 'test_2']
|
||||||
@ -186,6 +186,7 @@ describe('Refstack controllers', function () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
expect(ctrl.getTestList()).toEqual(['test_1', 'test_2']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have a method to open a modal for the relevant test list',
|
it('should have a method to open a modal for the relevant test list',
|
||||||
@ -351,7 +352,7 @@ describe('Refstack controllers', function () {
|
|||||||
$httpBackend.expectGET(fakeApiUrl + '/results?page=1')
|
$httpBackend.expectGET(fakeApiUrl + '/results?page=1')
|
||||||
.respond(fakeResponse);
|
.respond(fakeResponse);
|
||||||
$httpBackend.expectGET(fakeApiUrl +
|
$httpBackend.expectGET(fakeApiUrl +
|
||||||
'/capabilities').respond(['2015.03.json', '2015.04.json']);
|
'/guidelines').respond(['2015.03.json', '2015.04.json']);
|
||||||
ctrl.getVersionList();
|
ctrl.getVersionList();
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
// Expect the list to have the latest guideline first.
|
// Expect the list to have the latest guideline first.
|
||||||
@ -394,30 +395,30 @@ describe('Refstack controllers', function () {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should make all necessary API requests to get results ' +
|
it('should make all necessary API requests to get results ' +
|
||||||
'and capabilities',
|
'and guidelines',
|
||||||
function () {
|
function () {
|
||||||
$httpBackend.expectGET(fakeApiUrl +
|
$httpBackend.expectGET(fakeApiUrl +
|
||||||
'/results/1234').respond(fakeResultResponse);
|
'/results/1234').respond(fakeResultResponse);
|
||||||
$httpBackend.expectGET(fakeApiUrl +
|
$httpBackend.expectGET(fakeApiUrl +
|
||||||
'/capabilities').respond(['2015.03.json', '2015.04.json']);
|
'/guidelines').respond(['2015.03.json', '2015.04.json']);
|
||||||
// Should call request with latest version.
|
// Should call request with latest version.
|
||||||
$httpBackend.expectGET(fakeApiUrl +
|
$httpBackend.expectGET(fakeApiUrl +
|
||||||
'/capabilities/2015.04.json').respond(fakeCapabilityResponse);
|
'/guidelines/2015.04.json').respond(fakeCapabilityResponse);
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
expect(ctrl.resultsData).toEqual(fakeResultResponse);
|
expect(ctrl.resultsData).toEqual(fakeResultResponse);
|
||||||
// The version list should be sorted latest first.
|
// The version list should be sorted latest first.
|
||||||
expect(ctrl.versionList).toEqual(['2015.04.json',
|
expect(ctrl.versionList).toEqual(['2015.04.json',
|
||||||
'2015.03.json']);
|
'2015.03.json']);
|
||||||
expect(ctrl.capabilityData).toEqual(fakeCapabilityResponse);
|
expect(ctrl.guidelineData).toEqual(fakeCapabilityResponse);
|
||||||
// The guideline status should be approved.
|
// The guideline status should be approved.
|
||||||
expect(ctrl.capabilityData.status).toEqual('approved');
|
expect(ctrl.guidelineData.status).toEqual('approved');
|
||||||
expect(ctrl.schemaVersion).toEqual('1.2');
|
expect(ctrl.schemaVersion).toEqual('1.2');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have a method that creates an object containing each ' +
|
it('should have a method that creates an object containing each ' +
|
||||||
'relevant capability and its highest priority status',
|
'relevant capability and its highest priority status',
|
||||||
function () {
|
function () {
|
||||||
ctrl.capabilityData = {
|
ctrl.guidelineData = {
|
||||||
'schema': '1.3',
|
'schema': '1.3',
|
||||||
'platform': {'required': ['compute', 'object']},
|
'platform': {'required': ['compute', 'object']},
|
||||||
'components': {
|
'components': {
|
||||||
@ -447,7 +448,7 @@ describe('Refstack controllers', function () {
|
|||||||
'schema version 1.2',
|
'schema version 1.2',
|
||||||
function () {
|
function () {
|
||||||
ctrl.resultsData = fakeResultResponse;
|
ctrl.resultsData = fakeResultResponse;
|
||||||
ctrl.capabilityData = fakeCapabilityResponse;
|
ctrl.guidelineData = fakeCapabilityResponse;
|
||||||
ctrl.schemaVersion = '1.2';
|
ctrl.schemaVersion = '1.2';
|
||||||
ctrl.buildCapabilitiesObject();
|
ctrl.buildCapabilitiesObject();
|
||||||
var expectedCapsObject = {
|
var expectedCapsObject = {
|
||||||
@ -481,7 +482,7 @@ describe('Refstack controllers', function () {
|
|||||||
'old_test_id_3',
|
'old_test_id_3',
|
||||||
'test_id_4']
|
'test_id_4']
|
||||||
};
|
};
|
||||||
ctrl.capabilityData = {
|
ctrl.guidelineData = {
|
||||||
'platform': {'required': ['compute']},
|
'platform': {'required': ['compute']},
|
||||||
'schema': '1.4',
|
'schema': '1.4',
|
||||||
'components': {
|
'components': {
|
||||||
|
@ -1,86 +0,0 @@
|
|||||||
# Copyright (c) 2015 Mirantis, Inc.
|
|
||||||
# All Rights Reserved.
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
|
|
||||||
"""Defcore capabilities controller."""
|
|
||||||
|
|
||||||
from oslo_config import cfg
|
|
||||||
from oslo_log import log
|
|
||||||
import pecan
|
|
||||||
from pecan import rest
|
|
||||||
import re
|
|
||||||
import requests
|
|
||||||
import requests_cache
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
|
||||||
LOG = log.getLogger(__name__)
|
|
||||||
|
|
||||||
# Cached requests will expire after 10 minutes.
|
|
||||||
requests_cache.install_cache(cache_name='github_cache',
|
|
||||||
backend='memory',
|
|
||||||
expire_after=600)
|
|
||||||
|
|
||||||
|
|
||||||
class CapabilitiesController(rest.RestController):
|
|
||||||
"""/v1/capabilities handler.
|
|
||||||
|
|
||||||
This acts as a proxy for retrieving capability files
|
|
||||||
from the openstack/defcore Github repository.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@pecan.expose('json')
|
|
||||||
def get(self):
|
|
||||||
"""Get a list of all available capabilities."""
|
|
||||||
try:
|
|
||||||
response = requests.get(CONF.api.github_api_capabilities_url)
|
|
||||||
LOG.debug("Response Status: %s / Used Requests Cache: %s" %
|
|
||||||
(response.status_code,
|
|
||||||
getattr(response, 'from_cache', False)))
|
|
||||||
if response.status_code == 200:
|
|
||||||
regex = re.compile('^[0-9]{4}\.[0-9]{2}\.json$')
|
|
||||||
capability_files = []
|
|
||||||
for rfile in response.json():
|
|
||||||
if rfile["type"] == "file" and regex.search(rfile["name"]):
|
|
||||||
capability_files.append(rfile["name"])
|
|
||||||
return capability_files
|
|
||||||
else:
|
|
||||||
LOG.warning('Github returned non-success HTTP '
|
|
||||||
'code: %s' % response.status_code)
|
|
||||||
pecan.abort(response.status_code)
|
|
||||||
|
|
||||||
except requests.exceptions.RequestException as e:
|
|
||||||
LOG.warning('An error occurred trying to get GitHub '
|
|
||||||
'repository contents: %s' % e)
|
|
||||||
pecan.abort(500)
|
|
||||||
|
|
||||||
@pecan.expose('json')
|
|
||||||
def get_one(self, file_name):
|
|
||||||
"""Handler for getting contents of specific capability file."""
|
|
||||||
github_url = ''.join((CONF.api.github_raw_base_url.rstrip('/'),
|
|
||||||
'/', file_name, ".json"))
|
|
||||||
try:
|
|
||||||
response = requests.get(github_url)
|
|
||||||
LOG.debug("Response Status: %s / Used Requests Cache: %s" %
|
|
||||||
(response.status_code,
|
|
||||||
getattr(response, 'from_cache', False)))
|
|
||||||
if response.status_code == 200:
|
|
||||||
return response.json()
|
|
||||||
else:
|
|
||||||
LOG.warning('Github returned non-success HTTP '
|
|
||||||
'code: %s' % response.status_code)
|
|
||||||
pecan.abort(response.status_code)
|
|
||||||
except requests.exceptions.RequestException as e:
|
|
||||||
LOG.warning('An error occurred trying to get GitHub '
|
|
||||||
'capability file contents: %s' % e)
|
|
||||||
pecan.abort(500)
|
|
54
refstack/api/controllers/guidelines.py
Normal file
54
refstack/api/controllers/guidelines.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# Copyright (c) 2015 Mirantis, Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
"""Defcore guidelines controller."""
|
||||||
|
|
||||||
|
from oslo_log import log
|
||||||
|
import pecan
|
||||||
|
from pecan import rest
|
||||||
|
|
||||||
|
from refstack.api import guidelines
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class GuidelinesController(rest.RestController):
|
||||||
|
"""/v1/guidelines handler.
|
||||||
|
|
||||||
|
This acts as a proxy for retrieving guideline files
|
||||||
|
from the openstack/defcore Github repository.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@pecan.expose('json')
|
||||||
|
def get(self):
|
||||||
|
"""Get a list of all available guidelines."""
|
||||||
|
g = guidelines.Guidelines()
|
||||||
|
version_list = g.get_guideline_list()
|
||||||
|
if version_list is None:
|
||||||
|
pecan.abort(500, 'The server was unable to get a list of '
|
||||||
|
'guidelines from the external source.')
|
||||||
|
else:
|
||||||
|
return version_list
|
||||||
|
|
||||||
|
@pecan.expose('json')
|
||||||
|
def get_one(self, file_name):
|
||||||
|
"""Handler for getting contents of specific guideline file."""
|
||||||
|
g = guidelines.Guidelines()
|
||||||
|
json = g.get_guideline_contents(file_name)
|
||||||
|
if json:
|
||||||
|
return json
|
||||||
|
else:
|
||||||
|
pecan.abort(500, 'The server was unable to get the JSON '
|
||||||
|
'content for the specified guideline file.')
|
@ -16,7 +16,7 @@
|
|||||||
"""Version 1 of the API."""
|
"""Version 1 of the API."""
|
||||||
|
|
||||||
from refstack.api.controllers import auth
|
from refstack.api.controllers import auth
|
||||||
from refstack.api.controllers import capabilities
|
from refstack.api.controllers import guidelines
|
||||||
from refstack.api.controllers import results
|
from refstack.api.controllers import results
|
||||||
from refstack.api.controllers import user
|
from refstack.api.controllers import user
|
||||||
|
|
||||||
@ -25,6 +25,6 @@ class V1Controller(object):
|
|||||||
"""Version 1 API controller root."""
|
"""Version 1 API controller root."""
|
||||||
|
|
||||||
results = results.ResultsController()
|
results = results.ResultsController()
|
||||||
capabilities = capabilities.CapabilitiesController()
|
guidelines = guidelines.GuidelinesController()
|
||||||
auth = auth.AuthController()
|
auth = auth.AuthController()
|
||||||
profile = user.ProfileController()
|
profile = user.ProfileController()
|
||||||
|
103
refstack/api/guidelines.py
Normal file
103
refstack/api/guidelines.py
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
# Copyright (c) 2016 IBM, Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
"""Class for retrieving DefCore guideline information."""
|
||||||
|
|
||||||
|
from oslo_config import cfg
|
||||||
|
from oslo_log import log
|
||||||
|
import re
|
||||||
|
import requests
|
||||||
|
import requests_cache
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
# Cached requests will expire after 12 hours.
|
||||||
|
requests_cache.install_cache(cache_name='github_cache',
|
||||||
|
backend='memory',
|
||||||
|
expire_after=43200)
|
||||||
|
|
||||||
|
|
||||||
|
class Guidelines:
|
||||||
|
"""This class handles guideline/capability listing and retrieval."""
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
repo_url=None,
|
||||||
|
raw_url=None):
|
||||||
|
"""Initialize class with needed URLs.
|
||||||
|
|
||||||
|
The URL for the the guidelines repository is specified with 'repo_url'.
|
||||||
|
The URL for where raw files are served is specified with 'raw_url'.
|
||||||
|
These values will default to the values specified in the RefStack
|
||||||
|
config file.
|
||||||
|
"""
|
||||||
|
if repo_url:
|
||||||
|
self.repo_url = repo_url
|
||||||
|
else:
|
||||||
|
self.repo_url = CONF.api.github_api_capabilities_url
|
||||||
|
|
||||||
|
if raw_url:
|
||||||
|
self.raw_url = raw_url
|
||||||
|
else:
|
||||||
|
self.raw_url = CONF.api.github_raw_base_url
|
||||||
|
|
||||||
|
def get_guideline_list(self):
|
||||||
|
"""Return a list of a guideline files.
|
||||||
|
|
||||||
|
The repository url specificed in class instantiation is checked
|
||||||
|
for a list of JSON guideline files. A list of these is returned.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
response = requests.get(self.repo_url)
|
||||||
|
LOG.debug("Response Status: %s / Used Requests Cache: %s" %
|
||||||
|
(response.status_code,
|
||||||
|
getattr(response, 'from_cache', False)))
|
||||||
|
if response.status_code == 200:
|
||||||
|
regex = re.compile('^[0-9]{4}\.[0-9]{2}\.json$')
|
||||||
|
capability_files = []
|
||||||
|
for rfile in response.json():
|
||||||
|
if rfile["type"] == "file" and regex.search(rfile["name"]):
|
||||||
|
capability_files.append(rfile["name"])
|
||||||
|
return capability_files
|
||||||
|
else:
|
||||||
|
LOG.warning('Guidelines repo URL (%s) returned non-success '
|
||||||
|
'HTTP code: %s' % (self.repo_url,
|
||||||
|
response.status_code))
|
||||||
|
return None
|
||||||
|
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
LOG.warning('An error occurred trying to get repository contents '
|
||||||
|
'through %s: %s' % (self.repo_url, e))
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_guideline_contents(self, guideline_file):
|
||||||
|
"""Get JSON data from raw guidelines URL."""
|
||||||
|
file_url = ''.join((self.raw_url.rstrip('/'),
|
||||||
|
'/', guideline_file, ".json"))
|
||||||
|
try:
|
||||||
|
response = requests.get(file_url)
|
||||||
|
LOG.debug("Response Status: %s / Used Requests Cache: %s" %
|
||||||
|
(response.status_code,
|
||||||
|
getattr(response, 'from_cache', False)))
|
||||||
|
if response.status_code == 200:
|
||||||
|
return response.json()
|
||||||
|
else:
|
||||||
|
LOG.warning('Raw guideline URL (%s) returned non-success HTTP '
|
||||||
|
'code: %s' % (self.raw_url, response.status_code))
|
||||||
|
return None
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
LOG.warning('An error occurred trying to get raw capability file '
|
||||||
|
'contents from %s: %s' % (self.raw_url, e))
|
||||||
|
return None
|
@ -226,12 +226,12 @@ class TestResultsController(api.FunctionalTest):
|
|||||||
self.assertEqual(r, filtering_results)
|
self.assertEqual(r, filtering_results)
|
||||||
|
|
||||||
|
|
||||||
class TestCapabilitiesController(api.FunctionalTest):
|
class TestGuidelinesController(api.FunctionalTest):
|
||||||
"""Test case for CapabilitiesController."""
|
"""Test case for GuidelinesController."""
|
||||||
|
|
||||||
URL = '/v1/capabilities/'
|
URL = '/v1/guidelines/'
|
||||||
|
|
||||||
def test_get_capability_list(self):
|
def test_get_guideline_list(self):
|
||||||
@httmock.all_requests
|
@httmock.all_requests
|
||||||
def github_api_mock(url, request):
|
def github_api_mock(url, request):
|
||||||
headers = {'content-type': 'application/json'}
|
headers = {'content-type': 'application/json'}
|
||||||
@ -247,7 +247,7 @@ class TestCapabilitiesController(api.FunctionalTest):
|
|||||||
expected_response = ['2015.03.json']
|
expected_response = ['2015.03.json']
|
||||||
self.assertEqual(expected_response, actual_response)
|
self.assertEqual(expected_response, actual_response)
|
||||||
|
|
||||||
def test_get_capability_file(self):
|
def test_get_guideline_file(self):
|
||||||
@httmock.all_requests
|
@httmock.all_requests
|
||||||
def github_mock(url, request):
|
def github_mock(url, request):
|
||||||
content = {'foo': 'bar'}
|
content = {'foo': 'bar'}
|
||||||
|
@ -16,34 +16,22 @@
|
|||||||
"""Tests for API's controllers"""
|
"""Tests for API's controllers"""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import sys
|
|
||||||
|
|
||||||
import httmock
|
|
||||||
import mock
|
import mock
|
||||||
from oslo_config import fixture as config_fixture
|
from oslo_config import fixture as config_fixture
|
||||||
import requests
|
|
||||||
from six.moves.urllib import parse
|
from six.moves.urllib import parse
|
||||||
import webob.exc
|
import webob.exc
|
||||||
|
|
||||||
from refstack.api import constants as const
|
from refstack.api import constants as const
|
||||||
from refstack.api import exceptions as api_exc
|
from refstack.api import exceptions as api_exc
|
||||||
from refstack.api.controllers import auth
|
from refstack.api.controllers import auth
|
||||||
from refstack.api.controllers import capabilities
|
from refstack.api.controllers import guidelines
|
||||||
from refstack.api.controllers import results
|
from refstack.api.controllers import results
|
||||||
from refstack.api.controllers import validation
|
from refstack.api.controllers import validation
|
||||||
from refstack.api.controllers import user
|
from refstack.api.controllers import user
|
||||||
from refstack.tests import unit as base
|
from refstack.tests import unit as base
|
||||||
|
|
||||||
|
|
||||||
def safe_json_dump(content):
|
|
||||||
if isinstance(content, (dict, list)):
|
|
||||||
if sys.version_info[0] == 3:
|
|
||||||
content = bytes(json.dumps(content), 'utf-8')
|
|
||||||
else:
|
|
||||||
content = json.dumps(content)
|
|
||||||
return content
|
|
||||||
|
|
||||||
|
|
||||||
class BaseControllerTestCase(base.RefstackBaseTestCase):
|
class BaseControllerTestCase(base.RefstackBaseTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -289,76 +277,41 @@ class ResultsControllerTestCase(BaseControllerTestCase):
|
|||||||
self.controller.delete, 'test_id')
|
self.controller.delete, 'test_id')
|
||||||
|
|
||||||
|
|
||||||
class CapabilitiesControllerTestCase(BaseControllerTestCase):
|
class GuidelinesControllerTestCase(BaseControllerTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(CapabilitiesControllerTestCase, self).setUp()
|
super(GuidelinesControllerTestCase, self).setUp()
|
||||||
self.controller = capabilities.CapabilitiesController()
|
self.controller = guidelines.GuidelinesController()
|
||||||
self.mock_abort.side_effect = None
|
self.mock_abort.side_effect = None
|
||||||
|
|
||||||
def test_get_capabilities(self):
|
@mock.patch('refstack.api.guidelines.Guidelines.get_guideline_list')
|
||||||
"""Test when getting a list of all capability files."""
|
def test_get_guidelines(self, mock_list):
|
||||||
@httmock.all_requests
|
"""Test when getting a list of all guideline files."""
|
||||||
def github_api_mock(url, request):
|
mock_list.return_value = ['2015.03.json']
|
||||||
headers = {'content-type': 'application/json'}
|
|
||||||
content = [{'name': '2015.03.json', 'type': 'file'},
|
|
||||||
{'name': '2015.next.json', 'type': 'file'},
|
|
||||||
{'name': '2015.03', 'type': 'dir'}]
|
|
||||||
content = safe_json_dump(content)
|
|
||||||
return httmock.response(200, content, headers, None, 5, request)
|
|
||||||
|
|
||||||
with httmock.HTTMock(github_api_mock):
|
|
||||||
result = self.controller.get()
|
result = self.controller.get()
|
||||||
self.assertEqual(['2015.03.json'], result)
|
self.assertEqual(['2015.03.json'], result)
|
||||||
|
|
||||||
def test_get_capabilities_error_code(self):
|
@mock.patch('refstack.api.guidelines.Guidelines.get_guideline_list')
|
||||||
"""Test when the HTTP status code isn't a 200 OK. The status should
|
def test_get_guidelines_error(self, mock_list):
|
||||||
be propogated."""
|
"""Test when there is a problem getting the guideline list and
|
||||||
@httmock.all_requests
|
nothing is returned."""
|
||||||
def github_api_mock(url, request):
|
mock_list.return_value = None
|
||||||
content = {'title': 'Not Found'}
|
|
||||||
return httmock.response(404, content, None, None, 5, request)
|
|
||||||
|
|
||||||
with httmock.HTTMock(github_api_mock):
|
|
||||||
self.controller.get()
|
self.controller.get()
|
||||||
self.mock_abort.assert_called_with(404)
|
self.mock_abort.assert_called_with(500, mock.ANY)
|
||||||
|
|
||||||
@mock.patch('requests.get')
|
@mock.patch('refstack.api.guidelines.Guidelines.get_guideline_contents')
|
||||||
def test_get_capabilities_exception(self, mock_requests_get):
|
def test_get_guideline_file(self, mock_get_contents):
|
||||||
"""Test when the GET request raises an exception."""
|
"""Test when getting a specific guideline file"""
|
||||||
mock_requests_get.side_effect = requests.exceptions.RequestException()
|
mock_get_contents.return_value = {'foo': 'bar'}
|
||||||
self.controller.get()
|
|
||||||
self.mock_abort.assert_called_with(500)
|
|
||||||
|
|
||||||
def test_get_capability_file(self):
|
|
||||||
"""Test when getting a specific capability file"""
|
|
||||||
@httmock.all_requests
|
|
||||||
def github_mock(url, request):
|
|
||||||
content = {'foo': 'bar'}
|
|
||||||
return httmock.response(200, content, None, None, 5, request)
|
|
||||||
|
|
||||||
with httmock.HTTMock(github_mock):
|
|
||||||
result = self.controller.get_one('2015.03')
|
result = self.controller.get_one('2015.03')
|
||||||
self.assertEqual({'foo': 'bar'}, result)
|
self.assertEqual({'foo': 'bar'}, result)
|
||||||
|
|
||||||
def test_get_capability_file_error_code(self):
|
@mock.patch('refstack.api.guidelines.Guidelines.get_guideline_contents')
|
||||||
"""Test when the HTTP status code isn't a 200 OK. The status should
|
def test_get_guideline_file_error(self, mock_get_contents):
|
||||||
be propogated."""
|
"""Test when there is a problem getting the guideline file contents."""
|
||||||
@httmock.all_requests
|
mock_get_contents.return_value = None
|
||||||
def github_api_mock(url, request):
|
|
||||||
content = {'title': 'Not Found'}
|
|
||||||
return httmock.response(404, content, None, None, 5, request)
|
|
||||||
|
|
||||||
with httmock.HTTMock(github_api_mock):
|
|
||||||
self.controller.get_one('2010.03')
|
self.controller.get_one('2010.03')
|
||||||
self.mock_abort.assert_called_with(404)
|
self.mock_abort.assert_called_with(500, mock.ANY)
|
||||||
|
|
||||||
@mock.patch('requests.get')
|
|
||||||
def test_get_capability_file_exception(self, mock_requests_get):
|
|
||||||
"""Test when the GET request raises an exception."""
|
|
||||||
mock_requests_get.side_effect = requests.exceptions.RequestException()
|
|
||||||
self.controller.get_one('2010.03')
|
|
||||||
self.mock_abort.assert_called_with(500)
|
|
||||||
|
|
||||||
|
|
||||||
class BaseRestControllerWithValidationTestCase(BaseControllerTestCase):
|
class BaseRestControllerWithValidationTestCase(BaseControllerTestCase):
|
||||||
|
90
refstack/tests/unit/test_guidelines.py
Normal file
90
refstack/tests/unit/test_guidelines.py
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
# Copyright (c) 2016 IBM, Inc.
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
import httmock
|
||||||
|
import mock
|
||||||
|
from oslotest import base
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from refstack.api import guidelines
|
||||||
|
|
||||||
|
|
||||||
|
class GuidelinesTestCase(base.BaseTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(GuidelinesTestCase, self).setUp()
|
||||||
|
self.guidelines = guidelines.Guidelines()
|
||||||
|
|
||||||
|
def test_guidelines_list(self):
|
||||||
|
@httmock.all_requests
|
||||||
|
def github_api_mock(url, request):
|
||||||
|
headers = {'content-type': 'application/json'}
|
||||||
|
content = [{'name': '2015.03.json', 'type': 'file'},
|
||||||
|
{'name': '2015.next.json', 'type': 'file'},
|
||||||
|
{'name': '2015.03', 'type': 'dir'}]
|
||||||
|
content = json.dumps(content)
|
||||||
|
return httmock.response(200, content, headers, None, 5, request)
|
||||||
|
with httmock.HTTMock(github_api_mock):
|
||||||
|
result = self.guidelines.get_guideline_list()
|
||||||
|
self.assertEqual(['2015.03.json'], result)
|
||||||
|
|
||||||
|
def test_get_guidelines_list_error_code(self):
|
||||||
|
"""Test when the HTTP status code isn't a 200 OK."""
|
||||||
|
@httmock.all_requests
|
||||||
|
def github_api_mock(url, request):
|
||||||
|
content = {'title': 'Not Found'}
|
||||||
|
return httmock.response(404, content, None, None, 5, request)
|
||||||
|
|
||||||
|
with httmock.HTTMock(github_api_mock):
|
||||||
|
result = self.guidelines.get_guideline_list()
|
||||||
|
self.assertIsNone(result)
|
||||||
|
|
||||||
|
@mock.patch('requests.get')
|
||||||
|
def test_get_guidelines_exception(self, mock_requests_get):
|
||||||
|
"""Test when the GET request raises an exception."""
|
||||||
|
mock_requests_get.side_effect = requests.exceptions.RequestException()
|
||||||
|
result = self.guidelines.get_guideline_list()
|
||||||
|
self.assertIsNone(result)
|
||||||
|
|
||||||
|
def test_get_capability_file(self):
|
||||||
|
"""Test when getting a specific guideline file"""
|
||||||
|
@httmock.all_requests
|
||||||
|
def github_mock(url, request):
|
||||||
|
content = {'foo': 'bar'}
|
||||||
|
return httmock.response(200, content, None, None, 5, request)
|
||||||
|
|
||||||
|
with httmock.HTTMock(github_mock):
|
||||||
|
result = self.guidelines.get_guideline_contents('2010.03.json')
|
||||||
|
self.assertEqual({'foo': 'bar'}, result)
|
||||||
|
|
||||||
|
def test_get_capability_file_error_code(self):
|
||||||
|
"""Test when the HTTP status code isn't a 200 OK."""
|
||||||
|
@httmock.all_requests
|
||||||
|
def github_api_mock(url, request):
|
||||||
|
content = {'title': 'Not Found'}
|
||||||
|
return httmock.response(404, content, None, None, 5, request)
|
||||||
|
|
||||||
|
with httmock.HTTMock(github_api_mock):
|
||||||
|
result = self.guidelines.get_guideline_contents('2010.03.json')
|
||||||
|
self.assertIsNone(result)
|
||||||
|
|
||||||
|
@mock.patch('requests.get')
|
||||||
|
def test_get_capability_file_exception(self, mock_requests_get):
|
||||||
|
"""Test when the GET request raises an exception."""
|
||||||
|
mock_requests_get.side_effect = requests.exceptions.RequestException()
|
||||||
|
result = self.guidelines.get_guideline_contents('2010.03.json')
|
||||||
|
self.assertIsNone(result)
|
@ -2,7 +2,7 @@ coverage>=3.6
|
|||||||
pep8==1.5.7
|
pep8==1.5.7
|
||||||
pyflakes==0.8.1
|
pyflakes==0.8.1
|
||||||
flake8==2.2.4
|
flake8==2.2.4
|
||||||
httmock
|
httmock>=1.2.4
|
||||||
mock
|
mock
|
||||||
oslotest>=1.2.0 # Apache-2.0
|
oslotest>=1.2.0 # Apache-2.0
|
||||||
python-subunit>=0.0.18
|
python-subunit>=0.0.18
|
||||||
|
Loading…
Reference in New Issue
Block a user