summaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rwxr-xr-xutils/fetch_os_creds.sh80
-rw-r--r--utils/push-test-logs.sh1
-rw-r--r--utils/test/reporting/LICENSE.txt4
-rw-r--r--utils/test/reporting/README.txt4
-rw-r--r--utils/test/reporting/api/api/handlers/testcases.py2
-rwxr-xr-xutils/test/reporting/functest/reporting-tempest.py19
-rw-r--r--utils/test/reporting/pages/app/images/overview.pngbin76161 -> 113333 bytes
-rw-r--r--utils/test/reporting/pages/app/scripts/controllers/testvisual.controller.js45
-rw-r--r--utils/test/reporting/pages/app/styles/custome.css1
-rw-r--r--utils/test/reporting/pages/app/views/commons/testCaseVisual.html7
-rw-r--r--utils/test/reporting/pages/app/views/modal/testcasedetail.html4
-rw-r--r--utils/test/testapi/3rd_party/static/testapi-ui/app.js16
-rwxr-xr-xutils/test/testapi/3rd_party/static/testapi-ui/assets/img/OpenStack_Project_Refstack_mascot_90x90.pngbin2670 -> 0 bytes
-rw-r--r--utils/test/testapi/3rd_party/static/testapi-ui/assets/img/openstack-logo.pngbin27091 -> 0 bytes
-rwxr-xr-xutils/test/testapi/3rd_party/static/testapi-ui/assets/img/refstack-logo.pngbin3485 -> 0 bytes
-rw-r--r--utils/test/testapi/3rd_party/static/testapi-ui/assets/img/testapi-logo.pngbin0 -> 7407 bytes
-rw-r--r--utils/test/testapi/3rd_party/static/testapi-ui/components/results/results.html192
-rw-r--r--utils/test/testapi/3rd_party/static/testapi-ui/components/results/resultsController.js31
-rw-r--r--utils/test/testapi/3rd_party/static/testapi-ui/config.json2
-rw-r--r--utils/test/testapi/3rd_party/static/testapi-ui/shared/alerts/alertModalFactory.js2
-rw-r--r--utils/test/testapi/etc/config.ini10
-rw-r--r--utils/test/testapi/opnfv_testapi/common/config.py5
-rw-r--r--utils/test/testapi/opnfv_testapi/resources/handlers.py26
-rw-r--r--utils/test/testapi/opnfv_testapi/resources/result_handlers.py43
-rw-r--r--utils/test/testapi/opnfv_testapi/router/url_mappings.py2
-rw-r--r--utils/test/testapi/opnfv_testapi/tests/unit/fake_pymongo.py25
-rw-r--r--utils/test/testapi/opnfv_testapi/ui/auth/sign.py9
27 files changed, 245 insertions, 285 deletions
diff --git a/utils/fetch_os_creds.sh b/utils/fetch_os_creds.sh
index 6a382a56c..993c0b948 100755
--- a/utils/fetch_os_creds.sh
+++ b/utils/fetch_os_creds.sh
@@ -7,11 +7,14 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-
+set -o errexit
+set -o nounset
+set -o pipefail
usage() {
- echo "usage: $0 [-v] -d <destination> -i <installer_type> -a <installer_ip>" >&2
+ echo "usage: $0 [-v] -d <destination> -i <installer_type> -a <installer_ip> [-s <ssh_key>]" >&2
echo "[-v] Virtualized deployment" >&2
+ echo "[-s <ssh_key>] Path to ssh key. For MCP deployments only" >&2
}
info () {
@@ -51,11 +54,12 @@ swap_to_public() {
: ${DEPLOY_TYPE:=''}
#Get options
-while getopts ":d:i:a:h:v" optchar; do
+while getopts ":d:i:a:h:s:v" optchar; do
case "${optchar}" in
d) dest_path=${OPTARG} ;;
i) installer_type=${OPTARG} ;;
a) installer_ip=${OPTARG} ;;
+ s) ssh_key=${OPTARG} ;;
v) DEPLOY_TYPE="virt" ;;
*) echo "Non-option argument: '-${OPTARG}'" >&2
usage
@@ -68,6 +72,9 @@ done
dest_path=${dest_path:-$HOME/opnfv-openrc.sh}
installer_type=${installer_type:-$INSTALLER_TYPE}
installer_ip=${installer_ip:-$INSTALLER_IP}
+if [ "${installer_type}" == "fuel" ] && [ "${BRANCH}" == "master" ]; then
+ installer_ip=${SALT_MASTER_IP}
+fi
if [ -z $dest_path ] || [ -z $installer_type ] || [ -z $installer_ip ]; then
usage
@@ -87,40 +94,45 @@ ssh_options="-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
# Start fetching the files
if [ "$installer_type" == "fuel" ]; then
- #ip_fuel="10.20.0.2"
verify_connectivity $installer_ip
+ if [ "${BRANCH}" == "master" ]; then
+ ssh_key=${ssh_key:-$SSH_KEY}
+ if [ -z $ssh_key ] || [ ! -f $ssh_key ]; then
+ error "Please provide path to existing ssh key for mcp deployment."
+ exit 2
+ fi
+ ssh_options+=" -i ${ssh_key}"
- env=$(sshpass -p r00tme ssh 2>/dev/null $ssh_options root@${installer_ip} \
- 'fuel env'|grep operational|head -1|awk '{print $1}') &> /dev/null
- if [ -z $env ]; then
- error "No operational environment detected in Fuel"
- fi
- env_id="${FUEL_ENV:-$env}"
-
- # Check if controller is alive (online='True')
- controller_ip=$(sshpass -p r00tme ssh 2>/dev/null $ssh_options root@${installer_ip} \
- "fuel node --env ${env_id} | grep controller | grep 'True\| 1' | awk -F\| '{print \$5}' | head -1" | \
- sed 's/ //g') &> /dev/null
+ # retrieving controller vip
+ controller_ip=$(ssh 2>/dev/null ${ssh_options} ubuntu@${installer_ip} \
+ "sudo salt --out txt 'ctl01*' pillar.get _param:openstack_control_address | awk '{print \$2}'" | \
+ sed 's/ //g') &> /dev/null
- if [ -z $controller_ip ]; then
- error "The controller $controller_ip is not up. Please check that the POD is correctly deployed."
- fi
+ info "Fetching rc file from controller $controller_ip..."
+ ssh ${ssh_options} ubuntu@${controller_ip} "sudo cat /root/keystonercv3" > $dest_path
+ else
+ #ip_fuel="10.20.0.2"
+ env=$(sshpass -p r00tme ssh 2>/dev/null ${ssh_options} root@${installer_ip} \
+ 'fuel env'|grep operational|head -1|awk '{print $1}') &> /dev/null
+ if [ -z $env ]; then
+ error "No operational environment detected in Fuel"
+ fi
+ env_id="${FUEL_ENV:-$env}"
- info "Fetching rc file from controller $controller_ip..."
- sshpass -p r00tme ssh 2>/dev/null $ssh_options root@${installer_ip} \
- "scp $ssh_options ${controller_ip}:/root/openrc ." &> /dev/null
- sshpass -p r00tme scp 2>/dev/null $ssh_options root@${installer_ip}:~/openrc $dest_path &> /dev/null
+ # Check if controller is alive (online='True')
+ controller_ip=$(sshpass -p r00tme ssh 2>/dev/null ${ssh_options} root@${installer_ip} \
+ "fuel node --env ${env_id} | grep controller | grep 'True\| 1' | awk -F\| '{print \$5}' | head -1" | \
+ sed 's/ //g') &> /dev/null
- #This file contains the mgmt keystone API, we need the public one for our rc file
- admin_ip=$(cat $dest_path | grep "OS_AUTH_URL" | sed 's/^.*\=//' | sed "s/^\([\"']\)\(.*\)\1\$/\2/g" | sed s'/\/$//')
- public_ip=$(sshpass -p r00tme ssh $ssh_options root@${installer_ip} \
- "ssh ${controller_ip} 'source openrc; openstack endpoint list'" \
- | grep keystone | grep public | sed 's/ /\n/g' | grep ^http | head -1) &> /dev/null
- #| grep http | head -1 | cut -d '|' -f 4 | sed 's/v1\/.*/v1\//' | sed 's/ //g') &> /dev/null
- #NOTE: this is super ugly sed 's/v1\/.*/v1\//'OS_AUTH_URL
- # but sometimes the output of endpoint-list is like this: http://172.30.9.70:8004/v1/%(tenant_id)s
- # Fuel virtual need a fix
+ if [ -z $controller_ip ]; then
+ error "The controller $controller_ip is not up. Please check that the POD is correctly deployed."
+ fi
+ info "Fetching rc file from controller $controller_ip..."
+ sshpass -p r00tme ssh 2>/dev/null ${ssh_options} root@${installer_ip} \
+ "scp ${ssh_options} ${controller_ip}:/root/openrc ." &> /dev/null
+ sshpass -p r00tme scp 2>/dev/null ${ssh_options} root@${installer_ip}:~/openrc $dest_path &> /dev/null
+ fi
#convert to v3 URL
auth_url=$(cat $dest_path|grep AUTH_URL)
if [[ -z `echo $auth_url |grep v3` ]]; then
@@ -157,8 +169,8 @@ elif [ "$installer_type" == "compass" ]; then
sshpass -p root scp 2>/dev/null $ssh_options root@${installer_ip}:~/admin-openrc.sh $dest_path &> /dev/null
info "This file contains the mgmt keystone API, we need the public one for our rc file"
- grep "OS_AUTH_URL.*v2" $dest_path > /dev/null 2>&1
- if [ $? -eq 0 ] ; then
+
+ if grep "OS_AUTH_URL.*v2" $dest_path > /dev/null 2>&1 ; then
public_ip=$(sshpass -p root ssh $ssh_options root@${installer_ip} \
"ssh ${controller_ip} 'source /opt/admin-openrc.sh; openstack endpoint show identity '" \
| grep publicurl | awk '{print $4}')
@@ -223,5 +235,3 @@ fi
echo "-------- Credentials: --------"
cat $dest_path
-
-exit 0
diff --git a/utils/push-test-logs.sh b/utils/push-test-logs.sh
index 9099657c8..f0c488a5a 100644
--- a/utils/push-test-logs.sh
+++ b/utils/push-test-logs.sh
@@ -22,6 +22,7 @@ dir_result="${HOME}/opnfv/$project/results/${branch}"
# + intel-pod12 (vsperf)
node_list=(\
'lf-pod1' 'lf-pod2' 'intel-pod2' 'intel-pod12' \
+'lf-virtual2' 'lf-virtual3' \
'intel-pod5' 'intel-pod6' 'intel-pod7' 'intel-pod8' \
'ericsson-pod1' 'ericsson-pod2' \
'ericsson-virtual1' 'ericsson-virtual2' 'ericsson-virtual3' \
diff --git a/utils/test/reporting/LICENSE.txt b/utils/test/reporting/LICENSE.txt
index d447b560b..4d0b33c6e 100644
--- a/utils/test/reporting/LICENSE.txt
+++ b/utils/test/reporting/LICENSE.txt
@@ -1,5 +1,5 @@
-Creative Commons Attribution 3.0 Unported
-http://creativecommons.org/licenses/by/3.0/
+This work is licensed under a Creative Commons Attribution 4.0 International License.
+SPDX-License-Identifier: CC-BY-4.0
License
diff --git a/utils/test/reporting/README.txt b/utils/test/reporting/README.txt
index 31b8d044d..049cf62ef 100644
--- a/utils/test/reporting/README.txt
+++ b/utils/test/reporting/README.txt
@@ -1,6 +1,6 @@
Phantom by HTML5 UP
html5up.net | @ajlkn
-Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
+SPDX-License-Identifier: CC-BY-4.0
This is Phantom, a simple design built around a grid of large, colorful, semi-interactive
@@ -30,4 +30,4 @@ Credits:
html5shiv.js (@afarkas @jdalton @jon_neal @rem)
Misc. Sass functions (@HugoGiraudel)
Respond.js (j.mp/respondjs)
- Skel (skel.io) \ No newline at end of file
+ Skel (skel.io)
diff --git a/utils/test/reporting/api/api/handlers/testcases.py b/utils/test/reporting/api/api/handlers/testcases.py
index 110ac4c26..2b9118623 100644
--- a/utils/test/reporting/api/api/handlers/testcases.py
+++ b/utils/test/reporting/api/api/handlers/testcases.py
@@ -20,7 +20,7 @@ class TestCases(BaseHandler):
url = '{}/projects/{}/cases'.format(conf.base_url, project)
cases = requests.get(url).json().get('testcases', [])
- data = [t['name'] for t in cases]
+ data = [{t['name']: t['catalog_description']} for t in cases]
self.write(json_encode(data))
diff --git a/utils/test/reporting/functest/reporting-tempest.py b/utils/test/reporting/functest/reporting-tempest.py
index 6e6585a32..0304298b4 100755
--- a/utils/test/reporting/functest/reporting-tempest.py
+++ b/utils/test/reporting/functest/reporting-tempest.py
@@ -1,4 +1,15 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2017 Orange and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+# SPDX-license-identifier: Apache-2.0
+
from urllib2 import Request, urlopen, URLError
+from datetime import datetime
import json
import jinja2
import os
@@ -97,7 +108,13 @@ for version in rp_utils.get_config('general.versions'):
crit_rate = True
# Expect that the suite duration is inferior to 30m
- if result['details']['duration'] < criteria_duration:
+ stop_date = datetime.strptime(result['stop_date'],
+ '%Y-%m-%d %H:%M:%S')
+ start_date = datetime.strptime(result['start_date'],
+ '%Y-%m-%d %H:%M:%S')
+
+ delta = stop_date - start_date
+ if (delta.total_seconds() < criteria_duration):
crit_time = True
result['criteria'] = {'tests': crit_tests,
diff --git a/utils/test/reporting/pages/app/images/overview.png b/utils/test/reporting/pages/app/images/overview.png
index 14dbbff42..f1688cf37 100644
--- a/utils/test/reporting/pages/app/images/overview.png
+++ b/utils/test/reporting/pages/app/images/overview.png
Binary files differ
diff --git a/utils/test/reporting/pages/app/scripts/controllers/testvisual.controller.js b/utils/test/reporting/pages/app/scripts/controllers/testvisual.controller.js
index 7082aede0..def8e7293 100644
--- a/utils/test/reporting/pages/app/scripts/controllers/testvisual.controller.js
+++ b/utils/test/reporting/pages/app/scripts/controllers/testvisual.controller.js
@@ -10,16 +10,16 @@
angular.module('opnfvApp')
.controller('testVisualController', ['$scope', '$state', '$stateParams', 'TableFactory', 'ngDialog', '$http', '$loading',
function($scope, $state, $stateParams, TableFactory, ngDialog, $http, $loading) {
- $scope.dovet = "59,222,156,317";
- $scope.functest = "203,163,334,365";
- $scope.yardstick = "398,161,513,384";
- $scope.vsperf = "567,163,673,350";
- $scope.stor = "686,165,789,341";
- $scope.qtip = "802,164,905,341";
- $scope.bootleneck = "917,161,1022,338";
- $scope.noPopArea1 = "30,11,1243,146";
- $scope.noPopArea2 = "1041,157,1250,561";
- $scope.noPopArea3 = "15,392,1027,561";
+ $scope.dovet = "50,168,177,443";
+ $scope.functest = "194,173,356,442";
+ $scope.yardstick = "377,183,521,412";
+ $scope.vsperf = "542,185,640,414";
+ $scope.stor = "658,187,750,410";
+ $scope.qtip = "769,190,852,416";
+ $scope.bootleneck = "870,192,983,419";
+ $scope.noPopArea1 = "26,8,1190,180";
+ $scope.noPopArea2 = "1018,193,1190,590";
+ $scope.noPopArea3 = "37,455,1003,584";
init();
$scope.showSelectValue = 0;
@@ -51,20 +51,41 @@ angular.module('opnfvApp')
$http.get(url, config).then(function(response) {
if (response.status == 200) {
$scope.tableData = response.data;
+
+ $scope.tableData = constructObjectArray($scope.tableData);
+ console.log($scope.tableData);
$loading.finish('Key');
+
}
})
}
+ //construct key value for tableData
+ function constructObjectArray(array) {
+ var templateArray = [];
+ for (var i = 0; i < array.length; i++) {
+ var key = Object.keys(array[i])[0];
+ var value = array[i][key];
+ var temp = {
+ 'key': key,
+ 'value': value
+ };
+ templateArray.push(temp);
+
+ }
+
+ return templateArray;
+ }
+
function getDetail(casename) {
TableFactory.getProjectTestCaseDetail().get({
'project': $scope.modalName,
'testcase': casename
}).$promise.then(function(response) {
if (response != null) {
- $scope.project_name_modal = response.project_name;
+ $scope.name_modal = response.name;
$scope.description_modal = response.description;
openTestDetail();
}
@@ -108,4 +129,4 @@ angular.module('opnfvApp')
}
- ]); \ No newline at end of file
+ ]);
diff --git a/utils/test/reporting/pages/app/styles/custome.css b/utils/test/reporting/pages/app/styles/custome.css
index 7ab869b56..8e567ca6e 100644
--- a/utils/test/reporting/pages/app/styles/custome.css
+++ b/utils/test/reporting/pages/app/styles/custome.css
@@ -71,6 +71,7 @@ html {
border-radius: 5px 5px 5px 5px;
background-color: #f3f3f4;
opacity: 0.9;
+ width: 200px;
}
.ngdialog.ngdialog.ngdialog-theme-default .ngdialog-content {
diff --git a/utils/test/reporting/pages/app/views/commons/testCaseVisual.html b/utils/test/reporting/pages/app/views/commons/testCaseVisual.html
index 9d146ba93..74eb56eba 100644
--- a/utils/test/reporting/pages/app/views/commons/testCaseVisual.html
+++ b/utils/test/reporting/pages/app/views/commons/testCaseVisual.html
@@ -4,7 +4,7 @@
<div class="row">
- <div class="row border-bottom white-bg dashboard-header" style="border-radius: 5px 5px 5px 5px ">
+ <div class="row border-bottom white-bg dashboard-header" style="border-radius: 5px 5px 5px 5px;width:90%;margin-left:30px; ">
<h3>OPNFV Test ecosystem
<small> *mouse over display test case list</small>
@@ -70,7 +70,7 @@
</div>
- <div id="popup" class="popup" style="width: 20%;height: 35%" dw-loading="Key">
+ <div id="popup" class="popup" style="width: 40%;height: 35%" dw-loading="Key">
<div ng-show="tableData.length==0">
<center>
@@ -90,7 +90,8 @@
<tbody>
<tr dir-paginate="data in tableData | itemsPerPage: 8 track by $index ">
- <td><a ng-click="getDetail(data)"> {{data}}</a></td>
+ <td ng-if="data.value!=null"><a ng-click="getDetail(data.key)"> {{data.value}}</a></td>
+ <td ng-if="data.value==null"><a ng-click="getDetail(data.key)"> null</a></td>
<tr>
</tbody>
diff --git a/utils/test/reporting/pages/app/views/modal/testcasedetail.html b/utils/test/reporting/pages/app/views/modal/testcasedetail.html
index 8918b3f74..db6f71295 100644
--- a/utils/test/reporting/pages/app/views/modal/testcasedetail.html
+++ b/utils/test/reporting/pages/app/views/modal/testcasedetail.html
@@ -2,6 +2,6 @@
<div class="hr-line-dashed"></div>
-<strong> name</strong>: {{project_name_modal}}<br>
+<strong> name</strong>: {{name_modal}}<br>
-<strong>description</strong>: {{description_modal}}<br> \ No newline at end of file
+<strong>description</strong>: {{description_modal}}<br>
diff --git a/utils/test/testapi/3rd_party/static/testapi-ui/app.js b/utils/test/testapi/3rd_party/static/testapi-ui/app.js
index 4a2f23af9..8c701c36c 100644
--- a/utils/test/testapi/3rd_party/static/testapi-ui/app.js
+++ b/utils/test/testapi/3rd_party/static/testapi-ui/app.js
@@ -37,30 +37,30 @@
$stateProvider.
state('home', {
url: '/',
- templateUrl: '/testapi-ui/components/home/home.html'
+ templateUrl: 'testapi-ui/components/home/home.html'
}).
state('about', {
url: '/about',
- templateUrl: '/testapi-ui/components/about/about.html'
+ templateUrl: 'testapi-ui/components/about/about.html'
}).
state('guidelines', {
url: '/guidelines',
- templateUrl: '/testapi-ui/components/guidelines/guidelines.html',
+ templateUrl: 'testapi-ui/components/guidelines/guidelines.html',
controller: 'GuidelinesController as ctrl'
}).
state('communityResults', {
url: '/community_results',
- templateUrl: '/testapi-ui/components/results/results.html',
+ templateUrl: 'testapi-ui/components/results/results.html',
controller: 'ResultsController as ctrl'
}).
state('userResults', {
- url: '/user_results',
+ url: 'user_results',
templateUrl: '/testapi-ui/components/results/results.html',
controller: 'ResultsController as ctrl'
}).
state('resultsDetail', {
url: '/results/:testID',
- templateUrl: '/testapi-ui/components/results-report' +
+ templateUrl: 'testapi-ui/components/results-report' +
'/resultsReport.html',
controller: 'ResultsReportController as ctrl'
}).
@@ -71,12 +71,12 @@
}).
state('authFailure', {
url: '/auth_failure',
- templateUrl: '/testapi-ui/components/home/home.html',
+ templateUrl: 'testapi-ui/components/home/home.html',
controller: 'AuthFailureController as ctrl'
}).
state('logout', {
url: '/logout',
- templateUrl: '/testapi-ui/components/logout/logout.html',
+ templateUrl: 'testapi-ui/components/logout/logout.html',
controller: 'LogoutController as ctrl'
}).
state('userVendors', {
diff --git a/utils/test/testapi/3rd_party/static/testapi-ui/assets/img/OpenStack_Project_Refstack_mascot_90x90.png b/utils/test/testapi/3rd_party/static/testapi-ui/assets/img/OpenStack_Project_Refstack_mascot_90x90.png
deleted file mode 100755
index 4695090dc..000000000
--- a/utils/test/testapi/3rd_party/static/testapi-ui/assets/img/OpenStack_Project_Refstack_mascot_90x90.png
+++ /dev/null
Binary files differ
diff --git a/utils/test/testapi/3rd_party/static/testapi-ui/assets/img/openstack-logo.png b/utils/test/testapi/3rd_party/static/testapi-ui/assets/img/openstack-logo.png
deleted file mode 100644
index 826bf2e5d..000000000
--- a/utils/test/testapi/3rd_party/static/testapi-ui/assets/img/openstack-logo.png
+++ /dev/null
Binary files differ
diff --git a/utils/test/testapi/3rd_party/static/testapi-ui/assets/img/refstack-logo.png b/utils/test/testapi/3rd_party/static/testapi-ui/assets/img/refstack-logo.png
deleted file mode 100755
index fc45f3ee0..000000000
--- a/utils/test/testapi/3rd_party/static/testapi-ui/assets/img/refstack-logo.png
+++ /dev/null
Binary files differ
diff --git a/utils/test/testapi/3rd_party/static/testapi-ui/assets/img/testapi-logo.png b/utils/test/testapi/3rd_party/static/testapi-ui/assets/img/testapi-logo.png
new file mode 100644
index 000000000..ff78eb1ee
--- /dev/null
+++ b/utils/test/testapi/3rd_party/static/testapi-ui/assets/img/testapi-logo.png
Binary files differ
diff --git a/utils/test/testapi/3rd_party/static/testapi-ui/components/results/results.html b/utils/test/testapi/3rd_party/static/testapi-ui/components/results/results.html
index 2a43cd1e2..3056e1dbe 100644
--- a/utils/test/testapi/3rd_party/static/testapi-ui/components/results/results.html
+++ b/utils/test/testapi/3rd_party/static/testapi-ui/components/results/results.html
@@ -43,184 +43,36 @@
<div cg-busy="{promise:ctrl.resultsRequest,message:'Loading'}"></div>
<div ng-show="ctrl.data" class="results-table">
- <table ng-show="ctrl.data" class="table table-striped table-hover">
+ <table ng-data="ctrl.data.result" ng-show="ctrl.data" class="table table-striped table-hover">
<thead>
<tr>
- <th ng-if="ctrl.isUserResults"></th>
- <th>Upload Date</th>
- <th>Test Run ID</th>
- <th ng-if="ctrl.isUserResults">Vendor</th>
- <th ng-if="ctrl.isUserResults">Product (version)</th>
- <th ng-if="ctrl.isUserResults">Target Program</th>
- <th ng-if="ctrl.isUserResults">Guideline</th>
- <th ng-if="ctrl.isUserResults">Verified</th>
- <th ng-if="ctrl.isUserResults">Shared</th>
+ <th>ID</th>
+ <th>Pod</th>
+ <th>Project</th>
+ <th>Test Case</th>
+ <th>Installer</th>
+ <th>Version</th>
+ <th>Scenario</th>
+ <th>Criteria</th>
+ <th>Start Date</th>
+ <th>Stop Date</th>
</tr>
</thead>
<tbody>
<tr ng-repeat-start="(index, result) in ctrl.data.results">
- <td ng-if="ctrl.isUserResults">
- <a ng-if="!result.expanded"
- class="glyphicon glyphicon-plus"
- ng-click="result.expanded = true">
- </a>
- <a ng-if="result.expanded"
- class="glyphicon glyphicon-minus"
- ng-click="result.expanded = false">
- </a>
- </td>
- <td>{{result.created_at}}</td>
- <td><a ui-sref="resultsDetail({testID: result.id})">
- {{result.id.slice(0, 8)}}...{{result.id.slice(-8)}}
- </a>
- </td>
- <td ng-if="ctrl.isUserResults">
- {{ctrl.vendors[result.product_version.product_info.organization_id].name || '-'}}
- </td>
- <td ng-if="ctrl.isUserResults">{{result.product_version.product_info.name || '-'}}
- <span ng-if="result.product_version.version">
- ({{result.product_version.version}})
- </span>
- </td>
- <td ng-if="ctrl.isUserResults">{{ctrl.targetMappings[result.meta.target] || '-'}}</td>
- <td ng-if="ctrl.isUserResults">{{result.meta.guideline.slice(0, -5) || '-'}}</td>
- <td ng-if="ctrl.isUserResults">
- <span ng-if="result.verification_status" class="glyphicon glyphicon-ok"></span>
- <span ng-if="!result.verification_status">-</span>
-
- </td>
- <td ng-if="ctrl.isUserResults">
- <span ng-show="result.meta.shared" class="glyphicon glyphicon-share"></span>
- </td>
+ <td>{{ result._id }}</td>
+ <td>{{ result.pod_name }}</td>
+ <td>{{ result.project_name }}</td>
+ <td>{{ result.case_name }}</td>
+ <td>{{ result.installer }}</td>
+ <td>{{ result.version }}</td>
+ <td>{{ result.scenario }}</td>
+ <td>{{ result.criteria }}</td>
+ <td>{{ result.start_date }}</td>
+ <td>{{ result.stop_date }}</td>
</tr>
- <tr ng-if="result.expanded" ng-repeat-end>
- <td></td>
- <td colspan="3">
- <strong>Publicly Shared:</strong>
- <span ng-if="result.meta.shared == 'true' && !result.sharedEdit">Yes</span>
- <span ng-if="!result.meta.shared && !result.sharedEdit">
- <em>No</em>
- </span>
- <select ng-if="result.sharedEdit"
- ng-model="result.meta.shared"
- class="form-inline">
- <option value="true">Yes</option>
- <option value="">No</option>
- </select>
- <a ng-if="!result.sharedEdit"
- ng-click="result.sharedEdit = true"
- title="Edit"
- class="glyphicon glyphicon-pencil"></a>
- <a ng-if="result.sharedEdit"
- ng-click="ctrl.associateMeta(index,'shared',result.meta.shared)"
- title="Save"
- class="glyphicon glyphicon-floppy-disk"></a>
- <br />
-
- <strong>Associated Guideline:</strong>
- <span ng-if="!result.meta.guideline && !result.guidelineEdit">
- <em>None</em>
- </span>
- <span ng-if="result.meta.guideline && !result.guidelineEdit">
- {{result.meta.guideline.slice(0, -5)}}
- </span>
- <select ng-if="result.guidelineEdit"
- ng-model="result.meta.guideline"
- ng-options="o as o.slice(0, -5) for o in ctrl.versionList"
- class="form-inline">
- <option value="">None</option>
- </select>
- <a ng-if="!result.guidelineEdit"
- ng-click="ctrl.getVersionList();result.guidelineEdit = true"
- title="Edit"
- class="glyphicon glyphicon-pencil"></a>
- <a ng-if="result.guidelineEdit"
- ng-click="ctrl.associateMeta(index, 'guideline', result.meta.guideline)"
- title="Save"
- class="glyphicon glyphicon-floppy-disk">
- </a>
- <br />
-
- <strong>Associated Target Program:</strong>
- <span ng-if="!result.meta.target && !result.targetEdit">
- <em>None</em>
- </span>
- <span ng-if="result.meta.target && !result.targetEdit">
- {{ctrl.targetMappings[result.meta.target]}}</span>
- <select ng-if="result.targetEdit"
- ng-model="result.meta.target"
- class="form-inline">
- <option value="">None</option>
- <option value="platform">OpenStack Powered Platform</option>
- <option value="compute">OpenStack Powered Compute</option>
- <option value="object">OpenStack Powered Object Storage</option>
- </select>
- <a ng-if="!result.targetEdit"
- ng-click="result.targetEdit = true;"
- title="Edit"
- class="glyphicon glyphicon-pencil">
- </a>
- <a ng-if="result.targetEdit"
- ng-click="ctrl.associateMeta(index, 'target', result.meta.target)"
- title="Save"
- class="glyphicon glyphicon-floppy-disk">
- </a>
- <br />
-
- <strong>Associated Product:</strong>
- <span ng-if="!result.product_version && !result.productEdit">
- <em>None</em>
- </span>
- <span ng-if="result.product_version && !result.productEdit">
- <span ng-if="ctrl.products[result.product_version.product_info.id].product_type == 0">
- <a ui-sref="distro({id: result.product_version.product_info.id})">
- {{ctrl.products[result.product_version.product_info.id].name}}
- <small ng-if="result.product_version.version">
- ({{result.product_version.version}})
- </small>
- </a>
- </span>
- <span ng-if="ctrl.products[result.product_version.product_info.id].product_type != 0">
- <a ui-sref="cloud({id: result.product_version.product_info.id})">
- {{ctrl.products[result.product_version.product_info.id].name}}
- <small ng-if="result.product_version.version">
- ({{result.product_version.version}})
- </small>
- </a>
- </span>
- </span>
-
- <select ng-if="result.productEdit"
- ng-options="product as product.name for product in ctrl.products | arrayConverter | orderBy: 'name' track by product.id"
- ng-model="result.selectedProduct"
- ng-change="ctrl.getProductVersions(result)">
- <option value="">-- No Product --</option>
- </select>
-
- <span ng-if="result.productVersions.length && result.productEdit">
- <span class="glyphicon glyphicon-arrow-right" style="padding-right:3px;color:#303030;"></span>
- Version:
- <select ng-options="version as version.version for version in result.productVersions | orderBy: 'version' track by version.id"
- ng-model="result.selectedVersion">
- </select>
-
- </span>
- <a ng-if="!result.productEdit"
- ng-click="ctrl.prepVersionEdit(result)"
- title="Edit"
- class="glyphicon glyphicon-pencil">
- </a>
- <a ng-if="result.productEdit"
- ng-click="ctrl.associateProductVersion(result)"
- confirm="Once you associate this test to this product, ownership
- will be transferred to the product's vendor admins.
- Continue?"
- title="Save"
- class="glyphicon glyphicon-floppy-disk">
- </a>
- <br />
- </td>
+ <tr ng-repeat-end=>
</tr>
</tbody>
</table>
diff --git a/utils/test/testapi/3rd_party/static/testapi-ui/components/results/resultsController.js b/utils/test/testapi/3rd_party/static/testapi-ui/components/results/resultsController.js
index 2b0338c87..9e3540da5 100644
--- a/utils/test/testapi/3rd_party/static/testapi-ui/components/results/resultsController.js
+++ b/utils/test/testapi/3rd_party/static/testapi-ui/components/results/resultsController.js
@@ -38,7 +38,6 @@
ctrl.associateMeta = associateMeta;
ctrl.getVersionList = getVersionList;
ctrl.getUserProducts = getUserProducts;
- ctrl.getVendors = getVendors;
ctrl.associateProductVersion = associateProductVersion;
ctrl.getProductVersions = getProductVersions;
ctrl.prepVersionEdit = prepVersionEdit;
@@ -100,8 +99,6 @@
ctrl.update();
}
- ctrl.getVendors();
-
/**
* This will contact the TestAPI API to get a listing of test run
* results.
@@ -114,11 +111,11 @@
var start = $filter('date')(ctrl.startDate, 'yyyy-MM-dd');
if (start) {
content_url =
- content_url + '&start_date=' + start + ' 00:00:00';
+ content_url + '&from=' + start + ' 00:00:00';
}
var end = $filter('date')(ctrl.endDate, 'yyyy-MM-dd');
if (end) {
- content_url = content_url + '&end_date=' + end + ' 23:59:59';
+ content_url = content_url + '&to=' + end + ' 23:59:59';
}
if (ctrl.isUserResults) {
content_url = content_url + '&signed';
@@ -126,8 +123,7 @@
ctrl.resultsRequest =
$http.get(content_url).success(function (data) {
ctrl.data = data;
- ctrl.totalItems = ctrl.data.pagination.total_pages *
- ctrl.itemsPerPage;
+ ctrl.totalItems = ctrl.data.pagination.total_pages * ctrl.itemsPerPage;
ctrl.currentPage = ctrl.data.pagination.current_page;
}).error(function (error) {
ctrl.data = null;
@@ -248,27 +244,6 @@
}
/**
- * This will contact the TestAPI API to get a listing of
- * vendors.
- */
- function getVendors() {
- var contentUrl = testapiApiUrl + '/vendors';
- ctrl.vendorsRequest =
- $http.get(contentUrl).success(function (data) {
- ctrl.vendors = {};
- data.vendors.forEach(function(vendor) {
- ctrl.vendors[vendor.id] = vendor;
- });
- }).error(function (error) {
- ctrl.vendors = null;
- ctrl.showError = true;
- ctrl.error =
- 'Error retrieving vendor listing from server: ' +
- angular.toJson(error);
- });
- }
-
- /**
* Send a PUT request to the API server to associate a product with
* a test result.
*/
diff --git a/utils/test/testapi/3rd_party/static/testapi-ui/config.json b/utils/test/testapi/3rd_party/static/testapi-ui/config.json
index 5d48c7b12..9fdd85fbb 100644
--- a/utils/test/testapi/3rd_party/static/testapi-ui/config.json
+++ b/utils/test/testapi/3rd_party/static/testapi-ui/config.json
@@ -1 +1 @@
-{"testapiApiUrl": "http://localhost:8000/api/v1"}
+{"testapiApiUrl": "http://testresults.opnfv.org/test/api/v1"}
diff --git a/utils/test/testapi/3rd_party/static/testapi-ui/shared/alerts/alertModalFactory.js b/utils/test/testapi/3rd_party/static/testapi-ui/shared/alerts/alertModalFactory.js
index 3ce76c912..929f5433c 100644
--- a/utils/test/testapi/3rd_party/static/testapi-ui/shared/alerts/alertModalFactory.js
+++ b/utils/test/testapi/3rd_party/static/testapi-ui/shared/alerts/alertModalFactory.js
@@ -28,7 +28,7 @@
function raiseAlert($uibModal) {
return function(mode, title, text) {
$uibModal.open({
- templateUrl: '/shared/alerts/alertModal.html',
+ templateUrl: 'testapi-ui/shared/alerts/alertModal.html',
controller: 'RaiseAlertModalController as alert',
backdrop: true,
keyboard: true,
diff --git a/utils/test/testapi/etc/config.ini b/utils/test/testapi/etc/config.ini
index 692e48897..dad59d2d0 100644
--- a/utils/test/testapi/etc/config.ini
+++ b/utils/test/testapi/etc/config.ini
@@ -8,8 +8,12 @@ dbname = test_results_collection
[api]
# Listening port
-url = http://localhost:8000/api/v1
+url = http://testresults.opnfv.org/test/api/v1
port = 8000
+
+# Number of results for one page (integer value)
+#results_per_page = 20
+
# With debug_on set to true, error traces will be shown in HTTP responses
debug = True
authenticate = False
@@ -18,7 +22,7 @@ authenticate = False
base_url = http://localhost:8000
[ui]
-url = http://localhost:8000
+url = http://testresults.opnfv.org/test
[osid]
@@ -41,7 +45,7 @@ openid_ns = http://specs.openid.net/auth/2.0
# Return endpoint in Refstack's API. Value indicating the endpoint
# where the user should be returned to after signing in. Openstack Id
# Idp only supports HTTPS address types. (string value)
-openid_return_to = /api/v1/auth/signin_return
+openid_return_to = v1/auth/signin_return
# Claimed identifier. This value must be set to
# "http://specs.openid.net/auth/2.0/identifier_select". or to user
diff --git a/utils/test/testapi/opnfv_testapi/common/config.py b/utils/test/testapi/opnfv_testapi/common/config.py
index 46765ffd1..f73c0abf2 100644
--- a/utils/test/testapi/opnfv_testapi/common/config.py
+++ b/utils/test/testapi/opnfv_testapi/common/config.py
@@ -17,6 +17,7 @@ class Config(object):
def __init__(self):
self.file = self.CONFIG if self.CONFIG else self._default_config()
self._parse()
+ self._parse_per_page()
self.static_path = os.path.join(
os.path.dirname(os.path.normpath(__file__)),
os.pardir,
@@ -37,6 +38,10 @@ class Config(object):
[setattr(self, '{}_{}'.format(section, k), self._parse_value(v))
for k, v in config.items(section)]
+ def _parse_per_page(self):
+ if not hasattr(self, 'api_results_per_page'):
+ self.api_results_per_page = 20
+
@staticmethod
def _parse_value(value):
try:
diff --git a/utils/test/testapi/opnfv_testapi/resources/handlers.py b/utils/test/testapi/opnfv_testapi/resources/handlers.py
index 2fc31ca45..42372e837 100644
--- a/utils/test/testapi/opnfv_testapi/resources/handlers.py
+++ b/utils/test/testapi/opnfv_testapi/resources/handlers.py
@@ -104,17 +104,35 @@ class GenericApiHandler(web.RequestHandler):
if query is None:
query = {}
data = []
+ sort = kwargs.get('sort')
+ page = kwargs.get('page')
+ last = kwargs.get('last')
+ per_page = kwargs.get('per_page')
+
cursor = self._eval_db(self.table, 'find', query)
- if 'sort' in kwargs:
- cursor = cursor.sort(kwargs.get('sort'))
- if 'last' in kwargs:
- cursor = cursor.limit(kwargs.get('last'))
+ if sort:
+ cursor = cursor.sort(sort)
+ if last and last != 0:
+ cursor = cursor.limit(last)
+ if page:
+ records_count = yield cursor.count()
+ total_pages, remainder = divmod(records_count, per_page)
+ if remainder > 0:
+ total_pages += 1
+ cursor = cursor.skip((page - 1) * per_page).limit(per_page)
while (yield cursor.fetch_next):
data.append(self.format_data(cursor.next_object()))
if res_op is None:
res = {self.table: data}
else:
res = res_op(data, *args)
+ if page:
+ res.update({
+ 'pagination': {
+ 'current_page': page,
+ 'total_pages': total_pages
+ }
+ })
self.finish_request(res)
@web.asynchronous
diff --git a/utils/test/testapi/opnfv_testapi/resources/result_handlers.py b/utils/test/testapi/opnfv_testapi/resources/result_handlers.py
index 214706f5f..208af6da2 100644
--- a/utils/test/testapi/opnfv_testapi/resources/result_handlers.py
+++ b/utils/test/testapi/opnfv_testapi/resources/result_handlers.py
@@ -11,12 +11,15 @@ from datetime import timedelta
from bson import objectid
+from opnfv_testapi.common import config
from opnfv_testapi.common import message
from opnfv_testapi.common import raises
from opnfv_testapi.resources import handlers
from opnfv_testapi.resources import result_models
from opnfv_testapi.tornado_swagger import swagger
+CONF = config.Config()
+
class GenericResultHandler(handlers.GenericApiHandler):
def __init__(self, application, request, **kwargs):
@@ -35,6 +38,8 @@ class GenericResultHandler(handlers.GenericApiHandler):
def set_query(self):
query = dict()
+ date_range = dict()
+
for k in self.request.query_arguments.keys():
v = self.get_query_argument(k)
if k == 'project' or k == 'pod' or k == 'case':
@@ -47,8 +52,14 @@ class GenericResultHandler(handlers.GenericApiHandler):
query['start_date'] = obj
elif k == 'trust_indicator':
query[k + '.current'] = float(v)
- elif k != 'last':
+ elif k == 'from':
+ date_range.update({'$gte': str(v)})
+ elif k == 'to':
+ date_range.update({'$lt': str(v)})
+ elif k != 'last' and k != 'page':
query[k] = v
+ if date_range:
+ query['start_date'] = date_range
return query
@@ -64,9 +75,11 @@ class ResultsCLHandler(GenericResultHandler):
- case : case name
- pod : pod name
- version : platform version (Arno-R1, ...)
- - installer (fuel, ...)
+ - installer : fuel/apex/compass/joid/daisy
- build_tag : Jenkins build tag name
- - period : x (x last days)
+ - period : x last days, incompatible with from/to
+ - from : starting time in 2016-01-01 or 2016-01-01 00:01:23
+ - to : ending time in 2016-01-01 or 2016-01-01 00:01:23
- scenario : the test scenario (previously version)
- criteria : the global criteria status passed or failed
- trust_indicator : evaluate the stability of the test case
@@ -113,22 +126,40 @@ class ResultsCLHandler(GenericResultHandler):
@type period: L{string}
@in period: query
@required period: False
+ @param from: i.e. 2016-01-01 or 2016-01-01 00:01:23
+ @type from: L{string}
+ @in from: query
+ @required from: False
+ @param to: i.e. 2016-01-01 or 2016-01-01 00:01:23
+ @type to: L{string}
+ @in to: query
+ @required to: False
@param last: last records stored until now
@type last: L{string}
@in last: query
@required last: False
+ @param page: which page to list
+ @type page: L{int}
+ @in page: query
+ @required page: False
@param trust_indicator: must be float
@type trust_indicator: L{float}
@in trust_indicator: query
@required trust_indicator: False
"""
+ limitations = {'sort': [('start_date', -1)]}
last = self.get_query_argument('last', 0)
if last is not None:
last = self.get_int('last', last)
+ limitations.update({'last': last})
+
+ page = self.get_query_argument('page', 1)
+ if page is not None:
+ page = self.get_int('page', page)
+ limitations.update({'page': page,
+ 'per_page': CONF.api_results_per_page})
- self._list(query=self.set_query(),
- sort=[('start_date', -1)],
- last=last)
+ self._list(query=self.set_query(), **limitations)
@swagger.operation(nickname="createTestResult")
def post(self):
diff --git a/utils/test/testapi/opnfv_testapi/router/url_mappings.py b/utils/test/testapi/opnfv_testapi/router/url_mappings.py
index aea85a4c4..a2312de09 100644
--- a/utils/test/testapi/opnfv_testapi/router/url_mappings.py
+++ b/utils/test/testapi/opnfv_testapi/router/url_mappings.py
@@ -55,7 +55,7 @@ mappings = [
(r"/api/v1/scenarios/([^/]+)", scenario_handlers.ScenarioGURHandler),
# static path
- (r'/(.*\.(css|png|gif|js|html|json|map))',
+ (r'/(.*\.(css|png|gif|js|html|json|map|woff2|woff|ttf))',
tornado.web.StaticFileHandler,
{'path': config.Config().static_path}),
diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/fake_pymongo.py b/utils/test/testapi/opnfv_testapi/tests/unit/fake_pymongo.py
index ef74a0857..b2564a6de 100644
--- a/utils/test/testapi/opnfv_testapi/tests/unit/fake_pymongo.py
+++ b/utils/test/testapi/opnfv_testapi/tests/unit/fake_pymongo.py
@@ -20,18 +20,18 @@ def thread_execute(method, *args, **kwargs):
class MemCursor(object):
def __init__(self, collection):
self.collection = collection
- self.count = len(self.collection)
+ self.length = len(self.collection)
self.sorted = []
def _is_next_exist(self):
- return self.count != 0
+ return self.length != 0
@property
def fetch_next(self):
return thread_execute(self._is_next_exist)
def next_object(self):
- self.count -= 1
+ self.length -= 1
return self.collection.pop()
def sort(self, key_or_list):
@@ -48,10 +48,25 @@ class MemCursor(object):
def limit(self, limit):
if limit != 0 and limit < len(self.collection):
- self.collection = self.collection[0:limit]
- self.count = limit
+ self.collection = self.collection[0: limit]
+ self.length = limit
return self
+ def skip(self, skip):
+ if skip < self.length and (skip > 0):
+ self.collection = self.collection[self.length - skip: -1]
+ self.length -= skip
+ elif skip >= self.length:
+ self.collection = []
+ self.length = 0
+ return self
+
+ def _count(self):
+ return self.length
+
+ def count(self):
+ return thread_execute(self._count)
+
class MemDb(object):
diff --git a/utils/test/testapi/opnfv_testapi/ui/auth/sign.py b/utils/test/testapi/opnfv_testapi/ui/auth/sign.py
index 73190841f..6a9d94eb2 100644
--- a/utils/test/testapi/opnfv_testapi/ui/auth/sign.py
+++ b/utils/test/testapi/opnfv_testapi/ui/auth/sign.py
@@ -32,6 +32,9 @@ class SigninHandler(base.BaseHandler):
class SigninReturnHandler(base.BaseHandler):
def get(self):
+ if self.get_query_argument(const.OPENID_MODE) == 'cancel':
+ self._auth_failure('Authentication canceled.')
+
openid = self.get_query_argument(const.OPENID_CLAIMED_ID)
user_info = {
'openid': openid,
@@ -44,6 +47,12 @@ class SigninReturnHandler(base.BaseHandler):
self.set_secure_cookie('openid', openid)
self.redirect(url=CONF.ui_url)
+ def _auth_failure(self, message):
+ params = {'message': message}
+ url = parse.urljoin(CONF.ui_url,
+ '/#/auth_failure?' + parse.urlencode(params))
+ self.redirect(url)
+
class SignoutHandler(base.BaseHandler):
def get(self):