From 04ef201b1e8f5f3dcfde4319854b81c25240e63f Mon Sep 17 00:00:00 2001 From: chenjiankun Date: Tue, 21 Mar 2017 14:48:54 +0000 Subject: Create Catalogue page JIRA: RELENG-193 1.create a page to list all project. 2.This page can get test case list of certain project. 3.This page can show information of certain test case. Change-Id: I79e0d3aafa99c054865a0d2948b99918802f32a7 Signed-off-by: chenjiankun --- utils/test/reporting/api/__init__.py | 0 utils/test/reporting/api/api/__init__.py | 0 utils/test/reporting/api/api/conf.py | 1 + utils/test/reporting/api/api/handlers/__init__.py | 19 +++ utils/test/reporting/api/api/handlers/landing.py | 169 ++++++++++++++++++++ utils/test/reporting/api/api/handlers/projects.py | 27 ++++ utils/test/reporting/api/api/handlers/testcases.py | 33 ++++ utils/test/reporting/api/api/server.py | 27 ++++ utils/test/reporting/api/api/urls.py | 20 +++ utils/test/reporting/api/handlers/__init__.py | 0 utils/test/reporting/api/handlers/landing.py | 177 --------------------- utils/test/reporting/api/install.sh | 3 - utils/test/reporting/api/requirements.txt | 3 + utils/test/reporting/api/server.py | 27 ---- utils/test/reporting/api/setup.cfg | 32 ++++ utils/test/reporting/api/setup.py | 9 ++ utils/test/reporting/api/urls.py | 14 -- 17 files changed, 340 insertions(+), 221 deletions(-) delete mode 100644 utils/test/reporting/api/__init__.py create mode 100644 utils/test/reporting/api/api/__init__.py create mode 100644 utils/test/reporting/api/api/conf.py create mode 100644 utils/test/reporting/api/api/handlers/__init__.py create mode 100644 utils/test/reporting/api/api/handlers/landing.py create mode 100644 utils/test/reporting/api/api/handlers/projects.py create mode 100644 utils/test/reporting/api/api/handlers/testcases.py create mode 100644 utils/test/reporting/api/api/server.py create mode 100644 utils/test/reporting/api/api/urls.py delete mode 100644 utils/test/reporting/api/handlers/__init__.py delete mode 100644 utils/test/reporting/api/handlers/landing.py delete mode 100755 utils/test/reporting/api/install.sh create mode 100644 utils/test/reporting/api/requirements.txt delete mode 100644 utils/test/reporting/api/server.py create mode 100644 utils/test/reporting/api/setup.cfg create mode 100644 utils/test/reporting/api/setup.py delete mode 100644 utils/test/reporting/api/urls.py (limited to 'utils/test/reporting/api') diff --git a/utils/test/reporting/api/__init__.py b/utils/test/reporting/api/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/utils/test/reporting/api/api/__init__.py b/utils/test/reporting/api/api/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/utils/test/reporting/api/api/conf.py b/utils/test/reporting/api/api/conf.py new file mode 100644 index 000000000..5897d4f97 --- /dev/null +++ b/utils/test/reporting/api/api/conf.py @@ -0,0 +1 @@ +base_url = 'http://testresults.opnfv.org/test/api/v1' diff --git a/utils/test/reporting/api/api/handlers/__init__.py b/utils/test/reporting/api/api/handlers/__init__.py new file mode 100644 index 000000000..bcda66438 --- /dev/null +++ b/utils/test/reporting/api/api/handlers/__init__.py @@ -0,0 +1,19 @@ +############################################################################## +# Copyright (c) 2017 Huawei Technologies Co.,Ltd 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 +############################################################################## +from tornado.web import RequestHandler + + +class BaseHandler(RequestHandler): + def _set_header(self): + self.set_header('Access-Control-Allow-Origin', '*') + self.set_header('Access-Control-Allow-Headers', + 'Content-Type, Content-Length, Authorization, \ + Accept, X-Requested-With , PRIVATE-TOKEN') + self.set_header('Access-Control-Allow-Methods', + 'PUT, POST, GET, DELETE, OPTIONS') diff --git a/utils/test/reporting/api/api/handlers/landing.py b/utils/test/reporting/api/api/handlers/landing.py new file mode 100644 index 000000000..749916fb6 --- /dev/null +++ b/utils/test/reporting/api/api/handlers/landing.py @@ -0,0 +1,169 @@ +############################################################################## +# Copyright (c) 2016 Huawei Technologies Co.,Ltd 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 +############################################################################## +import requests + +from tornado.escape import json_encode +from tornado.escape import json_decode + +from api.handlers import BaseHandler +from api import conf + + +class FiltersHandler(BaseHandler): + def get(self): + self._set_header() + + filters = { + 'filters': { + 'status': ['success', 'warning', 'danger'], + 'projects': ['functest', 'yardstick'], + 'installers': ['apex', 'compass', 'fuel', 'joid'], + 'version': ['colorado', 'master'], + 'loops': ['daily', 'weekly', 'monthly'], + 'time': ['10 days', '30 days'] + } + } + return self.write(json_encode(filters)) + + +class ScenariosHandler(BaseHandler): + def post(self): + self._set_header() + + body = json_decode(self.request.body) + args = self._get_args(body) + + scenarios = self._get_result_data(self._get_scenarios(), args) + + return self.write(json_encode(dict(scenarios=scenarios))) + + def _get_result_data(self, data, args): + data = self._filter_status(data, args) + return {s: self._get_scenario_result(s, data[s], args) for s in data} + + def _filter_status(self, data, args): + return {k: v for k, v in data.items() if v['status'] in args['status']} + + def _get_scenario_result(self, scenario, data, args): + result = { + 'status': data.get('status'), + 'installers': self._get_installers_result(data['installers'], args) + } + return result + + def _get_installers_result(self, data, args): + func = self._get_installer_result + return {k: func(k, data.get(k, {}), args) for k in args['installers']} + + def _get_installer_result(self, installer, data, args): + projects = data.get(args['version'], []) + return [self._get_project_data(projects, p) for p in args['projects']] + + def _get_project_data(self, projects, project): + atom = { + 'project': project, + 'score': None, + 'status': None + } + for p in projects: + if p['project'] == project: + return p + return atom + + def _get_scenarios(self): + url = '{}/scenarios'.format(conf.base_url) + resp = requests.get(url).json() + data = self._change_to_utf8(resp).get('scenarios', {}) + return {a.get('name'): self._get_scenario(a.get('installers', []) + ) for a in data} + + def _get_scenario(self, data): + installers = {a.get('installer'): self._get_installer(a.get('versions', + []) + ) for a in data} + scenario = { + 'status': self._get_status(), + 'installers': installers + } + return scenario + + def _get_status(self): + return 'success' + + def _get_installer(self, data): + return {a.get('version'): self._get_version(a) for a in data} + + def _get_version(self, data): + try: + scores = data.get('score', {}).get('projects')[0] + trusts = data.get('trust_indicator', {}).get('projects')[0] + except (TypeError, IndexError): + return [] + else: + scores = {key: [dict(date=a.get('date')[:10], + score=a.get('score') + ) for a in scores[key]] for key in scores} + trusts = {key: [dict(date=a.get('date')[:10], + status=a.get('status') + ) for a in trusts[key]] for key in trusts} + atom = self._get_atom(scores, trusts) + return [dict(project=k, + score=sorted(atom[k], reverse=True)[0].get('score'), + status=sorted(atom[k], reverse=True)[0].get('status') + ) for k in atom if atom[k]] + + def _get_atom(self, scores, trusts): + s = {k: {a['date']: a['score'] for a in scores[k]} for k in scores} + t = {k: {a['date']: a['status'] for a in trusts[k]} for k in trusts} + return {k: [dict(score=s[k][a], status=t[k][a], data=a + ) for a in s[k] if a in t[k]] for k in s} + + def _change_to_utf8(self, obj): + if isinstance(obj, dict): + return {str(k): self._change_to_utf8(v) for k, v in obj.items()} + elif isinstance(obj, list): + return [self._change_to_utf8(ele) for ele in obj] + else: + try: + new = eval(obj) + if isinstance(new, int): + return obj + return self._change_to_utf8(new) + except (NameError, TypeError, SyntaxError): + return str(obj) + + def _get_args(self, body): + status = self._get_status_args(body) + projects = self._get_projects_args(body) + installers = self._get_installers_args(body) + + args = { + 'status': status, + 'projects': projects, + 'installers': installers, + 'version': body.get('version', 'master').lower(), + 'loops': body.get('loops', 'daily').lower(), + 'time': body.get('times', '10 days')[:2].lower() + } + return args + + def _get_status_args(self, body): + status_all = ['success', 'warning', 'danger'] + status = [a.lower() for a in body.get('status', ['all'])] + return status_all if 'all' in status else status + + def _get_projects_args(self, body): + project_all = ['functest', 'yardstick'] + projects = [a.lower() for a in body.get('projects', ['all'])] + return project_all if 'all' in projects else projects + + def _get_installers_args(self, body): + installer_all = ['apex', 'compass', 'fuel', 'joid'] + installers = [a.lower() for a in body.get('installers', ['all'])] + return installer_all if 'all' in installers else installers diff --git a/utils/test/reporting/api/api/handlers/projects.py b/utils/test/reporting/api/api/handlers/projects.py new file mode 100644 index 000000000..02412cd62 --- /dev/null +++ b/utils/test/reporting/api/api/handlers/projects.py @@ -0,0 +1,27 @@ +############################################################################## +# Copyright (c) 2017 Huawei Technologies Co.,Ltd 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.apaiche.org/licenses/LICENSE-2.0 +############################################################################## +import requests + +from tornado.escape import json_encode + +from api.handlers import BaseHandler +from api import conf + + +class Projects(BaseHandler): + def get(self): + self._set_header() + + url = '{}/projects'.format(conf.base_url) + projects = requests.get(url).json().get('projects', {}) + + project_url = 'https://wiki.opnfv.org/display/{}' + data = {p['name']: project_url.format(p['name']) for p in projects} + + return self.write(json_encode(data)) diff --git a/utils/test/reporting/api/api/handlers/testcases.py b/utils/test/reporting/api/api/handlers/testcases.py new file mode 100644 index 000000000..110ac4c26 --- /dev/null +++ b/utils/test/reporting/api/api/handlers/testcases.py @@ -0,0 +1,33 @@ +############################################################################## +# Copyright (c) 2017 Huawei Technologies Co.,Ltd 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 +############################################################################## +import requests + +from tornado.escape import json_encode + +from api.handlers import BaseHandler +from api import conf + + +class TestCases(BaseHandler): + def get(self, project): + self._set_header() + + url = '{}/projects/{}/cases'.format(conf.base_url, project) + cases = requests.get(url).json().get('testcases', []) + data = [t['name'] for t in cases] + self.write(json_encode(data)) + + +class TestCase(BaseHandler): + def get(self, project, name): + self._set_header() + + url = '{}/projects/{}/cases/{}'.format(conf.base_url, project, name) + data = requests.get(url).json() + self.write(json_encode(data)) diff --git a/utils/test/reporting/api/api/server.py b/utils/test/reporting/api/api/server.py new file mode 100644 index 000000000..e340b0181 --- /dev/null +++ b/utils/test/reporting/api/api/server.py @@ -0,0 +1,27 @@ +############################################################################## +# Copyright (c) 2016 Huawei Technologies Co.,Ltd 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 +############################################################################## +import tornado.ioloop +import tornado.web +from tornado.options import define +from tornado.options import options + +from api.urls import mappings + +define("port", default=8000, help="run on the given port", type=int) + + +def main(): + tornado.options.parse_command_line() + application = tornado.web.Application(mappings) + application.listen(options.port) + tornado.ioloop.IOLoop.current().start() + + +if __name__ == "__main__": + main() diff --git a/utils/test/reporting/api/api/urls.py b/utils/test/reporting/api/api/urls.py new file mode 100644 index 000000000..a5228b2d4 --- /dev/null +++ b/utils/test/reporting/api/api/urls.py @@ -0,0 +1,20 @@ +############################################################################## +# Copyright (c) 2016 Huawei Technologies Co.,Ltd 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 +############################################################################## +from api.handlers import landing +from api.handlers import projects +from api.handlers import testcases + +mappings = [ + (r"/landing-page/filters", landing.FiltersHandler), + (r"/landing-page/scenarios", landing.ScenariosHandler), + + (r"/projects-page/projects", projects.Projects), + (r"/projects/([^/]+)/cases", testcases.TestCases), + (r"/projects/([^/]+)/cases/([^/]+)", testcases.TestCase) +] diff --git a/utils/test/reporting/api/handlers/__init__.py b/utils/test/reporting/api/handlers/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/utils/test/reporting/api/handlers/landing.py b/utils/test/reporting/api/handlers/landing.py deleted file mode 100644 index ae1fd2037..000000000 --- a/utils/test/reporting/api/handlers/landing.py +++ /dev/null @@ -1,177 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Huawei Technologies Co.,Ltd 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 -############################################################################## -import requests - -from tornado.web import RequestHandler -from tornado.escape import json_encode -from tornado.escape import json_decode - - -class BaseHandler(RequestHandler): - def _set_header(self): - self.set_header('Access-Control-Allow-Origin', '*') - self.set_header('Access-Control-Allow-Headers', - 'Content-Type, Content-Length, Authorization, \ - Accept, X-Requested-With , PRIVATE-TOKEN') - self.set_header('Access-Control-Allow-Methods', - 'PUT, POST, GET, DELETE, OPTIONS') - - -class FiltersHandler(BaseHandler): - def get(self): - self._set_header() - - filters = { - 'filters': { - 'status': ['success', 'warning', 'danger'], - 'projects': ['functest', 'yardstick'], - 'installers': ['apex', 'compass', 'fuel', 'joid'], - 'version': ['colorado', 'master'], - 'loops': ['daily', 'weekly', 'monthly'], - 'time': ['10 days', '30 days'] - } - } - return self.write(json_encode(filters)) - - -class ScenariosHandler(BaseHandler): - def post(self): - self._set_header() - - body = json_decode(self.request.body) - args = self._get_args(body) - - scenarios = self._get_result_data(self._get_scenarios(), args) - - return self.write(json_encode(dict(scenarios=scenarios))) - - def _get_result_data(self, data, args): - data = self._filter_status(data, args) - return {s: self._get_scenario_result(s, data[s], args) for s in data} - - def _filter_status(self, data, args): - return {k: v for k, v in data.items() if v['status'] in args['status']} - - def _get_scenario_result(self, scenario, data, args): - result = { - 'status': data.get('status'), - 'installers': self._get_installers_result(data['installers'], args) - } - return result - - def _get_installers_result(self, data, args): - func = self._get_installer_result - return {k: func(k, data.get(k, {}), args) for k in args['installers']} - - def _get_installer_result(self, installer, data, args): - projects = data.get(args['version'], []) - return [self._get_project_data(projects, p) for p in args['projects']] - - def _get_project_data(self, projects, project): - atom = { - 'project': project, - 'score': None, - 'status': None - } - for p in projects: - if p['project'] == project: - return p - return atom - - def _get_scenarios(self): - url = 'http://testresults.opnfv.org/test/api/v1/scenarios' - resp = requests.get(url).json() - data = self._change_to_utf8(resp).get('scenarios', {}) - return {a.get('name'): self._get_scenario(a.get('installers', []) - ) for a in data} - - def _get_scenario(self, data): - installers = {a.get('installer'): self._get_installer(a.get('versions', - []) - ) for a in data} - scenario = { - 'status': self._get_status(), - 'installers': installers - } - return scenario - - def _get_status(self): - return 'success' - - def _get_installer(self, data): - return {a.get('version'): self._get_version(a) for a in data} - - def _get_version(self, data): - try: - scores = data.get('score', {}).get('projects')[0] - trusts = data.get('trust_indicator', {}).get('projects')[0] - except (TypeError, IndexError): - return [] - else: - scores = {key: [dict(date=a.get('date')[:10], - score=a.get('score') - ) for a in scores[key]] for key in scores} - trusts = {key: [dict(date=a.get('date')[:10], - status=a.get('status') - ) for a in trusts[key]] for key in trusts} - atom = self._get_atom(scores, trusts) - return [dict(project=k, - score=sorted(atom[k], reverse=True)[0].get('score'), - status=sorted(atom[k], reverse=True)[0].get('status') - ) for k in atom if atom[k]] - - def _get_atom(self, scores, trusts): - s = {k: {a['date']: a['score'] for a in scores[k]} for k in scores} - t = {k: {a['date']: a['status'] for a in trusts[k]} for k in trusts} - return {k: [dict(score=s[k][a], status=t[k][a], data=a - ) for a in s[k] if a in t[k]] for k in s} - - def _change_to_utf8(self, obj): - if isinstance(obj, dict): - return {str(k): self._change_to_utf8(v) for k, v in obj.items()} - elif isinstance(obj, list): - return [self._change_to_utf8(ele) for ele in obj] - else: - try: - new = eval(obj) - if isinstance(new, int): - return obj - return self._change_to_utf8(new) - except (NameError, TypeError, SyntaxError): - return str(obj) - - def _get_args(self, body): - status = self._get_status_args(body) - projects = self._get_projects_args(body) - installers = self._get_installers_args(body) - - args = { - 'status': status, - 'projects': projects, - 'installers': installers, - 'version': body.get('version', 'master').lower(), - 'loops': body.get('loops', 'daily').lower(), - 'time': body.get('times', '10 days')[:2].lower() - } - return args - - def _get_status_args(self, body): - status_all = ['success', 'warning', 'danger'] - status = [a.lower() for a in body.get('status', ['all'])] - return status_all if 'all' in status else status - - def _get_projects_args(self, body): - project_all = ['functest', 'yardstick'] - projects = [a.lower() for a in body.get('projects', ['all'])] - return project_all if 'all' in projects else projects - - def _get_installers_args(self, body): - installer_all = ['apex', 'compass', 'fuel', 'joid'] - installers = [a.lower() for a in body.get('installers', ['all'])] - return installer_all if 'all' in installers else installers diff --git a/utils/test/reporting/api/install.sh b/utils/test/reporting/api/install.sh deleted file mode 100755 index 55d6b77ec..000000000 --- a/utils/test/reporting/api/install.sh +++ /dev/null @@ -1,3 +0,0 @@ -apt-get install -y python-pip -pip install tornado -pip install requests diff --git a/utils/test/reporting/api/requirements.txt b/utils/test/reporting/api/requirements.txt new file mode 100644 index 000000000..12ad6881b --- /dev/null +++ b/utils/test/reporting/api/requirements.txt @@ -0,0 +1,3 @@ +tornado==4.4.2 +requests==2.1.0 + diff --git a/utils/test/reporting/api/server.py b/utils/test/reporting/api/server.py deleted file mode 100644 index 0b00e9389..000000000 --- a/utils/test/reporting/api/server.py +++ /dev/null @@ -1,27 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Huawei Technologies Co.,Ltd 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 -############################################################################## -import tornado.ioloop -import tornado.web -from tornado.options import define -from tornado.options import options - -from urls import mappings - -define("port", default=8000, help="run on the given port", type=int) - - -def main(): - tornado.options.parse_command_line() - application = tornado.web.Application(mappings) - application.listen(options.port) - tornado.ioloop.IOLoop.current().start() - - -if __name__ == "__main__": - main() diff --git a/utils/test/reporting/api/setup.cfg b/utils/test/reporting/api/setup.cfg new file mode 100644 index 000000000..53d1092b9 --- /dev/null +++ b/utils/test/reporting/api/setup.cfg @@ -0,0 +1,32 @@ +[metadata] +name = reporting + +author = JackChan +author-email = chenjiankun1@huawei.com + +classifier = + Environment :: opnfv + Intended Audience :: Information Technology + Intended Audience :: System Administrators + License :: OSI Approved :: Apache Software License + Operating System :: POSIX :: Linux + Programming Language :: Python + Programming Language :: Python :: 2 + Programming Language :: Python :: 2.7 + +[global] +setup-hooks = + pbr.hooks.setup_hook + +[files] +packages = + api + +[entry_points] +console_scripts = + api = api.server:main + +[egg_info] +tag_build = +tag_date = 0 +tag_svn_revision = 0 diff --git a/utils/test/reporting/api/setup.py b/utils/test/reporting/api/setup.py new file mode 100644 index 000000000..d97481642 --- /dev/null +++ b/utils/test/reporting/api/setup.py @@ -0,0 +1,9 @@ +import setuptools + + +__author__ = 'JackChan' + + +setuptools.setup( + setup_requires=['pbr>=1.8'], + pbr=True) diff --git a/utils/test/reporting/api/urls.py b/utils/test/reporting/api/urls.py deleted file mode 100644 index fcfb2d795..000000000 --- a/utils/test/reporting/api/urls.py +++ /dev/null @@ -1,14 +0,0 @@ -############################################################################## -# Copyright (c) 2016 Huawei Technologies Co.,Ltd 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 -############################################################################## -from handlers import landing - -mappings = [ - (r"/landing-page/filters", landing.FiltersHandler), - (r"/landing-page/scenarios", landing.ScenariosHandler) -] -- cgit 1.2.3-korg