summaryrefslogtreecommitdiffstats
path: root/reporting/api/service
diff options
context:
space:
mode:
authorchenjiankun <chenjiankun1@huawei.com>2018-04-21 08:53:03 +0000
committerchenjiankun <chenjiankun1@huawei.com>2018-04-21 09:03:09 +0000
commit6ffbb81ec808aa615c7dad95fe6328ea5cc9c7b5 (patch)
tree0630754b3a6a8bf89c441392ef59d4e83db6c76a /reporting/api/service
parentc77cf76cbf31e65aa599f71f33d59abc267b4e50 (diff)
Add testing gating reporting page
Change-Id: I9f46d684a11b7999defffe983fc3224ef1a50412 Signed-off-by: chenjiankun <chenjiankun1@huawei.com>
Diffstat (limited to 'reporting/api/service')
-rw-r--r--reporting/api/service/__init__.py0
-rw-r--r--reporting/api/service/result.py90
-rw-r--r--reporting/api/service/scenario.py133
3 files changed, 223 insertions, 0 deletions
diff --git a/reporting/api/service/__init__.py b/reporting/api/service/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/reporting/api/service/__init__.py
diff --git a/reporting/api/service/result.py b/reporting/api/service/result.py
new file mode 100644
index 0000000..fa6553c
--- /dev/null
+++ b/reporting/api/service/result.py
@@ -0,0 +1,90 @@
+import json
+import logging
+from collections import defaultdict
+
+from tornado.gen import coroutine
+from tornado.gen import Return
+from tornado.httpclient import AsyncHTTPClient
+
+from api import conf as consts
+from api.extension.client import NoQueueTimeoutHTTPClient
+
+LOG = logging.getLogger(__name__)
+AsyncHTTPClient.configure(NoQueueTimeoutHTTPClient)
+
+
+class Result(object):
+
+ def __init__(self):
+ self._url = '{}/results?period={}&version={}&page={}'
+ self._client = AsyncHTTPClient()
+ self._result = defaultdict(list)
+
+ @property
+ @coroutine
+ def result(self):
+ if not self._result:
+ yield self.update_results()
+ raise Return(self._result)
+
+ @coroutine
+ def update_results(self):
+ LOG.info('start update results')
+
+ for version in consts.versions:
+ yield self._update_version_result(version)
+
+ LOG.info('results update finished')
+
+ @coroutine
+ def _update_version_result(self, version):
+ total_page = yield self._get_total_page(version)
+
+ responses = yield self._fetch_results(version, total_page)
+
+ self._update_version_dict(version, responses)
+
+ @coroutine
+ def _fetch_results(self, version, total_page):
+ urls = [self._url.format(consts.base_url, consts.period, version, i)
+ for i in range(1, total_page + 1)]
+ responses = yield [self._client.fetch(url) for url in urls]
+ raise Return(responses)
+
+ @coroutine
+ def _get_total_page(self, version):
+ url = self._url.format(consts.base_url, consts.period, version, 1)
+ response = yield self._client.fetch(url)
+ raise Return(json.loads(response.body)['pagination']['total_pages'])
+
+ def _update_version_dict(self, version, responses):
+ for response in responses:
+ results = json.loads(response.body)['results']
+ for result in results:
+ data = {k: v for k, v in result.items() if k != 'details'}
+ self._result[version].append(data)
+
+
+class ResultCache(Result):
+
+ @classmethod
+ @coroutine
+ def update(cls):
+ cls._check()
+
+ yield cls.cache.update_results()
+
+ @classmethod
+ @coroutine
+ def get(cls, version):
+ cls._check()
+
+ result = yield cls.cache.result
+ raise Return(result[version])
+
+ @classmethod
+ def _check(cls):
+ try:
+ cls.cache
+ except AttributeError:
+ cls.cache = cls()
diff --git a/reporting/api/service/scenario.py b/reporting/api/service/scenario.py
new file mode 100644
index 0000000..f9e2a91
--- /dev/null
+++ b/reporting/api/service/scenario.py
@@ -0,0 +1,133 @@
+import abc
+from collections import defaultdict
+
+import six
+from tornado.gen import coroutine
+from tornado.gen import Return
+
+from api.service.result import ResultCache
+
+PROJECTS = ['fastdatastacks', 'barometer', 'sfc', 'sdnvpn', 'doctor', 'parser']
+
+
+def _set(key, llist):
+ return set(x[key] for x in llist)
+
+
+def _filter(key, value, llist):
+ return filter(lambda x: x[key] == value, llist)
+
+
+class ScenarioTableResult(object):
+
+ def __init__(self, scenario, version, installer, iteration):
+ self.scenario = scenario
+ self.version = version
+ self.installer = installer
+ self.iteration = iteration
+
+ @coroutine
+ def get(self):
+ results = yield ResultCache.get(self.version)
+ results = self._filter_result(results)
+ results = self._struct_result(results)
+
+ raise Return(results)
+
+ def _filter_result(self, results):
+ results = [x for x in results if x['build_tag']]
+ if self.installer:
+ results = _filter('installer', self.installer, results)
+ if self.scenario:
+ results = _filter('scenario', self.scenario, results)
+ return results
+
+ def _struct_result(self, results):
+
+ return {
+ s: self._struct_scenario(_filter('scenario', s, results))
+ for s in _set('scenario', results)
+ }
+
+ def _struct_scenario(self, data):
+ return sorted([
+ HandlerFacade.get_result(b, _filter('build_tag', b, data))
+ for b in _set('build_tag', data)
+ ], key=lambda x: x['date'], reverse=True)[:self.iteration]
+
+
+class HandlerFacade(object):
+
+ @classmethod
+ def get_result(cls, index, data):
+ if not data:
+ return {}
+
+ cls._change_name_to_functest(data)
+ data = cls._sort_by_start_date(data)
+
+ return {
+ 'id': index,
+ 'date': data[0]['start_date'],
+ 'version': data[0]['version'],
+ 'installer': data[0]['installer'],
+ 'projects': cls._get_projects_data(data)
+ }
+
+ @classmethod
+ def _sort_by_start_date(cls, data):
+ return sorted(data, key=lambda x: x['start_date'])
+
+ @classmethod
+ def _get_projects_data(cls, data):
+
+ return {
+ p: HANDLER_MAP[p](_filter('project_name', p, data)).struct()
+ for p in _set('project_name', data)
+ }
+
+ @classmethod
+ def _change_name_to_functest(cls, data):
+ for ele in data:
+ if ele['project_name'] in PROJECTS:
+ ele['project_name'] = 'functest'
+
+
+@six.add_metaclass(abc.ABCMeta)
+class ProjectHandler(object):
+
+ def __init__(self, data):
+ self.data = data
+
+ def struct(self):
+ return self._struct_project_data()
+
+ def _struct_project_data(self):
+ return {
+ 'gating': self._gating()
+ }
+
+ @abc.abstractmethod
+ def _gating(self):
+ pass
+
+
+class DefaultHandler(ProjectHandler):
+
+ def _struct_project_data(self):
+ return {}
+
+ def _gating(self):
+ pass
+
+
+class FunctestHandler(ProjectHandler):
+
+ def _gating(self):
+ if all([x['criteria'] == 'PASS' for x in self.data]):
+ return 'PASS'
+ else:
+ return 'FAIL'
+
+
+HANDLER_MAP = defaultdict(lambda: DefaultHandler, functest=FunctestHandler)