diff options
Diffstat (limited to 'utils/test/testapi/opnfv_testapi')
76 files changed, 0 insertions, 8428 deletions
diff --git a/utils/test/testapi/opnfv_testapi/__init__.py b/utils/test/testapi/opnfv_testapi/__init__.py deleted file mode 100644 index 363bc388e..000000000 --- a/utils/test/testapi/opnfv_testapi/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -############################################################################## -# Copyright (c) 2016 ZTE Corporation -# feng.xiaowei@zte.com.cn -# 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 -############################################################################## diff --git a/utils/test/testapi/opnfv_testapi/cmd/__init__.py b/utils/test/testapi/opnfv_testapi/cmd/__init__.py deleted file mode 100644 index 363bc388e..000000000 --- a/utils/test/testapi/opnfv_testapi/cmd/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -############################################################################## -# Copyright (c) 2016 ZTE Corporation -# feng.xiaowei@zte.com.cn -# 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 -############################################################################## diff --git a/utils/test/testapi/opnfv_testapi/cmd/server.py b/utils/test/testapi/opnfv_testapi/cmd/server.py deleted file mode 100644 index 011a6cd6e..000000000 --- a/utils/test/testapi/opnfv_testapi/cmd/server.py +++ /dev/null @@ -1,57 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Orange -# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.com -# 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 -############################################################################## - -""" -Pre-requisites: - pip install motor - pip install tornado - -We can launch the API with this file - -TODOs : - - logging - - json args validation with schemes - - POST/PUT/DELETE for PODs - - POST/PUT/GET/DELETE for installers, platforms (enrich results info) - - count cases for GET on projects - - count results for GET on cases - - include objects - - swagger documentation - - setup file - - results pagination - - unit tests - -""" - -import tornado.ioloop - -from opnfv_testapi.common.config import CONF -from opnfv_testapi.router import url_mappings -from opnfv_testapi.tornado_swagger import swagger - - -def make_app(): - swagger.docs(base_url=CONF.ui_url, - static_path=CONF.ui_static_path) - return swagger.Application( - url_mappings.mappings, - debug=CONF.api_debug, - auth=CONF.api_token_check, - cookie_secret='opnfv-testapi', - ) - - -def main(): - application = make_app() - application.listen(CONF.api_port) - tornado.ioloop.IOLoop.current().start() - - -if __name__ == "__main__": - main() diff --git a/utils/test/testapi/opnfv_testapi/common/__init__.py b/utils/test/testapi/opnfv_testapi/common/__init__.py deleted file mode 100644 index 05c0c9392..000000000 --- a/utils/test/testapi/opnfv_testapi/common/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Orange -# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.com -# 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 -############################################################################## diff --git a/utils/test/testapi/opnfv_testapi/common/check.py b/utils/test/testapi/opnfv_testapi/common/check.py deleted file mode 100644 index 667578fed..000000000 --- a/utils/test/testapi/opnfv_testapi/common/check.py +++ /dev/null @@ -1,148 +0,0 @@ -############################################################################## -# Copyright (c) 2017 ZTE Corp -# feng.xiaowei@zte.com.cn -# 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 functools -import re - -from tornado import gen - -from opnfv_testapi.common import constants -from opnfv_testapi.common import message -from opnfv_testapi.common import raises -from opnfv_testapi.common.config import CONF -from opnfv_testapi.db import api as dbapi - - -def is_authorized(method): - @functools.wraps(method) - def wrapper(self, *args, **kwargs): - if CONF.api_authenticate and self.table in ['pods']: - testapi_id = self.get_secure_cookie(constants.TESTAPI_ID) - if not testapi_id: - raises.Unauthorized(message.not_login()) - user_info = yield dbapi.db_find_one('users', {'user': testapi_id}) - if not user_info: - raises.Unauthorized(message.not_lfid()) - kwargs['owner'] = testapi_id - ret = yield gen.coroutine(method)(self, *args, **kwargs) - raise gen.Return(ret) - return wrapper - - -def valid_token(method): - @functools.wraps(method) - def wrapper(self, *args, **kwargs): - if self.auth and self.table == 'results': - try: - token = self.request.headers['X-Auth-Token'] - except KeyError: - raises.Unauthorized(message.unauthorized()) - query = {'access_token': token} - check = yield dbapi.db_find_one('tokens', query) - if not check: - raises.Forbidden(message.invalid_token()) - ret = yield gen.coroutine(method)(self, *args, **kwargs) - raise gen.Return(ret) - return wrapper - - -def not_exist(xstep): - @functools.wraps(xstep) - def wrap(self, *args, **kwargs): - query = kwargs.get('query') - data = yield dbapi.db_find_one(self.table, query) - if not data: - raises.NotFound(message.not_found(self.table, query)) - ret = yield gen.coroutine(xstep)(self, data, *args, **kwargs) - raise gen.Return(ret) - - return wrap - - -def no_body(xstep): - @functools.wraps(xstep) - def wrap(self, *args, **kwargs): - if self.json_args is None: - raises.BadRequest(message.no_body()) - ret = yield gen.coroutine(xstep)(self, *args, **kwargs) - raise gen.Return(ret) - - return wrap - - -def miss_fields(xstep): - @functools.wraps(xstep) - def wrap(self, *args, **kwargs): - fields = kwargs.pop('miss_fields', []) - if fields: - for miss in fields: - miss_data = self.json_args.get(miss) - if miss_data is None or miss_data == '': - raises.BadRequest(message.missing(miss)) - ret = yield gen.coroutine(xstep)(self, *args, **kwargs) - raise gen.Return(ret) - return wrap - - -def carriers_exist(xstep): - @functools.wraps(xstep) - def wrap(self, *args, **kwargs): - carriers = kwargs.pop('carriers', {}) - if carriers: - for table, query in carriers: - exist = yield dbapi.db_find_one(table, query()) - if not exist: - raises.Forbidden(message.not_found(table, query())) - ret = yield gen.coroutine(xstep)(self, *args, **kwargs) - raise gen.Return(ret) - return wrap - - -def values_check(xstep): - @functools.wraps(xstep) - def wrap(self, *args, **kwargs): - checks = kwargs.pop('values_check', {}) - if checks: - for field, check, options in checks: - if not check(field, options): - raises.BadRequest(message.invalid_value(field, options)) - ret = yield gen.coroutine(xstep)(self, *args, **kwargs) - raise gen.Return(ret) - return wrap - - -def new_not_exists(xstep): - @functools.wraps(xstep) - def wrap(self, *args, **kwargs): - query = kwargs.get('query') - if query: - query_data = query() - if self.table == 'pods': - if query_data.get('name') is not None: - query_data['name'] = re.compile(query_data.get('name'), - re.IGNORECASE) - to_data = yield dbapi.db_find_one(self.table, query_data) - if to_data: - raises.Forbidden(message.exist(self.table, query())) - ret = yield gen.coroutine(xstep)(self, *args, **kwargs) - raise gen.Return(ret) - return wrap - - -def updated_one_not_exist(xstep): - @functools.wraps(xstep) - def wrap(self, data, *args, **kwargs): - db_keys = kwargs.pop('db_keys', []) - query = self._update_query(db_keys, data) - if query: - to_data = yield dbapi.db_find_one(self.table, query) - if to_data: - raises.Forbidden(message.exist(self.table, query)) - ret = yield gen.coroutine(xstep)(self, data, *args, **kwargs) - raise gen.Return(ret) - return wrap diff --git a/utils/test/testapi/opnfv_testapi/common/config.py b/utils/test/testapi/opnfv_testapi/common/config.py deleted file mode 100644 index f888b07be..000000000 --- a/utils/test/testapi/opnfv_testapi/common/config.py +++ /dev/null @@ -1,63 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Orange -# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.com -# 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 -# feng.xiaowei@zte.com.cn remove prepare_put_request 5-30-2016 -############################################################################## -import ConfigParser -import argparse -import os -import sys - - -class Config(object): - - def __init__(self): - self.config_file = '/etc/opnfv_testapi/config.ini' - self._set_config_file() - self._parse() - self._parse_per_page() - - def _parse(self): - if not os.path.exists(self.config_file): - raise Exception("%s not found" % self.config_file) - - config = ConfigParser.RawConfigParser() - config.read(self.config_file) - self._parse_section(config) - - def _parse_section(self, config): - [self._parse_item(config, section) for section in (config.sections())] - - def _parse_item(self, config, section): - [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: - value = int(value) - except Exception: - if str(value).lower() == 'true': - value = True - elif str(value).lower() == 'false': - value = False - return value - - def _set_config_file(self): - parser = argparse.ArgumentParser() - parser.add_argument("-c", "--config-file", dest='config_file', - help="Config file location", metavar="FILE") - args, _ = parser.parse_known_args(sys.argv) - if hasattr(args, 'config_file') and args.config_file: - self.config_file = args.config_file - - -CONF = Config() diff --git a/utils/test/testapi/opnfv_testapi/common/constants.py b/utils/test/testapi/opnfv_testapi/common/constants.py deleted file mode 100644 index 70c922383..000000000 --- a/utils/test/testapi/opnfv_testapi/common/constants.py +++ /dev/null @@ -1,4 +0,0 @@ -TESTAPI_ID = 'testapi_id' -CSRF_TOKEN = 'csrf_token' -ROLE = 'role' -TESTAPI_USERS = ['opnfv-testapi-users'] diff --git a/utils/test/testapi/opnfv_testapi/common/message.py b/utils/test/testapi/opnfv_testapi/common/message.py deleted file mode 100644 index 3e14f7258..000000000 --- a/utils/test/testapi/opnfv_testapi/common/message.py +++ /dev/null @@ -1,62 +0,0 @@ -############################################################################## -# Copyright (c) 2017 ZTE Corp -# feng.xiaowei@zte.com.cn -# 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 -############################################################################## -not_found_base = 'Could Not Found' -exist_base = 'Already Exists' - - -def key_error(key): - return "KeyError: '{}'".format(key) - - -def no_body(): - return 'No Body' - - -def not_found(key, value): - return '{} {} [{}]'.format(not_found_base, key, value) - - -def missing(name): - return '{} Missing'.format(name) - - -def invalid_value(name, options): - return '{} must be in {}'.format(name, options) - - -def exist(key, value): - return '{} [{}] {}'.format(key, value, exist_base) - - -def bad_format(error): - return 'Bad Format [{}]'.format(error) - - -def unauthorized(): - return 'No Authentication Header' - - -def invalid_token(): - return 'Invalid Token' - - -def not_login(): - return 'TestAPI id is not provided' - - -def not_lfid(): - return 'Not a valid Linux Foundation Account' - - -def no_update(): - return 'Nothing to update' - - -def must_int(name): - return '{} must be int'.format(name) diff --git a/utils/test/testapi/opnfv_testapi/common/raises.py b/utils/test/testapi/opnfv_testapi/common/raises.py deleted file mode 100644 index 55c58c9e2..000000000 --- a/utils/test/testapi/opnfv_testapi/common/raises.py +++ /dev/null @@ -1,43 +0,0 @@ -############################################################################## -# Copyright (c) 2017 ZTE Corp -# feng.xiaowei@zte.com.cn -# 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 httplib - -from tornado import web - - -class Raiser(object): - code = httplib.OK - - def __init__(self, reason): - raise web.HTTPError(self.code, reason) - - -class BadRequest(Raiser): - code = httplib.BAD_REQUEST - - -class Forbidden(Raiser): - code = httplib.FORBIDDEN - - -class Conflict(Raiser): - code = httplib.CONFLICT - - -class NotFound(Raiser): - code = httplib.NOT_FOUND - - -class Unauthorized(Raiser): - code = httplib.UNAUTHORIZED - - -class CodeTBD(object): - def __init__(self, code, reason): - raise web.HTTPError(code, reason) diff --git a/utils/test/testapi/opnfv_testapi/db/__init__.py b/utils/test/testapi/opnfv_testapi/db/__init__.py deleted file mode 100644 index e69de29bb..000000000 --- a/utils/test/testapi/opnfv_testapi/db/__init__.py +++ /dev/null diff --git a/utils/test/testapi/opnfv_testapi/db/api.py b/utils/test/testapi/opnfv_testapi/db/api.py deleted file mode 100644 index c057480d4..000000000 --- a/utils/test/testapi/opnfv_testapi/db/api.py +++ /dev/null @@ -1,38 +0,0 @@ -import motor - -from opnfv_testapi.common.config import CONF - -DB = motor.MotorClient(CONF.mongo_url)[CONF.mongo_dbname] - - -def db_update(collection, query, update_req): - return _eval_db(collection, 'update', query, update_req, check_keys=False) - - -def db_delete(collection, query): - return _eval_db(collection, 'remove', query) - - -def db_aggregate(collection, pipelines): - return _eval_db(collection, 'aggregate', pipelines, allowDiskUse=True) - - -def db_list(collection, query): - return _eval_db(collection, 'find', query) - - -def db_save(collection, data): - return _eval_db(collection, 'insert', data, check_keys=False) - - -def db_find_one(collection, query): - return _eval_db(collection, 'find_one', query) - - -def _eval_db(collection, method, *args, **kwargs): - exec_collection = DB.__getattr__(collection) - return exec_collection.__getattribute__(method)(*args, **kwargs) - - -def _eval_db_find_one(query, table=None): - return _eval_db(table, 'find_one', query) diff --git a/utils/test/testapi/opnfv_testapi/handlers/__init__.py b/utils/test/testapi/opnfv_testapi/handlers/__init__.py deleted file mode 100644 index e69de29bb..000000000 --- a/utils/test/testapi/opnfv_testapi/handlers/__init__.py +++ /dev/null diff --git a/utils/test/testapi/opnfv_testapi/handlers/base_handlers.py b/utils/test/testapi/opnfv_testapi/handlers/base_handlers.py deleted file mode 100644 index a8ee3db2b..000000000 --- a/utils/test/testapi/opnfv_testapi/handlers/base_handlers.py +++ /dev/null @@ -1,257 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Orange -# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.com -# 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 -# feng.xiaowei@zte.com.cn refactor db.pod to db.pods 5-19-2016 -# feng.xiaowei@zte.com.cn refactor test_project to project 5-19-2016 -# feng.xiaowei@zte.com.cn refactor response body 5-19-2016 -# feng.xiaowei@zte.com.cn refactor pod/project response info 5-19-2016 -# feng.xiaowei@zte.com.cn refactor testcase related handler 5-20-2016 -# feng.xiaowei@zte.com.cn refactor result related handler 5-23-2016 -# feng.xiaowei@zte.com.cn refactor dashboard related handler 5-24-2016 -# feng.xiaowei@zte.com.cn add methods to GenericApiHandler 5-26-2016 -# feng.xiaowei@zte.com.cn remove PodHandler 5-26-2016 -# feng.xiaowei@zte.com.cn remove ProjectHandler 5-26-2016 -# feng.xiaowei@zte.com.cn remove TestcaseHandler 5-27-2016 -# feng.xiaowei@zte.com.cn remove ResultHandler 5-29-2016 -# feng.xiaowei@zte.com.cn remove DashboardHandler 5-30-2016 -############################################################################## - -from datetime import datetime -import json - -from tornado import gen -from tornado import web - -from opnfv_testapi.common import check -from opnfv_testapi.common import message -from opnfv_testapi.common import raises -from opnfv_testapi.db import api as dbapi -from opnfv_testapi.models import base_models -from opnfv_testapi.tornado_swagger import swagger - -DEFAULT_REPRESENTATION = "application/json" - - -class GenericApiHandler(web.RequestHandler): - def __init__(self, application, request, **kwargs): - super(GenericApiHandler, self).__init__(application, request, **kwargs) - self.json_args = None - self.table = None - self.table_cls = None - self.db_projects = 'projects' - self.db_pods = 'pods' - self.db_testcases = 'testcases' - self.db_results = 'results' - self.db_scenarios = 'scenarios' - self.auth = self.settings["auth"] - - def prepare(self): - if self.request.body: - if self.request.headers.get("Content-Type") is not None: - if self.request.headers["Content-Type"].startswith( - DEFAULT_REPRESENTATION): - try: - self.json_args = json.loads(self.request.body) - except (ValueError, KeyError, TypeError) as error: - raises.BadRequest(message.bad_format(str(error))) - - def finish_request(self, json_object=None): - if json_object: - self.write(json.dumps(json_object)) - self.set_header("Content-Type", DEFAULT_REPRESENTATION) - self.finish() - - def _create_response(self, resource): - href = self.request.full_url() + '/' + str(resource) - return base_models.CreateResponse(href=href).format() - - def format_data(self, data): - cls_data = self.table_cls.from_dict(data) - return cls_data.format_http() - - @web.asynchronous - @gen.coroutine - @check.is_authorized - @check.valid_token - @check.no_body - @check.miss_fields - @check.values_check - @check.carriers_exist - @check.new_not_exists - def _create(self, **kwargs): - """ - :param miss_checks: [miss1, miss2] - :param db_checks: [(table, exist, query, error)] - """ - data = self.table_cls.from_dict(self.json_args) - for k, v in kwargs.iteritems(): - if k != 'query': - data.__setattr__(k, v) - - if self.table != 'results': - data.creation_date = datetime.now() - _id = yield dbapi.db_save(self.table, data.format()) - if 'name' in self.json_args: - resource = data.name - else: - resource = _id - self.finish_request(self._create_response(resource)) - - @web.asynchronous - @gen.coroutine - def _list(self, query=None, res_op=None, *args, **kwargs): - sort = kwargs.get('sort') - page = kwargs.get('page', 0) - last = kwargs.get('last', 0) - per_page = kwargs.get('per_page', 0) - if query is None: - query = {} - pipelines = list() - pipelines.append({'$match': query}) - - total_pages = 0 - data = list() - cursor = dbapi.db_list(self.table, query) - records_count = yield cursor.count() - if records_count > 0: - if page > 0: - total_pages, return_nr = self._calc_total_pages(records_count, - last, - page, - per_page) - pipelines = self._set_pipelines(pipelines, - sort, - return_nr, - page, - per_page) - cursor = dbapi.db_aggregate(self.table, pipelines) - 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 > 0: - res.update({ - 'pagination': { - 'current_page': kwargs.get('page'), - 'total_pages': total_pages - } - }) - self.finish_request(res) - - @staticmethod - def _calc_total_pages(records_count, last, page, per_page): - records_nr = records_count - if (records_count > last) and (last > 0): - records_nr = last - - total_pages, remainder = divmod(records_nr, per_page) - if remainder > 0: - total_pages += 1 - if page > 1 and page > total_pages: - raises.BadRequest( - 'Request page > total_pages [{}]'.format(total_pages)) - return total_pages, records_nr - - @staticmethod - def _set_pipelines(pipelines, sort, return_nr, page, per_page): - if sort: - pipelines.append({'$sort': sort}) - - over = (page - 1) * per_page - left = return_nr - over - pipelines.append({'$skip': over}) - pipelines.append({'$limit': per_page if per_page < left else left}) - - return pipelines - - @web.asynchronous - @gen.coroutine - @check.not_exist - def _get_one(self, data, query=None): - self.finish_request(self.format_data(data)) - - @web.asynchronous - @gen.coroutine - @check.not_exist - def _delete(self, data, query=None): - yield dbapi.db_delete(self.table, query) - self.finish_request() - - @web.asynchronous - @gen.coroutine - @check.no_body - @check.not_exist - @check.updated_one_not_exist - def _update(self, data, query=None, **kwargs): - data = self.table_cls.from_dict(data) - update_req = self._update_requests(data) - yield dbapi.db_update(self.table, query, update_req) - update_req['_id'] = str(data._id) - self.finish_request(update_req) - - @web.asynchronous - @gen.coroutine - @check.no_body - @check.not_exist - @check.updated_one_not_exist - def pure_update(self, data, query=None, **kwargs): - data = self.table_cls.from_dict(data) - update_req = self._update_requests(data) - yield dbapi.db_update(self.table, query, update_req) - self.finish_request() - - def _update_requests(self, data): - request = dict() - for k, v in self.json_args.iteritems(): - request = self._update_request(request, k, v, - data.__getattribute__(k)) - if not request: - raises.Forbidden(message.no_update()) - - edit_request = data.format() - edit_request.update(request) - return edit_request - - @staticmethod - def _update_request(edit_request, key, new_value, old_value): - """ - This function serves to prepare the elements in the update request. - We try to avoid replace the exact values in the db - edit_request should be a dict in which we add an entry (key) after - comparing values - """ - if not (new_value is None): - if new_value != old_value: - edit_request[key] = new_value - - return edit_request - - def _update_query(self, keys, data): - query = dict() - equal = True - for key in keys: - new = self.json_args.get(key) - old = data.get(key) - if new is None: - new = old - elif new != old: - equal = False - query[key] = new - return query if not equal else dict() - - -class VersionHandler(GenericApiHandler): - @swagger.operation(nickname='listAllVersions') - def get(self): - """ - @description: list all supported versions - @rtype: L{Versions} - """ - versions = [{'version': 'v1.0', 'description': 'basics'}] - self.finish_request({'versions': versions}) diff --git a/utils/test/testapi/opnfv_testapi/handlers/pod_handlers.py b/utils/test/testapi/opnfv_testapi/handlers/pod_handlers.py deleted file mode 100644 index abf5bf9f1..000000000 --- a/utils/test/testapi/opnfv_testapi/handlers/pod_handlers.py +++ /dev/null @@ -1,78 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Orange -# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.com -# 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 opnfv_testapi.handlers import base_handlers -from opnfv_testapi.models import pod_models -from opnfv_testapi.tornado_swagger import swagger - - -class GenericPodHandler(base_handlers.GenericApiHandler): - def __init__(self, application, request, **kwargs): - super(GenericPodHandler, self).__init__(application, request, **kwargs) - self.table = 'pods' - self.table_cls = pod_models.Pod - - -class PodCLHandler(GenericPodHandler): - @swagger.operation(nickname='listAllPods') - def get(self): - """ - @description: list all pods - @return 200: list all pods, empty list is no pod exist - @rtype: L{Pods} - """ - self._list() - - @swagger.operation(nickname='createPod') - def post(self): - """ - @description: create a pod - @param body: pod to be created - @type body: L{PodCreateRequest} - @in body: body - @rtype: L{CreateResponse} - @return 200: pod is created. - @raise 403: pod already exists - @raise 400: body or name not provided - """ - def query(): - return {'name': self.json_args.get('name')} - miss_fields = ['name'] - self._create(miss_fields=miss_fields, query=query) - - -class PodGURHandler(GenericPodHandler): - @swagger.operation(nickname='getPodByName') - def get(self, pod_name): - """ - @description: get a single pod by pod_name - @rtype: L{Pod} - @return 200: pod exist - @raise 404: pod not exist - """ - self._get_one(query={'name': pod_name}) - - def delete(self, pod_name): - """ Remove a POD - - # check for an existing pod to be deleted - mongo_dict = yield self.db.pods.find_one( - {'name': pod_name}) - pod = TestProject.pod(mongo_dict) - if pod is None: - raise HTTPError(HTTP_NOT_FOUND, - "{} could not be found as a pod to be deleted" - .format(pod_name)) - - # just delete it, or maybe save it elsewhere in a future - res = yield self.db.projects.remove( - {'name': pod_name}) - - self.finish_request(answer) - """ - pass diff --git a/utils/test/testapi/opnfv_testapi/handlers/project_handlers.py b/utils/test/testapi/opnfv_testapi/handlers/project_handlers.py deleted file mode 100644 index 30d9ab34a..000000000 --- a/utils/test/testapi/opnfv_testapi/handlers/project_handlers.py +++ /dev/null @@ -1,86 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Orange -# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.com -# 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 opnfv_testapi.handlers import base_handlers -from opnfv_testapi.models import project_models -from opnfv_testapi.tornado_swagger import swagger - - -class GenericProjectHandler(base_handlers.GenericApiHandler): - def __init__(self, application, request, **kwargs): - super(GenericProjectHandler, self).__init__(application, - request, - **kwargs) - self.table = 'projects' - self.table_cls = project_models.Project - - -class ProjectCLHandler(GenericProjectHandler): - @swagger.operation(nickname="listAllProjects") - def get(self): - """ - @description: list all projects - @return 200: return all projects, empty list is no project exist - @rtype: L{Projects} - """ - self._list() - - @swagger.operation(nickname="createProject") - def post(self): - """ - @description: create a project - @param body: project to be created - @type body: L{ProjectCreateRequest} - @in body: body - @rtype: L{CreateResponse} - @return 200: project is created. - @raise 403: project already exists - @raise 400: body or name not provided - """ - def query(): - return {'name': self.json_args.get('name')} - miss_fields = ['name'] - self._create(miss_fields=miss_fields, query=query) - - -class ProjectGURHandler(GenericProjectHandler): - @swagger.operation(nickname='getProjectByName') - def get(self, project_name): - """ - @description: get a single project by project_name - @rtype: L{Project} - @return 200: project exist - @raise 404: project not exist - """ - self._get_one(query={'name': project_name}) - - @swagger.operation(nickname="updateProjectByName") - def put(self, project_name): - """ - @description: update a single project by project_name - @param body: project to be updated - @type body: L{ProjectUpdateRequest} - @in body: body - @rtype: L{Project} - @return 200: update success - @raise 404: project not exist - @raise 403: new project name already exist or nothing to update - """ - query = {'name': project_name} - db_keys = ['name'] - self._update(query=query, db_keys=db_keys) - - @swagger.operation(nickname='deleteProjectByName') - def delete(self, project_name): - """ - @description: delete a project by project_name - @return 200: delete success - @raise 404: project not exist - """ - self._delete(query={'name': project_name}) diff --git a/utils/test/testapi/opnfv_testapi/handlers/result_handlers.py b/utils/test/testapi/opnfv_testapi/handlers/result_handlers.py deleted file mode 100644 index c4b61ff22..000000000 --- a/utils/test/testapi/opnfv_testapi/handlers/result_handlers.py +++ /dev/null @@ -1,288 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Orange -# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.com -# 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 datetime import datetime -from datetime import timedelta -import json -import logging - -from bson import objectid - -from opnfv_testapi.common import constants -from opnfv_testapi.common import message -from opnfv_testapi.common import raises -from opnfv_testapi.common.config import CONF -from opnfv_testapi.handlers import base_handlers -from opnfv_testapi.models import result_models -from opnfv_testapi.tornado_swagger import swagger - - -class GenericResultHandler(base_handlers.GenericApiHandler): - def __init__(self, application, request, **kwargs): - super(GenericResultHandler, self).__init__(application, - request, - **kwargs) - self.table = self.db_results - self.table_cls = result_models.TestResult - - def get_int(self, key, value): - try: - value = int(value) - except Exception: - raises.BadRequest(message.must_int(key)) - return value - - def set_query(self): - query = dict() - date_range = dict() - - query['public'] = {'$not': {'$eq': 'false'}} - for k in self.request.query_arguments.keys(): - v = self.get_query_argument(k) - if k == 'project' or k == 'pod' or k == 'case': - query[k + '_name'] = v - elif k == 'period': - v = self.get_int(k, v) - if v > 0: - period = datetime.now() - timedelta(days=v) - obj = {"$gte": str(period)} - query['start_date'] = obj - elif k == 'trust_indicator': - query[k + '.current'] = float(v) - elif k == 'from': - date_range.update({'$gte': str(v)}) - elif k == 'to': - date_range.update({'$lt': str(v)}) - elif k == 'signed': - username = self.get_secure_cookie(constants.TESTAPI_ID) - role = self.get_secure_cookie(constants.ROLE) - if role: - del query['public'] - if role != "reviewer": - query['user'] = username - elif k not in ['last', 'page', 'descend']: - query[k] = v - if date_range: - query['start_date'] = date_range - - # if $lt is not provided, - # empty/None/null/'' start_date will also be returned - if 'start_date' in query and '$lt' not in query['start_date']: - query['start_date'].update({'$lt': str(datetime.now())}) - - return query - - -class ResultsCLHandler(GenericResultHandler): - @swagger.operation(nickname="queryTestResults") - def get(self): - """ - @description: Retrieve result(s) for a test project - on a specific pod. - @notes: Retrieve result(s) for a test project on a specific pod. - Available filters for this request are : - - project : project name - - case : case name - - pod : pod name - - version : platform version (Arno-R1, ...) - - installer : fuel/apex/compass/joid/daisy - - build_tag : Jenkins build tag name - - 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 - to avoid running systematically long and stable test case - - signed : get logined user result - - GET /results/project=functest&case=vPing&version=Arno-R1 \ - &pod=pod_name&period=15&signed - @return 200: all test results consist with query, - empty list if no result is found - @rtype: L{TestResults} - @param pod: pod name - @type pod: L{string} - @in pod: query - @required pod: False - @param project: project name - @type project: L{string} - @in project: query - @required project: False - @param case: case name - @type case: L{string} - @in case: query - @required case: False - @param version: i.e. Colorado - @type version: L{string} - @in version: query - @required version: False - @param installer: fuel/apex/joid/compass - @type installer: L{string} - @in installer: query - @required installer: False - @param build_tag: i.e. v3.0 - @type build_tag: L{string} - @in build_tag: query - @required build_tag: False - @param scenario: i.e. odl - @type scenario: L{string} - @in scenario: query - @required scenario: False - @param criteria: i.e. passed - @type criteria: L{string} - @in criteria: query - @required criteria: False - @param period: last days - @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, default to 1 - @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 - @param signed: user results or all results - @type signed: L{string} - @in signed: query - @required signed: False - @param descend: true, newest2oldest; false, oldest2newest - @type descend: L{string} - @in descend: query - @required descend: False - """ - def descend_limit(): - descend = self.get_query_argument('descend', 'true') - return -1 if descend.lower() == 'true' else 1 - - def last_limit(): - return self.get_int('last', self.get_query_argument('last', 0)) - - def page_limit(): - return self.get_int('page', self.get_query_argument('page', 1)) - - limitations = { - 'sort': {'_id': descend_limit()}, - 'last': last_limit(), - 'page': page_limit(), - 'per_page': CONF.api_results_per_page - } - - self._list(query=self.set_query(), **limitations) - - @swagger.operation(nickname="createTestResult") - def post(self): - """ - @description: create a test result - @param body: result to be created - @type body: L{ResultCreateRequest} - @in body: body - @rtype: L{CreateResponse} - @return 200: result is created. - @raise 404: pod/project/testcase not exist - @raise 400: body/pod_name/project_name/case_name not provided - """ - self._post() - - def _post(self): - def pod_query(): - return {'name': self.json_args.get('pod_name')} - - def project_query(): - return {'name': self.json_args.get('project_name')} - - def testcase_query(): - return {'project_name': self.json_args.get('project_name'), - 'name': self.json_args.get('case_name')} - - def options_check(field, options): - return self.json_args.get(field).upper() in options - - miss_fields = ['pod_name', 'project_name', 'case_name'] - carriers = [('pods', pod_query), - ('projects', project_query), - ('testcases', testcase_query)] - values_check = [('criteria', options_check, ['PASS', 'FAIL'])] - - self._create(miss_fields=miss_fields, - carriers=carriers, - values_check=values_check) - - -class ResultsUploadHandler(ResultsCLHandler): - @swagger.operation(nickname="uploadTestResult") - def post(self): - """ - @description: upload and create a test result - @param body: result to be created - @type body: L{ResultCreateRequest} - @in body: body - @rtype: L{CreateResponse} - @return 200: result is created. - @raise 404: pod/project/testcase not exist - @raise 400: body/pod_name/project_name/case_name not provided - """ - logging.info('file upload') - fileinfo = self.request.files['file'][0] - is_public = self.get_body_argument('public') - logging.warning('public:%s', is_public) - logging.info('results is :%s', fileinfo['filename']) - logging.info('results is :%s', fileinfo['body']) - self.json_args = json.loads(fileinfo['body']).copy() - self.json_args['public'] = is_public - - openid = self.get_secure_cookie(constants.TESTAPI_ID) - if openid: - self.json_args['user'] = openid - - super(ResultsUploadHandler, self)._post() - - -class ResultsGURHandler(GenericResultHandler): - @swagger.operation(nickname='getTestResultById') - def get(self, result_id): - """ - @description: get a single result by result_id - @rtype: L{TestResult} - @return 200: test result exist - @raise 404: test result not exist - """ - query = dict() - query["_id"] = objectid.ObjectId(result_id) - self._get_one(query=query) - - @swagger.operation(nickname="updateTestResultById") - def put(self, result_id): - """ - @description: update a single result by _id - @param body: fields to be updated - @type body: L{ResultUpdateRequest} - @in body: body - @rtype: L{Result} - @return 200: update success - @raise 404: result not exist - @raise 403: nothing to update - """ - query = {'_id': objectid.ObjectId(result_id)} - db_keys = [] - self._update(query=query, db_keys=db_keys) diff --git a/utils/test/testapi/opnfv_testapi/handlers/root_handlers.py b/utils/test/testapi/opnfv_testapi/handlers/root_handlers.py deleted file mode 100644 index 92920fa85..000000000 --- a/utils/test/testapi/opnfv_testapi/handlers/root_handlers.py +++ /dev/null @@ -1,10 +0,0 @@ -from opnfv_testapi.common.config import CONF -from opnfv_testapi.handlers import base_handlers - - -class RootHandler(base_handlers.GenericApiHandler): - def get_template_path(self): - return CONF.ui_static_path - - def get(self): - self.render('testapi-ui/index.html') diff --git a/utils/test/testapi/opnfv_testapi/handlers/scenario_handlers.py b/utils/test/testapi/opnfv_testapi/handlers/scenario_handlers.py deleted file mode 100644 index 67abcfff6..000000000 --- a/utils/test/testapi/opnfv_testapi/handlers/scenario_handlers.py +++ /dev/null @@ -1,775 +0,0 @@ -import functools - -from opnfv_testapi.common import message -from opnfv_testapi.common import raises -from opnfv_testapi.handlers import base_handlers -import opnfv_testapi.models.scenario_models as models -from opnfv_testapi.tornado_swagger import swagger - - -class GenericScenarioHandler(base_handlers.GenericApiHandler): - def __init__(self, application, request, **kwargs): - super(GenericScenarioHandler, self).__init__(application, - request, - **kwargs) - self.table = self.db_scenarios - self.table_cls = models.Scenario - - def set_query(self, locators): - query = dict() - elem_query = dict() - for k, v in locators.iteritems(): - if k == 'scenario': - query['name'] = v - elif k == 'installer': - elem_query["installer"] = v - elif k == 'version': - elem_query["versions.version"] = v - elif k == 'project': - elem_query["versions.projects.project"] = v - else: - query[k] = v - if elem_query: - query['installers'] = {'$elemMatch': elem_query} - return query - - -class ScenariosCLHandler(GenericScenarioHandler): - @swagger.operation(nickname="queryScenarios") - def get(self): - """ - @description: Retrieve scenario(s). - @notes: Retrieve scenario(s) - Available filters for this request are : - - name : scenario name - - GET /scenarios?name=scenario_1 - @param name: scenario name - @type name: L{string} - @in name: query - @required name: False - @param installer: installer type - @type installer: L{string} - @in installer: query - @required installer: False - @param version: version - @type version: L{string} - @in version: query - @required version: False - @param project: project name - @type project: L{string} - @in project: query - @required project: False - @return 200: all scenarios satisfy queries, - empty list if no scenario is found - @rtype: L{Scenarios} - """ - - def _set_query(): - query = dict() - elem_query = dict() - for k in self.request.query_arguments.keys(): - v = self.get_query_argument(k) - if k == 'installer': - elem_query["installer"] = v - elif k == 'version': - elem_query["versions.version"] = v - elif k == 'project': - elem_query["versions.projects.project"] = v - else: - query[k] = v - if elem_query: - query['installers'] = {'$elemMatch': elem_query} - return query - - self._list(query=_set_query()) - - @swagger.operation(nickname="createScenario") - def post(self): - """ - @description: create a new scenario by name - @param body: scenario to be created - @type body: L{ScenarioCreateRequest} - @in body: body - @rtype: L{CreateResponse} - @return 200: scenario is created. - @raise 403: scenario already exists - @raise 400: body or name not provided - """ - def query(): - return {'name': self.json_args.get('name')} - miss_fields = ['name'] - self._create(miss_fields=miss_fields, query=query) - - -class ScenarioGURHandler(GenericScenarioHandler): - @swagger.operation(nickname='getScenarioByName') - def get(self, name): - """ - @description: get a single scenario by name - @rtype: L{Scenario} - @return 200: scenario exist - @raise 404: scenario not exist - """ - self._get_one(query={'name': name}) - pass - - @swagger.operation(nickname="updateScenarioName") - def put(self, name): - """ - @description: update scenario, only rename is supported currently - @param body: fields to be updated - @type body: L{ScenarioUpdateRequest} - @in body: body - @rtype: L{Scenario} - @return 200: update success - @raise 404: scenario not exist - @raise 403: nothing to update - """ - query = {'name': name} - db_keys = ['name'] - self._update(query=query, db_keys=db_keys) - - @swagger.operation(nickname="deleteScenarioByName") - def delete(self, name): - """ - @description: delete a scenario by name - @return 200: delete success - @raise 404: scenario not exist: - """ - self._delete(query={'name': name}) - - -class ScenarioUpdater(object): - def __init__(self, data, body=None, - installer=None, version=None, project=None): - self.data = data - self.body = body - self.installer = installer - self.version = version - self.project = project - - def update(self, item, action): - updates = { - ('scores', 'post'): self._update_requests_add_score, - ('trust_indicators', 'post'): self._update_requests_add_ti, - ('customs', 'post'): self._update_requests_add_customs, - ('customs', 'put'): self._update_requests_update_customs, - ('customs', 'delete'): self._update_requests_delete_customs, - ('projects', 'post'): self._update_requests_add_projects, - ('projects', 'put'): self._update_requests_update_projects, - ('projects', 'delete'): self._update_requests_delete_projects, - ('owner', 'put'): self._update_requests_change_owner, - ('versions', 'post'): self._update_requests_add_versions, - ('versions', 'put'): self._update_requests_update_versions, - ('versions', 'delete'): self._update_requests_delete_versions, - ('installers', 'post'): self._update_requests_add_installers, - ('installers', 'put'): self._update_requests_update_installers, - ('installers', 'delete'): self._update_requests_delete_installers, - } - updates[(item, action)](self.data) - - return self.data.format() - - def iter_installers(xstep): - @functools.wraps(xstep) - def magic(self, data): - [xstep(self, installer) - for installer in self._filter_installers(data.installers)] - return magic - - def iter_versions(xstep): - @functools.wraps(xstep) - def magic(self, installer): - [xstep(self, version) - for version in (self._filter_versions(installer.versions))] - return magic - - def iter_projects(xstep): - @functools.wraps(xstep) - def magic(self, version): - [xstep(self, project) - for project in (self._filter_projects(version.projects))] - return magic - - @iter_installers - @iter_versions - @iter_projects - def _update_requests_add_score(self, project): - project.scores.append( - models.ScenarioScore.from_dict(self.body)) - - @iter_installers - @iter_versions - @iter_projects - def _update_requests_add_ti(self, project): - project.trust_indicators.append( - models.ScenarioTI.from_dict(self.body)) - - @iter_installers - @iter_versions - @iter_projects - def _update_requests_add_customs(self, project): - project.customs = list(set(project.customs + self.body)) - - @iter_installers - @iter_versions - @iter_projects - def _update_requests_update_customs(self, project): - project.customs = list(set(self.body)) - - @iter_installers - @iter_versions - @iter_projects - def _update_requests_delete_customs(self, project): - project.customs = filter( - lambda f: f not in self.body, - project.customs) - - @iter_installers - @iter_versions - def _update_requests_add_projects(self, version): - version.projects = self._update_with_body(models.ScenarioProject, - 'project', - version.projects) - - @iter_installers - @iter_versions - def _update_requests_update_projects(self, version): - version.projects = self._update_with_body(models.ScenarioProject, - 'project', - list()) - - @iter_installers - @iter_versions - def _update_requests_delete_projects(self, version): - version.projects = self._remove_projects(version.projects) - - @iter_installers - @iter_versions - def _update_requests_change_owner(self, version): - version.owner = self.body.get('owner') - - @iter_installers - def _update_requests_add_versions(self, installer): - installer.versions = self._update_with_body(models.ScenarioVersion, - 'version', - installer.versions) - - @iter_installers - def _update_requests_update_versions(self, installer): - installer.versions = self._update_with_body(models.ScenarioVersion, - 'version', - list()) - - @iter_installers - def _update_requests_delete_versions(self, installer): - installer.versions = self._remove_versions(installer.versions) - - def _update_requests_add_installers(self, scenario): - scenario.installers = self._update_with_body(models.ScenarioInstaller, - 'installer', - scenario.installers) - - def _update_requests_update_installers(self, scenario): - scenario.installers = self._update_with_body(models.ScenarioInstaller, - 'installer', - list()) - - def _update_requests_delete_installers(self, scenario): - scenario.installers = self._remove_installers(scenario.installers) - - def _update_with_body(self, clazz, field, withs): - exists = list() - malformat = list() - for new in self.body: - try: - format_new = clazz.from_dict_with_raise(new) - new_name = getattr(format_new, field) - if not any(getattr(o, field) == new_name for o in withs): - withs.append(format_new) - else: - exists.append(new_name) - except Exception as error: - malformat.append(error.message) - if malformat: - raises.BadRequest(message.bad_format(malformat)) - elif exists: - raises.Conflict(message.exist('{}s'.format(field), exists)) - return withs - - def _filter_installers(self, installers): - return self._filter('installer', installers) - - def _remove_installers(self, installers): - return self._remove('installer', installers) - - def _filter_versions(self, versions): - return self._filter('version', versions) - - def _remove_versions(self, versions): - return self._remove('version', versions) - - def _filter_projects(self, projects): - return self._filter('project', projects) - - def _remove_projects(self, projects): - return self._remove('project', projects) - - def _filter(self, item, items): - return filter( - lambda f: getattr(f, item) == getattr(self, item), - items) - - def _remove(self, field, fields): - return filter( - lambda f: getattr(f, field) not in self.body, - fields) - - -class GenericScenarioUpdateHandler(GenericScenarioHandler): - def __init__(self, application, request, **kwargs): - super(GenericScenarioUpdateHandler, self).__init__(application, - request, - **kwargs) - self.installer = None - self.version = None - self.project = None - self.item = None - self.action = None - - def do_update(self, item, action, locators): - self.item = item - self.action = action - for k, v in locators.iteritems(): - if not v: - v = self.get_query_argument(k) - setattr(self, k, v) - locators[k] = v - self.pure_update(query=self.set_query(locators=locators)) - - def _update_requests(self, data): - return ScenarioUpdater(data, - self.json_args, - self.installer, - self.version, - self.project).update(self.item, self.action) - - -class ScenarioScoresHandler(GenericScenarioUpdateHandler): - @swagger.operation(nickname="addScoreRecord") - def post(self, scenario): - """ - @description: add a new score record - @notes: add a new score record to a project - POST /api/v1/scenarios/<scenario_name>/scores? \ - installer=<installer_name>& \ - version=<version_name>& \ - project=<project_name> - @param body: score to be added - @type body: L{ScenarioScore} - @in body: body - @param installer: installer type - @type installer: L{string} - @in installer: query - @required installer: True - @param version: version - @type version: L{string} - @in version: query - @required version: True - @param project: project name - @type project: L{string} - @in project: query - @required project: True - @return 200: score is created. - @raise 404: scenario/installer/version/project not existed - """ - self.do_update('scores', - 'post', - locators={'scenario': scenario, - 'installer': None, - 'version': None, - 'project': None}) - - -class ScenarioTIsHandler(GenericScenarioUpdateHandler): - @swagger.operation(nickname="addTrustIndicatorRecord") - def post(self, scenario): - """ - @description: add a new trust indicator record - @notes: add a new trust indicator record to a project - POST /api/v1/scenarios/<scenario_name>/trust_indicators? \ - installer=<installer_name>& \ - version=<version_name>& \ - project=<project_name> - @param body: trust indicator to be added - @type body: L{ScenarioTI} - @in body: body - @param installer: installer type - @type installer: L{string} - @in installer: query - @required installer: True - @param version: version - @type version: L{string} - @in version: query - @required version: True - @param project: project name - @type project: L{string} - @in project: query - @required project: True - @return 200: trust indicator is added. - @raise 404: scenario/installer/version/project not existed - """ - self.do_update('trust_indicators', - 'post', - locators={'scenario': scenario, - 'installer': None, - 'version': None, - 'project': None}) - - -class ScenarioCustomsHandler(GenericScenarioUpdateHandler): - @swagger.operation(nickname="addCustomizedTestCases") - def post(self, scenario): - """ - @description: add customized test cases - @notes: add several test cases to a project - POST /api/v1/scenarios/<scenario_name>/customs? \ - installer=<installer_name>& \ - version=<version_name>& \ - project=<project_name> - @param body: test cases to be added - @type body: C{list} of L{string} - @in body: body - @param installer: installer type - @type installer: L{string} - @in installer: query - @required installer: True - @param version: version - @type version: L{string} - @in version: query - @required version: True - @param project: project name - @type project: L{string} - @in project: query - @required project: True - @return 200: test cases are added. - @raise 404: scenario/installer/version/project not existed - """ - self.do_update('customs', - 'post', - locators={'scenario': scenario, - 'installer': None, - 'version': None, - 'project': None}) - - @swagger.operation(nickname="updateCustomizedTestCases") - def put(self, scenario): - """ - @description: update customized test cases - @notes: substitute all the customized test cases - PUT /api/v1/scenarios/<scenario_name>/customs? \ - installer=<installer_name>& \ - version=<version_name>& \ - project=<project_name> - @param body: new supported test cases - @type body: C{list} of L{string} - @in body: body - @param installer: installer type - @type installer: L{string} - @in installer: query - @required installer: True - @param version: version - @type version: L{string} - @in version: query - @required version: True - @param project: project name - @type project: L{string} - @in project: query - @required project: True - @return 200: substitute test cases success. - @raise 404: scenario/installer/version/project not existed - """ - self.do_update('customs', - 'put', - locators={'scenario': scenario, - 'installer': None, - 'version': None, - 'project': None}) - - @swagger.operation(nickname="deleteCustomizedTestCases") - def delete(self, scenario): - """ - @description: delete one or several customized test cases - @notes: delete one or some customized test cases - DELETE /api/v1/scenarios/<scenario_name>/customs? \ - installer=<installer_name>& \ - version=<version_name>& \ - project=<project_name> - @param body: test case(s) to be deleted - @type body: C{list} of L{string} - @in body: body - @param installer: installer type - @type installer: L{string} - @in installer: query - @required installer: True - @param version: version - @type version: L{string} - @in version: query - @required version: True - @param project: project name - @type project: L{string} - @in project: query - @required project: True - @return 200: delete test case(s) success. - @raise 404: scenario/installer/version/project not existed - """ - self.do_update('customs', - 'delete', - locators={'scenario': scenario, - 'installer': None, - 'version': None, - 'project': None}) - - -class ScenarioProjectsHandler(GenericScenarioUpdateHandler): - @swagger.operation(nickname="addProjectsUnderScenario") - def post(self, scenario): - """ - @description: add projects to scenario - @notes: add one or multiple projects - POST /api/v1/scenarios/<scenario_name>/projects? \ - installer=<installer_name>& \ - version=<version_name> - @param body: projects to be added - @type body: C{list} of L{ScenarioProject} - @in body: body - @param installer: installer type - @type installer: L{string} - @in installer: query - @required installer: True - @param version: version - @type version: L{string} - @in version: query - @required version: True - @return 200: projects are added. - @raise 400: bad schema - @raise 409: conflict, project already exists - @raise 404: scenario/installer/version not existed - """ - self.do_update('projects', - 'post', - locators={'scenario': scenario, - 'installer': None, - 'version': None}) - - @swagger.operation(nickname="updateScenarioProjects") - def put(self, scenario): - """ - @description: replace all projects - @notes: substitute all projects, delete existed ones with new provides - PUT /api/v1/scenarios/<scenario_name>/projects? \ - installer=<installer_name>& \ - version=<version_name> - @param body: new projects - @type body: C{list} of L{ScenarioProject} - @in body: body - @param installer: installer type - @type installer: L{string} - @in installer: query - @required installer: True - @param version: version - @type version: L{string} - @in version: query - @required version: True - @return 200: replace projects success. - @raise 400: bad schema - @raise 404: scenario/installer/version not existed - """ - self.do_update('projects', - 'put', - locators={'scenario': scenario, - 'installer': None, - 'version': None}) - - @swagger.operation(nickname="deleteProjectsUnderScenario") - def delete(self, scenario): - """ - @description: delete one or multiple projects - @notes: delete one or multiple projects - DELETE /api/v1/scenarios/<scenario_name>/projects? \ - installer=<installer_name>& \ - version=<version_name> - @param body: projects(names) to be deleted - @type body: C{list} of L{string} - @in body: body - @param installer: installer type - @type installer: L{string} - @in installer: query - @required installer: True - @param version: version - @type version: L{string} - @in version: query - @required version: True - @return 200: delete project(s) success. - @raise 404: scenario/installer/version not existed - """ - self.do_update('projects', - 'delete', - locators={'scenario': scenario, - 'installer': None, - 'version': None}) - - -class ScenarioOwnerHandler(GenericScenarioUpdateHandler): - @swagger.operation(nickname="changeScenarioOwner") - def put(self, scenario): - """ - @description: change scenario owner - @notes: substitute all projects, delete existed ones with new provides - PUT /api/v1/scenarios/<scenario_name>/owner? \ - installer=<installer_name>& \ - version=<version_name> - @param body: new owner - @type body: L{ScenarioChangeOwnerRequest} - @in body: body - @param installer: installer type - @type installer: L{string} - @in installer: query - @required installer: True - @param version: version - @type version: L{string} - @in version: query - @required version: True - @return 200: change owner success. - @raise 404: scenario/installer/version not existed - """ - self.do_update('owner', - 'put', - locators={'scenario': scenario, - 'installer': None, - 'version': None}) - - -class ScenarioVersionsHandler(GenericScenarioUpdateHandler): - @swagger.operation(nickname="addVersionsUnderScenario") - def post(self, scenario): - """ - @description: add versions to scenario - @notes: add one or multiple versions - POST /api/v1/scenarios/<scenario_name>/versions? \ - installer=<installer_name> - @param body: versions to be added - @type body: C{list} of L{ScenarioVersion} - @in body: body - @param installer: installer type - @type installer: L{string} - @in installer: query - @required installer: True - @return 200: versions are added. - @raise 400: bad schema - @raise 409: conflict, version already exists - @raise 404: scenario/installer not exist - """ - self.do_update('versions', - 'post', - locators={'scenario': scenario, - 'installer': None}) - - @swagger.operation(nickname="updateVersionsUnderScenario") - def put(self, scenario): - """ - @description: replace all versions - @notes: substitute all versions as a totality - PUT /api/v1/scenarios/<scenario_name>/versions? \ - installer=<installer_name> - @param body: new versions - @type body: C{list} of L{ScenarioVersion} - @in body: body - @param installer: installer type - @type installer: L{string} - @in installer: query - @required installer: True - @return 200: replace versions success. - @raise 400: bad schema - @raise 404: scenario/installer not exist - """ - self.do_update('versions', - 'put', - locators={'scenario': scenario, - 'installer': None}) - - @swagger.operation(nickname="deleteVersionsUnderScenario") - def delete(self, scenario): - """ - @description: delete one or multiple versions - @notes: delete one or multiple versions - DELETE /api/v1/scenarios/<scenario_name>/versions? \ - installer=<installer_name> - @param body: versions(names) to be deleted - @type body: C{list} of L{string} - @in body: body - @param installer: installer type - @type installer: L{string} - @in installer: query - @required installer: True - @return 200: delete versions success. - @raise 404: scenario/installer not exist - """ - self.do_update('versions', - 'delete', - locators={'scenario': scenario, - 'installer': None}) - - -class ScenarioInstallersHandler(GenericScenarioUpdateHandler): - @swagger.operation(nickname="addInstallersUnderScenario") - def post(self, scenario): - """ - @description: add installers to scenario - @notes: add one or multiple installers - POST /api/v1/scenarios/<scenario_name>/installers - @param body: installers to be added - @type body: C{list} of L{ScenarioInstaller} - @in body: body - @return 200: installers are added. - @raise 400: bad schema - @raise 409: conflict, installer already exists - @raise 404: scenario not exist - """ - self.do_update('installers', - 'post', - locators={'scenario': scenario}) - - @swagger.operation(nickname="updateInstallersUnderScenario") - def put(self, scenario): - """ - @description: replace all installers - @notes: substitute all installers as a totality - PUT /api/v1/scenarios/<scenario_name>/installers - @param body: new installers - @type body: C{list} of L{ScenarioInstaller} - @in body: body - @return 200: replace versions success. - @raise 400: bad schema - @raise 404: scenario/installer not exist - """ - self.do_update('installers', - 'put', - locators={'scenario': scenario}) - - @swagger.operation(nickname="deleteInstallersUnderScenario") - def delete(self, scenario): - """ - @description: delete one or multiple installers - @notes: delete one or multiple installers - DELETE /api/v1/scenarios/<scenario_name>/installers - @param body: installers(names) to be deleted - @type body: C{list} of L{string} - @in body: body - @return 200: delete versions success. - @raise 404: scenario/installer not exist - """ - self.do_update('installers', - 'delete', - locators={'scenario': scenario}) diff --git a/utils/test/testapi/opnfv_testapi/handlers/sign_handlers.py b/utils/test/testapi/opnfv_testapi/handlers/sign_handlers.py deleted file mode 100644 index 754066256..000000000 --- a/utils/test/testapi/opnfv_testapi/handlers/sign_handlers.py +++ /dev/null @@ -1,59 +0,0 @@ -from cas import CASClient -from tornado import gen -from tornado import web - -from opnfv_testapi.common import constants -from opnfv_testapi.common.config import CONF -from opnfv_testapi.db import api as dbapi -from opnfv_testapi.handlers import base_handlers - - -class SignBaseHandler(base_handlers.GenericApiHandler): - def __init__(self, application, request, **kwargs): - super(SignBaseHandler, self).__init__(application, request, **kwargs) - self.table = 'users' - self.cas_client = CASClient(version='2', - server_url=CONF.lfid_cas_url, - service_url='{}/{}'.format( - CONF.ui_url, - CONF.lfid_signin_return)) - - -class SigninHandler(SignBaseHandler): - def get(self): - self.redirect(url=(self.cas_client.get_login_url())) - - -class SigninReturnHandler(SignBaseHandler): - - @web.asynchronous - @gen.coroutine - def get(self): - ticket = self.get_query_argument('ticket', default=None) - if ticket: - (user, attrs, _) = self.cas_client.verify_ticket(ticket=ticket) - login_user = { - 'user': user, - 'email': attrs.get('mail'), - 'fullname': attrs.get('field_lf_full_name'), - 'groups': constants.TESTAPI_USERS + attrs.get('group', []) - } - q_user = {'user': user} - db_user = yield dbapi.db_find_one(self.table, q_user) - if not db_user: - dbapi.db_save(self.table, login_user) - else: - dbapi.db_update(self.table, q_user, login_user) - - self.clear_cookie(constants.TESTAPI_ID) - self.set_secure_cookie(constants.TESTAPI_ID, user) - - self.redirect(url=CONF.ui_url) - - -class SignoutHandler(SignBaseHandler): - def get(self): - """Handle signout request.""" - self.clear_cookie(constants.TESTAPI_ID) - logout_url = self.cas_client.get_logout_url(redirect_url=CONF.ui_url) - self.redirect(url=logout_url) diff --git a/utils/test/testapi/opnfv_testapi/handlers/testcase_handlers.py b/utils/test/testapi/opnfv_testapi/handlers/testcase_handlers.py deleted file mode 100644 index c4c3c21f5..000000000 --- a/utils/test/testapi/opnfv_testapi/handlers/testcase_handlers.py +++ /dev/null @@ -1,103 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Orange -# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.com -# 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 opnfv_testapi.handlers import base_handlers -from opnfv_testapi.models import testcase_models -from opnfv_testapi.tornado_swagger import swagger - - -class GenericTestcaseHandler(base_handlers.GenericApiHandler): - def __init__(self, application, request, **kwargs): - super(GenericTestcaseHandler, self).__init__(application, - request, - **kwargs) - self.table = self.db_testcases - self.table_cls = testcase_models.Testcase - - -class TestcaseCLHandler(GenericTestcaseHandler): - @swagger.operation(nickname="listAllTestCases") - def get(self, project_name): - """ - @description: list all testcases of a project by project_name - @return 200: return all testcases of this project, - empty list is no testcase exist in this project - @rtype: L{TestCases} - """ - self._list(query={'project_name': project_name}) - - @swagger.operation(nickname="createTestCase") - def post(self, project_name): - """ - @description: create a testcase of a project by project_name - @param body: testcase to be created - @type body: L{TestcaseCreateRequest} - @in body: body - @rtype: L{CreateResponse} - @return 200: testcase is created in this project. - @raise 403: project not exist - or testcase already exists in this project - @raise 400: body or name not provided - """ - def project_query(): - return {'name': project_name} - - def testcase_query(): - return {'project_name': project_name, - 'name': self.json_args.get('name')} - miss_fields = ['name'] - carriers = [(self.db_projects, project_query)] - self._create(miss_fields=miss_fields, - carriers=carriers, - query=testcase_query, - project_name=project_name) - - -class TestcaseGURHandler(GenericTestcaseHandler): - @swagger.operation(nickname='getTestCaseByName') - def get(self, project_name, case_name): - """ - @description: get a single testcase - by case_name and project_name - @rtype: L{Testcase} - @return 200: testcase exist - @raise 404: testcase not exist - """ - query = dict() - query['project_name'] = project_name - query["name"] = case_name - self._get_one(query=query) - - @swagger.operation(nickname="updateTestCaseByName") - def put(self, project_name, case_name): - """ - @description: update a single testcase - by project_name and case_name - @param body: testcase to be updated - @type body: L{TestcaseUpdateRequest} - @in body: body - @rtype: L{Project} - @return 200: update success - @raise 404: testcase or project not exist - @raise 403: new testcase name already exist in project - or nothing to update - """ - query = {'project_name': project_name, 'name': case_name} - db_keys = ['name', 'project_name'] - self._update(query=query, db_keys=db_keys) - - @swagger.operation(nickname='deleteTestCaseByName') - def delete(self, project_name, case_name): - """ - @description: delete a testcase by project_name and case_name - @return 200: delete success - @raise 404: testcase not exist - """ - query = {'project_name': project_name, 'name': case_name} - self._delete(query=query) diff --git a/utils/test/testapi/opnfv_testapi/handlers/user_handlers.py b/utils/test/testapi/opnfv_testapi/handlers/user_handlers.py deleted file mode 100644 index 5067e358b..000000000 --- a/utils/test/testapi/opnfv_testapi/handlers/user_handlers.py +++ /dev/null @@ -1,25 +0,0 @@ -from opnfv_testapi.common import constants -from opnfv_testapi.common import raises -from opnfv_testapi.common.config import CONF -from opnfv_testapi.handlers import base_handlers -from opnfv_testapi.models.user_models import User - - -class UserHandler(base_handlers.GenericApiHandler): - def __init__(self, application, request, **kwargs): - super(UserHandler, self).__init__(application, request, **kwargs) - self.table = 'users' - self.table_cls = User - - def get(self): - if CONF.api_authenticate: - username = self.get_secure_cookie(constants.TESTAPI_ID) - if username: - self._get_one(query={'user': username}) - else: - raises.Unauthorized('Unauthorized') - else: - self.finish_request(User('anonymous', - 'anonymous@linuxfoundation.com', - 'anonymous lf', - constants.TESTAPI_USERS).format()) diff --git a/utils/test/testapi/opnfv_testapi/models/__init__.py b/utils/test/testapi/opnfv_testapi/models/__init__.py deleted file mode 100644 index 05c0c9392..000000000 --- a/utils/test/testapi/opnfv_testapi/models/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Orange -# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.com -# 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 -############################################################################## diff --git a/utils/test/testapi/opnfv_testapi/models/base_models.py b/utils/test/testapi/opnfv_testapi/models/base_models.py deleted file mode 100644 index 27396d116..000000000 --- a/utils/test/testapi/opnfv_testapi/models/base_models.py +++ /dev/null @@ -1,138 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Orange -# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.com -# 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 -# feng.xiaowei@zte.com.cn mv Pod to pod_models.py 5-18-2016 -# feng.xiaowei@zte.com.cn add MetaCreateResponse/MetaGetResponse 5-18-2016 -# feng.xiaowei@zte.com.cn mv TestProject to project_models.py 5-19-2016 -# feng.xiaowei@zte.com.cn delete meta class 5-19-2016 -# feng.xiaowei@zte.com.cn add CreateResponse 5-19-2016 -# feng.xiaowei@zte.com.cn mv TestCase to testcase_models.py 5-20-2016 -# feng.xiaowei@zte.com.cn mv TestResut to result_models.py 5-23-2016 -# feng.xiaowei@zte.com.cn add ModelBase 12-20-2016 -############################################################################## -import ast -import copy - -from opnfv_testapi.tornado_swagger import swagger - - -class ModelBase(object): - - def format(self): - return self._format(['_id']) - - def format_http(self): - return self._format([]) - - @classmethod - def from_dict(cls, a_dict): - if a_dict is None: - return None - - attr_parser = cls.attr_parser() - t = cls() - for k, v in a_dict.iteritems(): - value = v - if isinstance(v, dict) and k in attr_parser: - value = attr_parser[k].from_dict(v) - elif isinstance(v, list) and k in attr_parser: - value = [] - for item in v: - value.append(attr_parser[k].from_dict(item)) - - t.__setattr__(k, value) - - return t - - @classmethod - def from_dict_with_raise(cls, a_dict): - if a_dict is None: - return None - - attr_parser = cls.attr_parser() - t = cls() - for k, v in a_dict.iteritems(): - if k not in t.__dict__: - raise AttributeError( - '{} has no attribute {}'.format(cls.__name__, k)) - value = v - if isinstance(v, dict) and k in attr_parser: - value = attr_parser[k].from_dict_with_raise(v) - elif isinstance(v, list) and k in attr_parser: - value = [] - for item in v: - value.append(attr_parser[k].from_dict_with_raise(item)) - - t.__setattr__(k, value) - - return t - - @staticmethod - def attr_parser(): - return {} - - def _format(self, excludes): - new_obj = copy.deepcopy(self) - dicts = new_obj.__dict__ - for k in dicts.keys(): - if k in excludes: - del dicts[k] - elif dicts[k]: - dicts[k] = self._obj_format(dicts[k]) - return dicts - - def _obj_format(self, obj): - if self._has_format(obj): - obj = obj.format() - elif isinstance(obj, unicode): - try: - obj = self._obj_format(ast.literal_eval(obj)) - except Exception: - try: - obj = str(obj) - except Exception: - obj = obj - elif isinstance(obj, list): - hs = list() - for h in obj: - hs.append(self._obj_format(h)) - obj = hs - elif not isinstance(obj, (str, int, float, dict)): - obj = str(obj) - return obj - - @staticmethod - def _has_format(obj): - return not isinstance(obj, (str, unicode)) and hasattr(obj, 'format') - - -@swagger.model() -class CreateResponse(ModelBase): - def __init__(self, href=''): - self.href = href - - -@swagger.model() -class Versions(ModelBase): - """ - @property versions: - @ptype versions: C{list} of L{Version} - """ - - def __init__(self): - self.versions = list() - - @staticmethod - def attr_parser(): - return {'versions': Version} - - -@swagger.model() -class Version(ModelBase): - def __init__(self, version=None, description=None): - self.version = version - self.description = description diff --git a/utils/test/testapi/opnfv_testapi/models/pod_models.py b/utils/test/testapi/opnfv_testapi/models/pod_models.py deleted file mode 100644 index 15c283374..000000000 --- a/utils/test/testapi/opnfv_testapi/models/pod_models.py +++ /dev/null @@ -1,53 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Orange -# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.com -# 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 opnfv_testapi.models import base_models -from opnfv_testapi.tornado_swagger import swagger - - -# name: name of the POD e.g. zte-1 -# mode: metal or virtual -# details: any detail -# role: ci-pod or community-pod or single-node - - -@swagger.model() -class PodCreateRequest(base_models.ModelBase): - def __init__(self, name, mode='', details='', role=""): - self.name = name - self.mode = mode - self.details = details - self.role = role - - -@swagger.model() -class Pod(base_models.ModelBase): - def __init__(self, - name='', mode='', details='', - role="", _id='', create_date='', owner=''): - self.name = name - self.mode = mode - self.details = details - self.role = role - self._id = _id - self.creation_date = create_date - self.owner = owner - - -@swagger.model() -class Pods(base_models.ModelBase): - """ - @property pods: - @ptype pods: C{list} of L{Pod} - """ - def __init__(self): - self.pods = list() - - @staticmethod - def attr_parser(): - return {'pods': Pod} diff --git a/utils/test/testapi/opnfv_testapi/models/project_models.py b/utils/test/testapi/opnfv_testapi/models/project_models.py deleted file mode 100644 index 5f280f192..000000000 --- a/utils/test/testapi/opnfv_testapi/models/project_models.py +++ /dev/null @@ -1,48 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Orange -# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.com -# 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 opnfv_testapi.models import base_models -from opnfv_testapi.tornado_swagger import swagger - - -@swagger.model() -class ProjectCreateRequest(base_models.ModelBase): - def __init__(self, name, description=''): - self.name = name - self.description = description - - -@swagger.model() -class ProjectUpdateRequest(base_models.ModelBase): - def __init__(self, name='', description=''): - self.name = name - self.description = description - - -@swagger.model() -class Project(base_models.ModelBase): - def __init__(self, - name=None, _id=None, description=None, create_date=None): - self._id = _id - self.name = name - self.description = description - self.creation_date = create_date - - -@swagger.model() -class Projects(base_models.ModelBase): - """ - @property projects: - @ptype projects: C{list} of L{Project} - """ - def __init__(self): - self.projects = list() - - @staticmethod - def attr_parser(): - return {'projects': Project} diff --git a/utils/test/testapi/opnfv_testapi/models/result_models.py b/utils/test/testapi/opnfv_testapi/models/result_models.py deleted file mode 100644 index 97fda08b4..000000000 --- a/utils/test/testapi/opnfv_testapi/models/result_models.py +++ /dev/null @@ -1,129 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Orange -# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.com -# 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 opnfv_testapi.models import base_models -from opnfv_testapi.tornado_swagger import swagger - - -@swagger.model() -class TIHistory(base_models.ModelBase): - """ - @ptype step: L{float} - """ - def __init__(self, date=None, step=0): - self.date = date - self.step = step - - -@swagger.model() -class TI(base_models.ModelBase): - """ - @property histories: trust_indicator update histories - @ptype histories: C{list} of L{TIHistory} - @ptype current: L{float} - """ - def __init__(self, current=0): - self.current = current - self.histories = list() - - @staticmethod - def attr_parser(): - return {'histories': TIHistory} - - -@swagger.model() -class ResultCreateRequest(base_models.ModelBase): - """ - @property trust_indicator: - @ptype trust_indicator: L{TI} - """ - def __init__(self, - pod_name=None, - project_name=None, - case_name=None, - installer=None, - version=None, - start_date=None, - stop_date=None, - details=None, - build_tag=None, - scenario=None, - criteria=None, - user=None, - public="true", - trust_indicator=None): - self.pod_name = pod_name - self.project_name = project_name - self.case_name = case_name - self.installer = installer - self.version = version - self.start_date = start_date - self.stop_date = stop_date - self.details = details - self.build_tag = build_tag - self.scenario = scenario - self.criteria = criteria - self.user = user - self.public = public - self.trust_indicator = trust_indicator if trust_indicator else TI(0) - - -@swagger.model() -class ResultUpdateRequest(base_models.ModelBase): - """ - @property trust_indicator: - @ptype trust_indicator: L{TI} - """ - def __init__(self, trust_indicator=None): - self.trust_indicator = trust_indicator - - -@swagger.model() -class TestResult(base_models.ModelBase): - """ - @property trust_indicator: used for long duration test case - @ptype trust_indicator: L{TI} - """ - def __init__(self, _id=None, case_name=None, project_name=None, - pod_name=None, installer=None, version=None, - start_date=None, stop_date=None, details=None, - build_tag=None, scenario=None, criteria=None, - user=None, public="true", trust_indicator=None): - self._id = _id - self.case_name = case_name - self.project_name = project_name - self.pod_name = pod_name - self.installer = installer - self.version = version - self.start_date = start_date - self.stop_date = stop_date - self.details = details - self.build_tag = build_tag - self.scenario = scenario - self.criteria = criteria - self.user = user - self.public = public - self.trust_indicator = trust_indicator - - @staticmethod - def attr_parser(): - return {'trust_indicator': TI} - - -@swagger.model() -class TestResults(base_models.ModelBase): - """ - @property results: - @ptype results: C{list} of L{TestResult} - """ - def __init__(self): - self.results = list() - - @staticmethod - def attr_parser(): - return {'results': TestResult} diff --git a/utils/test/testapi/opnfv_testapi/models/scenario_models.py b/utils/test/testapi/opnfv_testapi/models/scenario_models.py deleted file mode 100644 index 0610c6b4c..000000000 --- a/utils/test/testapi/opnfv_testapi/models/scenario_models.py +++ /dev/null @@ -1,218 +0,0 @@ -from opnfv_testapi.models import base_models -from opnfv_testapi.tornado_swagger import swagger - - -def list_default(value): - return value if value else list() - - -def dict_default(value): - return value if value else dict() - - -@swagger.model() -class ScenarioTI(base_models.ModelBase): - def __init__(self, date=None, status='silver'): - self.date = date - self.status = status - - def __eq__(self, other): - return (self.date == other.date and - self.status == other.status) - - def __ne__(self, other): - return not self.__eq__(other) - - -@swagger.model() -class ScenarioScore(base_models.ModelBase): - def __init__(self, date=None, score='0'): - self.date = date - self.score = score - - def __eq__(self, other): - return (self.date == other.date and - self.score == other.score) - - def __ne__(self, other): - return not self.__eq__(other) - - -@swagger.model() -class ScenarioProject(base_models.ModelBase): - """ - @property customs: - @ptype customs: C{list} of L{string} - @property scores: - @ptype scores: C{list} of L{ScenarioScore} - @property trust_indicators: - @ptype trust_indicators: C{list} of L{ScenarioTI} - """ - def __init__(self, - project='', - customs=None, - scores=None, - trust_indicators=None): - self.project = project - self.customs = list_default(customs) - self.scores = list_default(scores) - self.trust_indicators = list_default(trust_indicators) - - @staticmethod - def attr_parser(): - return {'scores': ScenarioScore, - 'trust_indicators': ScenarioTI} - - def __eq__(self, other): - return (self.project == other.project and - self._customs_eq(other) and - self._scores_eq(other) and - self._ti_eq(other)) - - def __ne__(self, other): - return not self.__eq__(other) - - def _customs_eq(self, other): - return set(self.customs) == set(other.customs) - - def _scores_eq(self, other): - return self.scores == other.scores - - def _ti_eq(self, other): - return self.trust_indicators == other.trust_indicators - - -@swagger.model() -class ScenarioVersion(base_models.ModelBase): - """ - @property projects: - @ptype projects: C{list} of L{ScenarioProject} - """ - def __init__(self, owner=None, version=None, projects=None): - self.owner = owner - self.version = version - self.projects = list_default(projects) - - @staticmethod - def attr_parser(): - return {'projects': ScenarioProject} - - def __eq__(self, other): - return (self.version == other.version and - self.owner == other.owner and - self._projects_eq(other)) - - def __ne__(self, other): - return not self.__eq__(other) - - def _projects_eq(self, other): - for s_project in self.projects: - for o_project in other.projects: - if s_project.project == o_project.project: - if s_project != o_project: - return False - - return True - - -@swagger.model() -class ScenarioInstaller(base_models.ModelBase): - """ - @property versions: - @ptype versions: C{list} of L{ScenarioVersion} - """ - def __init__(self, installer=None, versions=None): - self.installer = installer - self.versions = list_default(versions) - - @staticmethod - def attr_parser(): - return {'versions': ScenarioVersion} - - def __eq__(self, other): - return (self.installer == other.installer and self._versions_eq(other)) - - def __ne__(self, other): - return not self.__eq__(other) - - def _versions_eq(self, other): - for s_version in self.versions: - for o_version in other.versions: - if s_version.version == o_version.version: - if s_version != o_version: - return False - - return True - - -@swagger.model() -class ScenarioCreateRequest(base_models.ModelBase): - """ - @property installers: - @ptype installers: C{list} of L{ScenarioInstaller} - """ - def __init__(self, name='', installers=None): - self.name = name - self.installers = list_default(installers) - - @staticmethod - def attr_parser(): - return {'installers': ScenarioInstaller} - - -@swagger.model() -class ScenarioChangeOwnerRequest(base_models.ModelBase): - def __init__(self, owner=None): - self.owner = owner - - -@swagger.model() -class ScenarioUpdateRequest(base_models.ModelBase): - def __init__(self, name=None): - self.name = name - - -@swagger.model() -class Scenario(base_models.ModelBase): - """ - @property installers: - @ptype installers: C{list} of L{ScenarioInstaller} - """ - def __init__(self, name='', create_date='', _id='', installers=None): - self.name = name - self._id = _id - self.creation_date = create_date - self.installers = list_default(installers) - - @staticmethod - def attr_parser(): - return {'installers': ScenarioInstaller} - - def __ne__(self, other): - return not self.__eq__(other) - - def __eq__(self, other): - return (self.name == other.name and self._installers_eq(other)) - - def _installers_eq(self, other): - for s_install in self.installers: - for o_install in other.installers: - if s_install.installer == o_install.installer: - if s_install != o_install: - return False - - return True - - -@swagger.model() -class Scenarios(base_models.ModelBase): - """ - @property scenarios: - @ptype scenarios: C{list} of L{Scenario} - """ - def __init__(self): - self.scenarios = list() - - @staticmethod - def attr_parser(): - return {'scenarios': Scenario} diff --git a/utils/test/testapi/opnfv_testapi/models/testcase_models.py b/utils/test/testapi/opnfv_testapi/models/testcase_models.py deleted file mode 100644 index d1b8877f7..000000000 --- a/utils/test/testapi/opnfv_testapi/models/testcase_models.py +++ /dev/null @@ -1,95 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Orange -# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.com -# 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 opnfv_testapi.models import base_models -from opnfv_testapi.tornado_swagger import swagger - - -@swagger.model() -class TestcaseCreateRequest(base_models.ModelBase): - def __init__(self, name, url=None, description=None, - catalog_description=None, tier=None, ci_loop=None, - criteria=None, blocking=None, dependencies=None, run=None, - domains=None, tags=None, version=None): - self.name = name - self.url = url - self.description = description - self.catalog_description = catalog_description - self.tier = tier - self.ci_loop = ci_loop - self.criteria = criteria - self.blocking = blocking - self.dependencies = dependencies - self.run = run - self.domains = domains - self.tags = tags - self.version = version - self.trust = "Silver" - - -@swagger.model() -class TestcaseUpdateRequest(base_models.ModelBase): - def __init__(self, name=None, description=None, project_name=None, - catalog_description=None, tier=None, ci_loop=None, - criteria=None, blocking=None, dependencies=None, run=None, - domains=None, tags=None, version=None, trust=None): - self.name = name - self.description = description - self.catalog_description = catalog_description - self.project_name = project_name - self.tier = tier - self.ci_loop = ci_loop - self.criteria = criteria - self.blocking = blocking - self.dependencies = dependencies - self.run = run - self.domains = domains - self.tags = tags - self.version = version - self.trust = trust - - -@swagger.model() -class Testcase(base_models.ModelBase): - def __init__(self, _id=None, name=None, project_name=None, - description=None, url=None, creation_date=None, - catalog_description=None, tier=None, ci_loop=None, - criteria=None, blocking=None, dependencies=None, run=None, - domains=None, tags=None, version=None, - trust=None): - self._id = None - self.name = None - self.project_name = None - self.description = None - self.catalog_description = None - self.url = None - self.creation_date = None - self.tier = None - self.ci_loop = None - self.criteria = None - self.blocking = None - self.dependencies = None - self.run = None - self.domains = None - self.tags = None - self.version = None - self.trust = None - - -@swagger.model() -class Testcases(base_models.ModelBase): - """ - @property testcases: - @ptype testcases: C{list} of L{Testcase} - """ - def __init__(self): - self.testcases = list() - - @staticmethod - def attr_parser(): - return {'testcases': Testcase} diff --git a/utils/test/testapi/opnfv_testapi/models/user_models.py b/utils/test/testapi/opnfv_testapi/models/user_models.py deleted file mode 100644 index 90fbadcd4..000000000 --- a/utils/test/testapi/opnfv_testapi/models/user_models.py +++ /dev/null @@ -1,9 +0,0 @@ -from opnfv_testapi.models import base_models - - -class User(base_models.ModelBase): - def __init__(self, user=None, email=None, fullname=None, groups=None): - self.user = user - self.email = email - self.fullname = fullname - self.groups = groups diff --git a/utils/test/testapi/opnfv_testapi/router/__init__.py b/utils/test/testapi/opnfv_testapi/router/__init__.py deleted file mode 100644 index 3fc79f1d5..000000000 --- a/utils/test/testapi/opnfv_testapi/router/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -############################################################################## -# Copyright (c) 2016 ZTE Corporation -# feng.xiaowei@zte.com.cn -# 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 -############################################################################## -__author__ = 'serena' diff --git a/utils/test/testapi/opnfv_testapi/router/url_mappings.py b/utils/test/testapi/opnfv_testapi/router/url_mappings.py deleted file mode 100644 index 349d55771..000000000 --- a/utils/test/testapi/opnfv_testapi/router/url_mappings.py +++ /dev/null @@ -1,84 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Orange -# guyrodrigue.koffi@orange.com / koffirodrigue@gmail.com -# 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.web - -from opnfv_testapi.common.config import CONF -from opnfv_testapi.handlers import base_handlers -from opnfv_testapi.handlers import pod_handlers -from opnfv_testapi.handlers import project_handlers -from opnfv_testapi.handlers import result_handlers -from opnfv_testapi.handlers import root_handlers -from opnfv_testapi.handlers import scenario_handlers -from opnfv_testapi.handlers import sign_handlers -from opnfv_testapi.handlers import testcase_handlers -from opnfv_testapi.handlers import user_handlers - -mappings = [ - # GET /versions => GET API version - (r"/versions", base_handlers.VersionHandler), - - # few examples: - # GET /api/v1/pods => Get all pods - # GET /api/v1/pods/1 => Get details on POD 1 - (r"/api/v1/pods", pod_handlers.PodCLHandler), - (r"/api/v1/pods/([^/]+)", pod_handlers.PodGURHandler), - - # few examples: - # GET /projects - # GET /projects/yardstick - (r"/api/v1/projects", project_handlers.ProjectCLHandler), - (r"/api/v1/projects/([^/]+)", project_handlers.ProjectGURHandler), - - # few examples - # GET /projects/qtip/cases => Get cases for qtip - (r"/api/v1/projects/([^/]+)/cases", testcase_handlers.TestcaseCLHandler), - (r"/api/v1/projects/([^/]+)/cases/([^/]+)", - testcase_handlers.TestcaseGURHandler), - - # new path to avoid a long depth - # GET /results?project=functest&case=keystone.catalog&pod=1 - # => get results with optional filters - # POST /results => - # Push results with mandatory request payload parameters - # (project, case, and pod) - (r"/api/v1/results", result_handlers.ResultsCLHandler), - (r'/api/v1/results/upload', result_handlers.ResultsUploadHandler), - (r"/api/v1/results/([^/]+)", result_handlers.ResultsGURHandler), - - # scenarios - (r"/api/v1/scenarios", scenario_handlers.ScenariosCLHandler), - (r"/api/v1/scenarios/([^/]+)", scenario_handlers.ScenarioGURHandler), - (r"/api/v1/scenarios/([^/]+)/scores", - scenario_handlers.ScenarioScoresHandler), - (r"/api/v1/scenarios/([^/]+)/trust_indicators", - scenario_handlers.ScenarioTIsHandler), - (r"/api/v1/scenarios/([^/]+)/customs", - scenario_handlers.ScenarioCustomsHandler), - (r"/api/v1/scenarios/([^/]+)/projects", - scenario_handlers.ScenarioProjectsHandler), - (r"/api/v1/scenarios/([^/]+)/owner", - scenario_handlers.ScenarioOwnerHandler), - (r"/api/v1/scenarios/([^/]+)/versions", - scenario_handlers.ScenarioVersionsHandler), - (r"/api/v1/scenarios/([^/]+)/installers", - scenario_handlers.ScenarioInstallersHandler), - - # static path - (r'/(.*\.(css|png|gif|js|html|json|map|woff2|woff|ttf))', - tornado.web.StaticFileHandler, - {'path': CONF.ui_static_path}), - - (r'/', root_handlers.RootHandler), - (r'/api/v1/auth/signin', sign_handlers.SigninHandler), - (r'/{}'.format(CONF.lfid_signin_return), - sign_handlers.SigninReturnHandler), - (r'/api/v1/auth/signout', sign_handlers.SignoutHandler), - (r'/api/v1/profile', user_handlers.UserHandler), - -] diff --git a/utils/test/testapi/opnfv_testapi/tests/UI/e2e/podsControllerSpec.js b/utils/test/testapi/opnfv_testapi/tests/UI/e2e/podsControllerSpec.js deleted file mode 100644 index 66a57f2f2..000000000 --- a/utils/test/testapi/opnfv_testapi/tests/UI/e2e/podsControllerSpec.js +++ /dev/null @@ -1,188 +0,0 @@ -'use strict'; - -var mock = require('protractor-http-mock'); -var baseURL = "http://localhost:8000" -describe('testing the Pods page for anonymous user', function () { - - beforeEach(function(){ - mock([{ - request: { - path: '/api/v1/pods', - method: 'GET' - }, - response: { - data: { - pods: [{role: "community-ci", name: "test", owner: "testUser", details: "DemoDetails", mode: "metal", _id: "59f02f099a07c84bfc5c7aed", creation_date: "2017-10-25 11:58:25.926168"}] - } - } - }]); - }); - - it( 'should navigate to pods link ', function() { - browser.get(baseURL); - var podslink = element(by.linkText('Pods')).click(); - var EC = browser.ExpectedConditions; - browser.wait(EC.urlContains(baseURL+ '/#/pods'), 10000); - }); - - it('create button is not visible for anonymous user', function () { - browser.get(baseURL+'#/pods'); - var buttonCreate = element(by.buttonText('Create')); - expect(buttonCreate.isDisplayed()).toBeFalsy(); - }); - - it('filter button is visible for anonymous user', function () { - var buttonFilter = element(by.buttonText('Filter')); - expect(buttonFilter.isDisplayed()).toBe(true) - }); - - it('clear button is visible for anonymous user', function () { - var buttonClear = element(by.buttonText('Clear')); - expect(buttonClear.isDisplayed()).toBe(true) - }); - - it('Show results when click filter button', function () { - var buttonFilter = element(by.buttonText('Filter')); - buttonFilter.click(); - var pod = element(by.css('.show-pod')); - expect(pod.isPresent()).toBe(true); - }); - - it('Show results when click clear button', function () { - browser.get(baseURL+'#/pods'); - var buttonClear = element(by.buttonText('Clear')); - buttonClear.click(); - var pod = element(by.css('.show-pod')); - expect(pod.isPresent()).toBe(true); - }); - - it('If details is not shown then show details when click the link',function() { - expect(element(by.css('.show-pod.hidden')).isPresent()).toBe(true); - var podslink = element(by.linkText('test')).click(); - expect(element(by.css('.show-pod.hidden')).isPresent()).toBe(false); - }); - - it('If details is shown then hide details when click the link',function() { - expect(element(by.css('.show-pod.hidden')).isPresent()).toBe(false); - var podslink = element(by.linkText('test')).click(); - expect(element(by.css('.show-pod.hidden')).isPresent()).toBe(true); - }); - - it('If backend is not responding then show error when click filter button', function () { - browser.get(baseURL + '/#/pods'); - mock.teardown(); - var buttonFilter = element(by.buttonText('Filter')); - buttonFilter.click().then(function(){ - expect(element(by.css('.alert.alert-danger.ng-binding.ng-scope')).isDisplayed()).toBe(true); - }); - }); - -}); - -describe('testing the Pods page for authorized user', function () { - - beforeEach(function(){ - mock([ - { - request: { - path: '/api/v1/pods', - method: 'POST' - }, - response: { - data: { - href: baseURL+"/api/v1/pods/test" - } - } - }, - { - request: { - path: '/api/v1/pods', - method: 'POST', - data: { - name: 'test1', - details : 'DemoDetails', - role : 'community-ci', - mode : 'metal' - } - }, - response: { - status : 403 - } - }, - { - request: { - path: '/api/v1/profile', - method: 'GET' - }, - response: { - data: { - "fullname": "Test User", "_id": "79f82eey9a00c84bfhc7aed", "user": "testUser", "groups": ["opnfv-testapi-users"], "email": "testuser@test.com" - } - } - } - ]); - }); - - it('create button is visible for authorized user', function () { - browser.get(baseURL + '/#/pods'); - var buttonCreate = element(by.buttonText('Create')); - expect(buttonCreate.isDisplayed()).toBe(true); - }); - - it('Do not show error if input is acceptable', function () { - var name = element(by.model('ctrl.name')); - var details = element(by.model('ctrl.details')); - name.sendKeys('test'); - details.sendKeys('DemoDetails'); - var buttonCreate = element(by.buttonText('Create')); - buttonCreate.click().then(function(){ - expect(element(by.css('.alert.alert-danger.ng-binding.ng-scope')).isDisplayed()).toBe(false); - }); - }); - - it('Show error when user click the create button with a empty name', function () { - browser.get(baseURL+ '/#/pods'); - var details = element(by.model('ctrl.details')); - details.sendKeys('DemoDetails'); - var buttonCreate = element(by.buttonText('Create')); - buttonCreate.click(); - expect(element(by.cssContainingText(".alert","Name is missing.")).isDisplayed()).toBe(true); - }); - - it('Show error when user click the create button with an already existing name', function () { - browser.get(baseURL+ '/#/pods'); - var name = element(by.model('ctrl.name')); - var details = element(by.model('ctrl.details')); - name.sendKeys('test1'); - details.sendKeys('DemoDetails'); - var buttonCreate = element(by.buttonText('Create')); - buttonCreate.click(); - expect(element(by.cssContainingText(".alert","Error creating the new pod from server: Pod's name already exists")).isDisplayed()).toBe(true); - }); - - it('If backend is not responding then show error when user click the create button',function(){ - mock.teardown(); - mock([ - { - request: { - path: '/api/v1/profile', - method: 'GET' - }, - response: { - data: { - "fullname": "Test User", "_id": "79f82eey9a00c84bfhc7aed", "user": "testUser", "groups": ["opnfv-testapi-users"], "email": "testuser@test.com" - } - } - } - ]); - browser.get(baseURL+ '/#/pods'); - var name = element(by.model('ctrl.name')); - var details = element(by.model('ctrl.details')); - name.sendKeys('test'); - details.sendKeys('DemoDetails'); - var buttonCreate = element(by.buttonText('Create')); - buttonCreate.click().then(function(){ - expect(element(by.css('.alert.alert-danger.ng-binding.ng-scope')).isDisplayed()).toBe(true); - }); - }) -});
\ No newline at end of file diff --git a/utils/test/testapi/opnfv_testapi/tests/UI/karma.conf.js b/utils/test/testapi/opnfv_testapi/tests/UI/karma.conf.js deleted file mode 100644 index eaded5a1d..000000000 --- a/utils/test/testapi/opnfv_testapi/tests/UI/karma.conf.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = function (config) { - config.set({ - frameworks: ['jasmine'], - files: [ - "assets/lib/angular/angular.js", - "assets/lib/angular-mocks/angular-mocks.js", - ], - autoWatch: true, - browsers: ['Chrome'], - singleRun: true, - reporters: ['progress', 'coverage'], - preprocessors: { 'src/*.js': ['coverage'] } - }); -}; diff --git a/utils/test/testapi/opnfv_testapi/tests/UI/protractor-conf.js b/utils/test/testapi/opnfv_testapi/tests/UI/protractor-conf.js deleted file mode 100644 index affbe5d26..000000000 --- a/utils/test/testapi/opnfv_testapi/tests/UI/protractor-conf.js +++ /dev/null @@ -1,18 +0,0 @@ -exports.config = { - seleniumAddress: 'http://localhost:4444/wd/hub', - capabilities: { - 'browserName': 'chrome', - 'chromeOptions': { - 'args': ['show-fps-counter=true', '--disable-web-security', "no-sandbox", "--headless", "--disable-gpu"] - } - }, - jasmineNodeOpts: { - showColors: true, - defaultTimeoutInterval: 30000 - }, - onPrepare: function(){ - require('protractor-http-mock').config = { - rootDirectory: __dirname - }; - } -}; diff --git a/utils/test/testapi/opnfv_testapi/tests/__init__.py b/utils/test/testapi/opnfv_testapi/tests/__init__.py deleted file mode 100644 index 9f28b0bfa..000000000 --- a/utils/test/testapi/opnfv_testapi/tests/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__author__ = 'serena' diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/__init__.py b/utils/test/testapi/opnfv_testapi/tests/unit/__init__.py deleted file mode 100644 index 3fc79f1d5..000000000 --- a/utils/test/testapi/opnfv_testapi/tests/unit/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -############################################################################## -# Copyright (c) 2016 ZTE Corporation -# feng.xiaowei@zte.com.cn -# 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 -############################################################################## -__author__ = 'serena' diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/common/__init__.py b/utils/test/testapi/opnfv_testapi/tests/unit/common/__init__.py deleted file mode 100644 index e69de29bb..000000000 --- a/utils/test/testapi/opnfv_testapi/tests/unit/common/__init__.py +++ /dev/null diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/common/test_config.py b/utils/test/testapi/opnfv_testapi/tests/unit/common/test_config.py deleted file mode 100644 index 6d160ce1d..000000000 --- a/utils/test/testapi/opnfv_testapi/tests/unit/common/test_config.py +++ /dev/null @@ -1,25 +0,0 @@ -import argparse -import pytest - - -def test_config_normal(mocker, config_normal): - mocker.patch( - 'argparse.ArgumentParser.parse_known_args', - return_value=(argparse.Namespace(config_file=config_normal), None)) - from opnfv_testapi.common import config - CONF = config.Config() - assert CONF.mongo_url == 'mongodb://127.0.0.1:27017/' - assert CONF.mongo_dbname == 'test_results_collection' - assert CONF.api_port == 8000 - assert CONF.api_debug is True - assert CONF.api_token_check is False - assert CONF.api_authenticate is True - assert CONF.ui_url == 'http://localhost:8000' - - -def test_config_file_not_exist(mocker): - mocker.patch('os.path.exists', return_value=False) - with pytest.raises(Exception) as m_exc: - from opnfv_testapi.common import config - config.Config() - assert 'not found' in str(m_exc.value) diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/conftest.py b/utils/test/testapi/opnfv_testapi/tests/unit/conftest.py deleted file mode 100644 index 75e621d0e..000000000 --- a/utils/test/testapi/opnfv_testapi/tests/unit/conftest.py +++ /dev/null @@ -1,8 +0,0 @@ -from os import path - -import pytest - - -@pytest.fixture -def config_normal(): - return path.join(path.dirname(__file__), '../../../etc/config.ini') diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/executor.py b/utils/test/testapi/opnfv_testapi/tests/unit/executor.py deleted file mode 100644 index 743c07615..000000000 --- a/utils/test/testapi/opnfv_testapi/tests/unit/executor.py +++ /dev/null @@ -1,130 +0,0 @@ -############################################################################## -# Copyright (c) 2017 ZTE Corp -# feng.xiaowei@zte.com.cn -# 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 functools -import httplib - -from concurrent.futures import ThreadPoolExecutor -import mock - - -O_get_secure_cookie = ( - 'opnfv_testapi.handlers.base_handlers.GenericApiHandler.get_secure_cookie') - - -def thread_execute(method, *args, **kwargs): - with ThreadPoolExecutor(max_workers=2) as executor: - result = executor.submit(method, *args, **kwargs) - return result - - -def mock_invalid_lfid(): - def _mock_invalid_lfid(xstep): - def wrap(self, *args, **kwargs): - with mock.patch(O_get_secure_cookie) as m_cookie: - m_cookie.return_value = 'InvalidUser' - return xstep(self, *args, **kwargs) - return wrap - return _mock_invalid_lfid - - -def mock_valid_lfid(): - def _mock_valid_lfid(xstep): - def wrap(self, *args, **kwargs): - with mock.patch(O_get_secure_cookie) as m_cookie: - m_cookie.return_value = 'ValidUser' - return xstep(self, *args, **kwargs) - return wrap - return _mock_valid_lfid - - -def upload(excepted_status, excepted_response): - def _upload(create_request): - @functools.wraps(create_request) - def wrap(self): - request = create_request(self) - status, body = self.upload(request) - if excepted_status == httplib.OK: - getattr(self, excepted_response)(body) - else: - self.assertIn(excepted_response, body) - return wrap - return _upload - - -def create(excepted_status, excepted_response): - def _create(create_request): - @functools.wraps(create_request) - def wrap(self): - request = create_request(self) - status, body = self.create(request) - if excepted_status == httplib.OK: - getattr(self, excepted_response)(body) - else: - self.assertIn(excepted_response, body) - return wrap - return _create - - -def get(excepted_status, excepted_response): - def _get(get_request): - @functools.wraps(get_request) - def wrap(self): - request = get_request(self) - status, body = self.get(request) - if excepted_status == httplib.OK: - getattr(self, excepted_response)(body) - else: - self.assertIn(excepted_response, body) - return wrap - return _get - - -def update(excepted_status, excepted_response): - def _update(update_request): - @functools.wraps(update_request) - def wrap(self): - request, resource = update_request(self) - status, body = self.update(request, resource) - if excepted_status == httplib.OK: - getattr(self, excepted_response)(request, body) - else: - self.assertIn(excepted_response, body) - return wrap - return _update - - -def delete(excepted_status, excepted_response): - def _delete(delete_request): - @functools.wraps(delete_request) - def wrap(self): - request = delete_request(self) - if isinstance(request, tuple): - status, body = self.delete(request[0], *(request[1])) - else: - status, body = self.delete(request) - if excepted_status == httplib.OK: - getattr(self, excepted_response)(body) - else: - self.assertIn(excepted_response, body) - return wrap - return _delete - - -def query(excepted_status, excepted_response, number=0): - def _query(get_request): - @functools.wraps(get_request) - def wrap(self): - request = get_request(self) - status, body = self.query(request) - if excepted_status == httplib.OK: - getattr(self, excepted_response)(body, number) - else: - self.assertIn(excepted_response, body) - return wrap - return _query diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/fake_pymongo.py b/utils/test/testapi/opnfv_testapi/tests/unit/fake_pymongo.py deleted file mode 100644 index c44a92c11..000000000 --- a/utils/test/testapi/opnfv_testapi/tests/unit/fake_pymongo.py +++ /dev/null @@ -1,291 +0,0 @@ -############################################################################## -# Copyright (c) 2016 ZTE Corporation -# feng.xiaowei@zte.com.cn -# 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 re - -from operator import itemgetter - -from bson.objectid import ObjectId -from concurrent.futures import ThreadPoolExecutor - - -def thread_execute(method, *args, **kwargs): - with ThreadPoolExecutor(max_workers=2) as executor: - result = executor.submit(method, *args, **kwargs) - return result - - -class MemCursor(object): - def __init__(self, collection): - self.collection = collection - self.length = len(self.collection) - self.sorted = [] - - def _is_next_exist(self): - return self.length != 0 - - @property - def fetch_next(self): - return thread_execute(self._is_next_exist) - - def next_object(self): - self.length -= 1 - return self.collection.pop() - - def sort(self, key_or_list): - for k, v in key_or_list.iteritems(): - if v == -1: - reverse = True - else: - reverse = False - - self.collection = sorted(self.collection, - key=itemgetter(k), reverse=reverse) - return self - - def limit(self, limit): - if limit != 0 and limit < len(self.collection): - 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): - - def __init__(self, name): - self.name = name - self.contents = [] - pass - - def _find_one(self, spec_or_id=None, *args): - if spec_or_id is not None and not isinstance(spec_or_id, dict): - spec_or_id = {"_id": spec_or_id} - if '_id' in spec_or_id: - spec_or_id['_id'] = str(spec_or_id['_id']) - cursor = self._find(spec_or_id, *args) - for result in cursor: - return result - return None - - def find_one(self, spec_or_id=None, *args): - return thread_execute(self._find_one, spec_or_id, *args) - - def _insert(self, doc_or_docs, check_keys=True): - - docs = doc_or_docs - return_one = False - if isinstance(docs, dict): - return_one = True - docs = [docs] - - if check_keys: - for doc in docs: - self._check_keys(doc) - - ids = [] - for doc in docs: - if '_id' not in doc: - doc['_id'] = str(ObjectId()) - if not self._find_one(doc['_id']): - ids.append(doc['_id']) - self.contents.append(doc_or_docs) - - if len(ids) == 0: - return None - if return_one: - return ids[0] - else: - return ids - - def insert(self, doc_or_docs, check_keys=True): - return thread_execute(self._insert, doc_or_docs, check_keys) - - @staticmethod - def _compare_date(spec, value): - gte = True - lt = False - for k, v in spec.iteritems(): - if k == '$gte' and value < v: - gte = False - elif k == '$lt' and value < v: - lt = True - return gte and lt - - def _in(self, content, *args): - if self.name == 'scenarios': - return self._in_scenarios(content, *args) - else: - return self._in_others(content, *args) - - def _in_scenarios_installer(self, installer, content): - hit = False - for s_installer in content['installers']: - if installer == s_installer['installer']: - hit = True - - return hit - - def _in_scenarios_version(self, version, content): - hit = False - for s_installer in content['installers']: - for s_version in s_installer['versions']: - if version == s_version['version']: - hit = True - return hit - - def _in_scenarios_project(self, project, content): - hit = False - for s_installer in content['installers']: - for s_version in s_installer['versions']: - for s_project in s_version['projects']: - if project == s_project['project']: - hit = True - - return hit - - def _in_scenarios(self, content, *args): - for arg in args: - for k, v in arg.iteritems(): - if k == 'installers': - for inner in v.values(): - for i_k, i_v in inner.iteritems(): - if i_k == 'installer': - return self._in_scenarios_installer(i_v, - content) - elif i_k == 'versions.version': - return self._in_scenarios_version(i_v, - content) - elif i_k == 'versions.projects.project': - return self._in_scenarios_project(i_v, - content) - elif content.get(k, None) != v: - return False - - return True - - def _in_others(self, content, *args): - for arg in args: - for k, v in arg.iteritems(): - if k == 'start_date': - if not MemDb._compare_date(v, content.get(k)): - return False - elif k == 'trust_indicator.current': - if content.get('trust_indicator').get('current') != v: - return False - elif not isinstance(v, dict): - if isinstance(v, re._pattern_type): - if v.match(content.get(k, None)) is None: - return False - else: - if content.get(k, None) != v: - return False - return True - - def _find(self, *args): - res = [] - for content in self.contents: - if self._in(content, *args): - res.append(content) - return res - - def find(self, *args): - return MemCursor(self._find(*args)) - - def _aggregate(self, *args, **kwargs): - res = self.contents - print args - for arg in args[0]: - for k, v in arg.iteritems(): - if k == '$match': - res = self._find(v) - cursor = MemCursor(res) - for arg in args[0]: - for k, v in arg.iteritems(): - if k == '$sort': - cursor = cursor.sort(v) - elif k == '$skip': - cursor = cursor.skip(v) - elif k == '$limit': - cursor = cursor.limit(v) - return cursor - - def aggregate(self, *args, **kwargs): - return self._aggregate(*args, **kwargs) - - def _update(self, spec, document, check_keys=True): - updated = False - - if check_keys: - self._check_keys(document) - - for index in range(len(self.contents)): - content = self.contents[index] - if self._in(content, spec): - for k, v in document.iteritems(): - updated = True - content[k] = v - self.contents[index] = content - return updated - - def update(self, spec, document, check_keys=True): - return thread_execute(self._update, spec, document, check_keys) - - def _remove(self, spec_or_id=None): - if spec_or_id is None: - self.contents = [] - if not isinstance(spec_or_id, dict): - spec_or_id = {'_id': spec_or_id} - for index in range(len(self.contents)): - content = self.contents[index] - if self._in(content, spec_or_id): - del self.contents[index] - return True - return False - - def remove(self, spec_or_id=None): - return thread_execute(self._remove, spec_or_id) - - def clear(self): - self._remove() - - def _check_keys(self, doc): - for key in doc.keys(): - if '.' in key: - raise NameError('key {} must not contain .'.format(key)) - if key.startswith('$'): - raise NameError('key {} must not start with $'.format(key)) - if isinstance(doc.get(key), dict): - self._check_keys(doc.get(key)) - - -def __getattr__(name): - return globals()[name] - - -pods = MemDb('pods') -projects = MemDb('projects') -testcases = MemDb('testcases') -results = MemDb('results') -scenarios = MemDb('scenarios') -tokens = MemDb('tokens') -users = MemDb('users') diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/handlers/__init__.py b/utils/test/testapi/opnfv_testapi/tests/unit/handlers/__init__.py deleted file mode 100644 index e69de29bb..000000000 --- a/utils/test/testapi/opnfv_testapi/tests/unit/handlers/__init__.py +++ /dev/null diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/handlers/scenario-c1.json b/utils/test/testapi/opnfv_testapi/tests/unit/handlers/scenario-c1.json deleted file mode 100644 index 187802215..000000000 --- a/utils/test/testapi/opnfv_testapi/tests/unit/handlers/scenario-c1.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "nosdn-nofeature-ha", - "installers": - [ - { - "installer": "apex", - "versions": - [ - { - "owner": "Luke", - "version": "master", - "projects": - [ - { - "project": "functest", - "customs": [ "healthcheck", "vping_ssh"], - "scores": - [ - { - "date": "2017-01-08 22:46:44", - "score": "12/14" - } - - ], - "trust_indicators": [] - }, - { - "project": "yardstick", - "customs": [], - "scores": [], - "trust_indicators": [] - } - ] - } - ] - } - ] -} diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/handlers/scenario-c2.json b/utils/test/testapi/opnfv_testapi/tests/unit/handlers/scenario-c2.json deleted file mode 100644 index 980051c4f..000000000 --- a/utils/test/testapi/opnfv_testapi/tests/unit/handlers/scenario-c2.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "name": "odl_2-nofeature-ha", - "installers": - [ - { - "installer": "fuel", - "versions": - [ - { - "owner": "Lucky", - "version": "danube", - "projects": - [ - { - "project": "functest", - "customs": [ "healthcheck", "vping_ssh"], - "scores": [], - "trust_indicators": [ - { - "date": "2017-01-18 22:46:44", - "status": "silver" - } - - ] - }, - { - "project": "yardstick", - "customs": ["suite-a"], - "scores": [ - { - "date": "2017-01-08 22:46:44", - "score": "0/1" - } - ], - "trust_indicators": [ - { - "date": "2017-01-18 22:46:44", - "status": "gold" - } - ] - } - ] - }, - { - "owner": "Luke", - "version": "colorado", - "projects": - [ - { - "project": "functest", - "customs": [ "healthcheck", "vping_ssh"], - "scores": - [ - { - "date": "2017-01-09 22:46:44", - "score": "11/14" - } - - ], - "trust_indicators": [] - }, - { - "project": "yardstick", - "customs": [], - "scores": [], - "trust_indicators": [] - } - ] - } - ] - } - ] -} diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_base.py b/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_base.py deleted file mode 100644 index b7fabb994..000000000 --- a/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_base.py +++ /dev/null @@ -1,204 +0,0 @@ -############################################################################## -# Copyright (c) 2016 ZTE Corporation -# feng.xiaowei@zte.com.cn -# 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 datetime import datetime -import json -from os import path - -from bson.objectid import ObjectId -import mock -from tornado import testing - -from opnfv_testapi.models import base_models -from opnfv_testapi.models import pod_models -from opnfv_testapi.tests.unit import fake_pymongo - - -class TestBase(testing.AsyncHTTPTestCase): - headers = {'Content-Type': 'application/json; charset=UTF-8'} - - def setUp(self): - self._patch_server() - self.basePath = '' - self.create_res = base_models.CreateResponse - self.get_res = None - self.list_res = None - self.update_res = None - self.pod_d = pod_models.Pod(name='zte-pod1', - mode='virtual', - details='zte pod 1', - role='community-ci', - _id=str(ObjectId()), - owner='ValidUser', - create_date=str(datetime.now())) - self.pod_e = pod_models.Pod(name='zte-pod2', - mode='metal', - details='zte pod 2', - role='production-ci', - _id=str(ObjectId()), - owner='ValidUser', - create_date=str(datetime.now())) - self.req_d = None - self.req_e = None - self.addCleanup(self._clear) - super(TestBase, self).setUp() - fake_pymongo.users.insert({"user": "ValidUser", - 'email': 'validuser@lf.com', - 'fullname': 'Valid User', - 'groups': [ - 'opnfv-testapi-users', - 'opnfv-gerrit-functest-submitters', - 'opnfv-gerrit-qtip-contributors'] - }) - - def tearDown(self): - self.db_patcher.stop() - self.config_patcher.stop() - - def _patch_server(self): - import argparse - config = path.join(path.dirname(__file__), - '../../../../etc/config.ini') - self.config_patcher = mock.patch( - 'argparse.ArgumentParser.parse_known_args', - return_value=(argparse.Namespace(config_file=config), None)) - self.db_patcher = mock.patch('opnfv_testapi.db.api.DB', - fake_pymongo) - self.config_patcher.start() - self.db_patcher.start() - - def get_app(self): - from opnfv_testapi.cmd import server - return server.make_app() - - def create_d(self, *args): - return self.create(self.req_d, *args) - - def create_e(self, *args): - return self.create(self.req_e, *args) - - def create(self, req=None, *args): - return self.create_help(self.basePath, req, *args) - - def create_help(self, uri, req, *args): - return self.post_direct_url(self._update_uri(uri, *args), req) - - def post_direct_url(self, url, req): - if req and not isinstance(req, str) and hasattr(req, 'format'): - req = req.format() - res = self.fetch(url, - method='POST', - body=json.dumps(req), - headers=self.headers) - - return self._get_return(res, self.create_res) - - def get(self, *args): - res = self.fetch(self._get_uri(*args), - method='GET', - headers=self.headers) - - def inner(): - new_args, num = self._get_valid_args(*args) - return self.get_res \ - if num != self._need_arg_num(self.basePath) else self.list_res - return self._get_return(res, inner()) - - def query(self, query): - res = self.fetch(self._get_query_uri(query), - method='GET', - headers=self.headers) - return self._get_return(res, self.list_res) - - def update_direct_url(self, url, new=None): - if new and hasattr(new, 'format'): - new = new.format() - res = self.fetch(url, - method='PUT', - body=json.dumps(new), - headers=self.headers) - return self._get_return(res, self.update_res) - - def update(self, new=None, *args): - return self.update_direct_url(self._get_uri(*args), new) - - def delete_direct_url(self, url, body): - if body: - res = self.fetch(url, - method='DELETE', - body=json.dumps(body), - headers=self.headers, - allow_nonstandard_methods=True) - else: - res = self.fetch(url, - method='DELETE', - headers=self.headers) - - return res.code, res.body - - def delete(self, *args): - return self.delete_direct_url(self._get_uri(*args), None) - - @staticmethod - def _get_valid_args(*args): - new_args = tuple(['%s' % arg for arg in args if arg is not None]) - return new_args, len(new_args) - - def _need_arg_num(self, uri): - return uri.count('%s') - - def _get_query_uri(self, query): - return self.basePath + '?' + query if query else self.basePath - - def _get_uri(self, *args): - return self._update_uri(self.basePath, *args) - - def _update_uri(self, uri, *args): - r_uri = uri - new_args, num = self._get_valid_args(*args) - if num != self._need_arg_num(uri): - r_uri += '/%s' - - return r_uri % tuple(['%s' % arg for arg in new_args]) - - def _get_return(self, res, cls): - code = res.code - body = res.body - if body: - return code, self._get_return_body(code, body, cls) - else: - return code, None - - @staticmethod - def _get_return_body(code, body, cls): - return cls.from_dict(json.loads(body)) if code < 300 and cls else body - - def assert_href(self, body): - self.assertIn(self.basePath, body.href) - - def assert_create_body(self, body, req=None, *args): - import inspect - if not req: - req = self.req_d - resource_name = '' - if inspect.isclass(req): - resource_name = req.name - elif isinstance(req, dict): - resource_name = req['name'] - elif isinstance(req, str): - resource_name = json.loads(req)['name'] - new_args = args + tuple([resource_name]) - self.assertIn(self._get_uri(*new_args), body.href) - - @staticmethod - def _clear(): - fake_pymongo.pods.clear() - fake_pymongo.projects.clear() - fake_pymongo.testcases.clear() - fake_pymongo.results.clear() - fake_pymongo.scenarios.clear() diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_pod.py b/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_pod.py deleted file mode 100644 index 95ed8bac1..000000000 --- a/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_pod.py +++ /dev/null @@ -1,118 +0,0 @@ -############################################################################## -# Copyright (c) 2016 ZTE Corporation -# feng.xiaowei@zte.com.cn -# 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 httplib -import unittest - -from opnfv_testapi.common import message -from opnfv_testapi.models import pod_models -from opnfv_testapi.tests.unit import executor -from opnfv_testapi.tests.unit import fake_pymongo -from opnfv_testapi.tests.unit.handlers import test_base as base - - -class TestPodBase(base.TestBase): - def setUp(self): - super(TestPodBase, self).setUp() - self.get_res = pod_models.Pod - self.list_res = pod_models.Pods - self.basePath = '/api/v1/pods' - self.req_d = pod_models.PodCreateRequest(name=self.pod_d.name, - mode=self.pod_d.mode, - details=self.pod_d.details, - role=self.pod_d.role) - self.req_e = pod_models.PodCreateRequest(name=self.pod_e.name, - mode=self.pod_e.mode, - details=self.pod_e.details, - role=self.pod_e.role) - - def assert_get_body(self, pod, req=None): - if not req: - req = self.req_d - self.assertEqual(pod.owner, 'ValidUser') - self.assertEqual(pod.name, req.name) - self.assertEqual(pod.mode, req.mode) - self.assertEqual(pod.details, req.details) - self.assertEqual(pod.role, req.role) - self.assertIsNotNone(pod.creation_date) - self.assertIsNotNone(pod._id) - - -class TestPodCreate(TestPodBase): - @executor.create(httplib.BAD_REQUEST, message.not_login()) - def test_notlogin(self): - return self.req_d - - @executor.mock_invalid_lfid() - @executor.create(httplib.BAD_REQUEST, message.not_lfid()) - def test_invalidLfid(self): - return self.req_d - - @executor.mock_valid_lfid() - @executor.create(httplib.BAD_REQUEST, message.no_body()) - def test_withoutBody(self): - return None - - @executor.mock_valid_lfid() - @executor.create(httplib.BAD_REQUEST, message.missing('name')) - def test_emptyName(self): - return pod_models.PodCreateRequest('') - - @executor.mock_valid_lfid() - @executor.create(httplib.BAD_REQUEST, message.missing('name')) - def test_noneName(self): - return pod_models.PodCreateRequest(None) - - @executor.mock_valid_lfid() - @executor.create(httplib.OK, 'assert_create_body') - def test_success(self): - return self.req_d - - @executor.mock_valid_lfid() - @executor.create(httplib.FORBIDDEN, message.exist_base) - def test_alreadyExist(self): - fake_pymongo.pods.insert(self.pod_d.format()) - return self.req_d - - @executor.mock_valid_lfid() - @executor.create(httplib.FORBIDDEN, message.exist_base) - def test_alreadyExistCaseInsensitive(self): - fake_pymongo.pods.insert(self.pod_d.format()) - self.req_d.name = self.req_d.name.upper() - return self.req_d - - -class TestPodGet(TestPodBase): - def setUp(self): - super(TestPodGet, self).setUp() - fake_pymongo.pods.insert(self.pod_d.format()) - fake_pymongo.pods.insert(self.pod_e.format()) - - @executor.get(httplib.NOT_FOUND, message.not_found_base) - def test_notExist(self): - return 'notExist' - - @executor.get(httplib.OK, 'assert_get_body') - def test_getOne(self): - return self.pod_d.name - - @executor.get(httplib.OK, '_assert_list') - def test_list(self): - return None - - def _assert_list(self, body): - self.assertEqual(len(body.pods), 2) - for pod in body.pods: - if self.pod_d.name == pod.name: - self.assert_get_body(pod) - else: - self.assert_get_body(pod, self.pod_e) - - -if __name__ == '__main__': - unittest.main() diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_project.py b/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_project.py deleted file mode 100644 index 939cc0d07..000000000 --- a/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_project.py +++ /dev/null @@ -1,137 +0,0 @@ -import httplib -import unittest - -from opnfv_testapi.common import message -from opnfv_testapi.models import project_models -from opnfv_testapi.tests.unit import executor -from opnfv_testapi.tests.unit.handlers import test_base as base - - -class TestProjectBase(base.TestBase): - def setUp(self): - super(TestProjectBase, self).setUp() - self.req_d = project_models.ProjectCreateRequest('vping', - 'vping-ssh test') - self.req_e = project_models.ProjectCreateRequest('doctor', - 'doctor test') - self.get_res = project_models.Project - self.list_res = project_models.Projects - self.update_res = project_models.Project - self.basePath = '/api/v1/projects' - - def assert_body(self, project, req=None): - if not req: - req = self.req_d - self.assertEqual(project.name, req.name) - self.assertEqual(project.description, req.description) - self.assertIsNotNone(project._id) - self.assertIsNotNone(project.creation_date) - - -class TestProjectCreate(TestProjectBase): - @executor.create(httplib.BAD_REQUEST, message.no_body()) - def test_withoutBody(self): - return None - - @executor.create(httplib.BAD_REQUEST, message.missing('name')) - def test_emptyName(self): - return project_models.ProjectCreateRequest('') - - @executor.create(httplib.BAD_REQUEST, message.missing('name')) - def test_noneName(self): - return project_models.ProjectCreateRequest(None) - - @executor.create(httplib.OK, 'assert_create_body') - def test_success(self): - return self.req_d - - @executor.create(httplib.FORBIDDEN, message.exist_base) - def test_alreadyExist(self): - self.create_d() - return self.req_d - - -class TestProjectGet(TestProjectBase): - def setUp(self): - super(TestProjectGet, self).setUp() - self.create_d() - self.create_e() - - @executor.get(httplib.NOT_FOUND, message.not_found_base) - def test_notExist(self): - return 'notExist' - - @executor.get(httplib.OK, 'assert_body') - def test_getOne(self): - return self.req_d.name - - @executor.get(httplib.OK, '_assert_list') - def test_list(self): - return None - - def _assert_list(self, body): - for project in body.projects: - if self.req_d.name == project.name: - self.assert_body(project) - else: - self.assert_body(project, self.req_e) - - -class TestProjectUpdate(TestProjectBase): - def setUp(self): - super(TestProjectUpdate, self).setUp() - _, d_body = self.create_d() - _, get_res = self.get(self.req_d.name) - self.index_d = get_res._id - self.create_e() - - @executor.update(httplib.BAD_REQUEST, message.no_body()) - def test_withoutBody(self): - return None, 'noBody' - - @executor.update(httplib.NOT_FOUND, message.not_found_base) - def test_notFound(self): - return self.req_e, 'notFound' - - @executor.update(httplib.FORBIDDEN, message.exist_base) - def test_newNameExist(self): - return self.req_e, self.req_d.name - - @executor.update(httplib.FORBIDDEN, message.no_update()) - def test_noUpdate(self): - return self.req_d, self.req_d.name - - @executor.update(httplib.OK, '_assert_update') - def test_success(self): - req = project_models.ProjectUpdateRequest('newName', 'new description') - return req, self.req_d.name - - def _assert_update(self, req, body): - self.assertEqual(self.index_d, body._id) - self.assert_body(body, req) - _, new_body = self.get(req.name) - self.assertEqual(self.index_d, new_body._id) - self.assert_body(new_body, req) - - -class TestProjectDelete(TestProjectBase): - def setUp(self): - super(TestProjectDelete, self).setUp() - self.create_d() - - @executor.delete(httplib.NOT_FOUND, message.not_found_base) - def test_notFound(self): - return 'notFound' - - @executor.delete(httplib.OK, '_assert_delete') - def test_success(self): - return self.req_d.name - - def _assert_delete(self, body): - self.assertEqual(body, '') - code, body = self.get(self.req_d.name) - self.assertEqual(code, httplib.NOT_FOUND) - - -if __name__ == '__main__': - unittest.main() diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_result.py b/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_result.py deleted file mode 100644 index b9f9ede26..000000000 --- a/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_result.py +++ /dev/null @@ -1,413 +0,0 @@ -############################################################################## -# Copyright (c) 2016 ZTE Corporation -# feng.xiaowei@zte.com.cn -# 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 copy -from datetime import datetime -from datetime import timedelta -import httplib -import json -import urllib -import unittest - -from opnfv_testapi.common import message -from opnfv_testapi.models import project_models -from opnfv_testapi.models import result_models -from opnfv_testapi.models import testcase_models -from opnfv_testapi.tests.unit import executor -from opnfv_testapi.tests.unit import fake_pymongo -from opnfv_testapi.tests.unit.handlers import test_base as base - - -class Details(object): - def __init__(self, timestart=None, duration=None, status=None): - self.timestart = timestart - self.duration = duration - self.status = status - self.items = [{'item1': 1}, {'item2': 2}] - - def format(self): - return { - "timestart": self.timestart, - "duration": self.duration, - "status": self.status, - 'items': [{'item1': 1}, {'item2': 2}] - } - - @staticmethod - def from_dict(a_dict): - - if a_dict is None: - return None - - t = Details() - t.timestart = a_dict.get('timestart') - t.duration = a_dict.get('duration') - t.status = a_dict.get('status') - t.items = a_dict.get('items') - return t - - -class TestResultBase(base.TestBase): - def setUp(self): - super(TestResultBase, self).setUp() - self.pod = self.pod_d.name - self.project = 'functest' - self.case = 'vPing' - self.installer = 'fuel' - self.version = 'C' - self.build_tag = 'v3.0' - self.scenario = 'odl-l2' - self.criteria = 'PASS' - self.trust_indicator = result_models.TI(0.7) - self.start_date = str(datetime.now()) - self.stop_date = str(datetime.now() + timedelta(minutes=1)) - self.update_date = str(datetime.now() + timedelta(days=1)) - self.update_step = -0.05 - self.details = Details(timestart='0', duration='9s', status='OK') - self.req_d = result_models.ResultCreateRequest( - pod_name=self.pod, - project_name=self.project, - case_name=self.case, - installer=self.installer, - version=self.version, - start_date=self.start_date, - stop_date=self.stop_date, - details=self.details.format(), - build_tag=self.build_tag, - scenario=self.scenario, - criteria=self.criteria, - trust_indicator=self.trust_indicator) - self.get_res = result_models.TestResult - self.list_res = result_models.TestResults - self.update_res = result_models.TestResult - self.basePath = '/api/v1/results' - self.req_project = project_models.ProjectCreateRequest( - self.project, - 'vping test') - self.req_testcase = testcase_models.TestcaseCreateRequest( - self.case, - '/cases/vping', - 'vping-ssh test') - fake_pymongo.pods.insert(self.pod_d.format()) - self.create_help('/api/v1/projects', self.req_project) - self.create_help('/api/v1/projects/%s/cases', - self.req_testcase, - self.project) - - def assert_res(self, result, req=None): - if req is None: - req = self.req_d - self.assertEqual(result.pod_name, req.pod_name) - self.assertEqual(result.project_name, req.project_name) - self.assertEqual(result.case_name, req.case_name) - self.assertEqual(result.installer, req.installer) - self.assertEqual(result.version, req.version) - details_req = Details.from_dict(req.details) - details_res = Details.from_dict(result.details) - self.assertEqual(details_res.duration, details_req.duration) - self.assertEqual(details_res.timestart, details_req.timestart) - self.assertEqual(details_res.status, details_req.status) - self.assertEqual(details_res.items, details_req.items) - self.assertEqual(result.build_tag, req.build_tag) - self.assertEqual(result.scenario, req.scenario) - self.assertEqual(result.criteria, req.criteria) - self.assertEqual(result.start_date, req.start_date) - self.assertEqual(result.stop_date, req.stop_date) - self.assertIsNotNone(result._id) - ti = result.trust_indicator - self.assertEqual(ti.current, req.trust_indicator.current) - if ti.histories: - history = ti.histories[0] - self.assertEqual(history.date, self.update_date) - self.assertEqual(history.step, self.update_step) - - def _create_d(self): - _, res = self.create_d() - return res.href.split('/')[-1] - - def upload(self, req): - if req and not isinstance(req, str) and hasattr(req, 'format'): - req = req.format() - res = self.fetch(self.basePath + '/upload', - method='POST', - body=json.dumps(req), - headers=self.headers) - - return self._get_return(res, self.create_res) - - -class TestResultUpload(TestResultBase): - @executor.upload(httplib.BAD_REQUEST, message.key_error('file')) - def test_filenotfind(self): - return None - - -class TestResultCreate(TestResultBase): - @executor.create(httplib.BAD_REQUEST, message.no_body()) - def test_nobody(self): - return None - - @executor.create(httplib.BAD_REQUEST, message.missing('pod_name')) - def test_podNotProvided(self): - req = self.req_d - req.pod_name = None - return req - - @executor.create(httplib.BAD_REQUEST, message.missing('project_name')) - def test_projectNotProvided(self): - req = self.req_d - req.project_name = None - return req - - @executor.create(httplib.BAD_REQUEST, message.missing('case_name')) - def test_testcaseNotProvided(self): - req = self.req_d - req.case_name = None - return req - - @executor.create(httplib.BAD_REQUEST, - message.invalid_value('criteria', ['PASS', 'FAIL'])) - def test_invalid_criteria(self): - req = self.req_d - req.criteria = 'invalid' - return req - - @executor.create(httplib.FORBIDDEN, message.not_found_base) - def test_noPod(self): - req = self.req_d - req.pod_name = 'notExistPod' - return req - - @executor.create(httplib.FORBIDDEN, message.not_found_base) - def test_noProject(self): - req = self.req_d - req.project_name = 'notExistProject' - return req - - @executor.create(httplib.FORBIDDEN, message.not_found_base) - def test_noTestcase(self): - req = self.req_d - req.case_name = 'notExistTestcase' - return req - - @executor.create(httplib.OK, 'assert_href') - def test_success(self): - return self.req_d - - @executor.create(httplib.OK, 'assert_href') - def test_key_with_doc(self): - req = copy.deepcopy(self.req_d) - req.details = {'1.name': 'dot_name'} - return req - - @executor.create(httplib.OK, '_assert_no_ti') - def test_no_ti(self): - req = result_models.ResultCreateRequest(pod_name=self.pod, - project_name=self.project, - case_name=self.case, - installer=self.installer, - version=self.version, - start_date=self.start_date, - stop_date=self.stop_date, - details=self.details.format(), - build_tag=self.build_tag, - scenario=self.scenario, - criteria=self.criteria) - self.actual_req = req - return req - - def _assert_no_ti(self, body): - _id = body.href.split('/')[-1] - code, body = self.get(_id) - self.assert_res(body, self.actual_req) - - -class TestResultGet(TestResultBase): - def setUp(self): - super(TestResultGet, self).setUp() - self.req_10d_before = self._create_changed_date(days=-10) - self.req_d_id = self._create_d() - self.req_10d_later = self._create_changed_date(days=10) - - @executor.get(httplib.OK, 'assert_res') - def test_getOne(self): - return self.req_d_id - - @executor.query(httplib.OK, '_query_success', 3) - def test_queryPod(self): - return self._set_query('pod') - - @executor.query(httplib.OK, '_query_success', 3) - def test_queryProject(self): - return self._set_query('project') - - @executor.query(httplib.OK, '_query_success', 3) - def test_queryTestcase(self): - return self._set_query('case') - - @executor.query(httplib.OK, '_query_success', 3) - def test_queryVersion(self): - return self._set_query('version') - - @executor.query(httplib.OK, '_query_success', 3) - def test_queryInstaller(self): - return self._set_query('installer') - - @executor.query(httplib.OK, '_query_success', 3) - def test_queryBuildTag(self): - return self._set_query('build_tag') - - @executor.query(httplib.OK, '_query_success', 3) - def test_queryScenario(self): - return self._set_query('scenario') - - @executor.query(httplib.OK, '_query_success', 3) - def test_queryTrustIndicator(self): - return self._set_query('trust_indicator') - - @executor.query(httplib.OK, '_query_success', 3) - def test_queryCriteria(self): - return self._set_query('criteria') - - @executor.query(httplib.BAD_REQUEST, message.must_int('period')) - def test_queryPeriodNotInt(self): - return self._set_query(period='a') - - @executor.query(httplib.OK, '_query_period_one', 1) - def test_queryPeriodSuccess(self): - return self._set_query(period=5) - - @executor.query(httplib.BAD_REQUEST, message.must_int('last')) - def test_queryLastNotInt(self): - return self._set_query(last='a') - - @executor.query(httplib.OK, '_query_last_one', 1) - def test_queryLast(self): - return self._set_query(last=1) - - @executor.query(httplib.OK, '_query_success', 4) - def test_queryPublic(self): - self._create_public_data() - return self._set_query() - - @executor.query(httplib.OK, '_query_success', 1) - def test_queryPrivate(self): - self._create_private_data() - return self._set_query(public='false') - - @executor.query(httplib.OK, '_query_period_one', 1) - def test_combination(self): - return self._set_query('pod', - 'project', - 'case', - 'version', - 'installer', - 'build_tag', - 'scenario', - 'trust_indicator', - 'criteria', - period=5) - - @executor.query(httplib.OK, '_query_success', 0) - def test_notFound(self): - return self._set_query('project', - 'case', - 'version', - 'installer', - 'build_tag', - 'scenario', - 'trust_indicator', - 'criteria', - pod='notExistPod', - period=1) - - @executor.query(httplib.OK, '_query_success', 1) - def test_filterErrorStartdate(self): - self._create_error_start_date(None) - self._create_error_start_date('None') - self._create_error_start_date('null') - self._create_error_start_date('') - return self._set_query(period=5) - - def _query_success(self, body, number): - self.assertEqual(number, len(body.results)) - - def _query_last_one(self, body, number): - self.assertEqual(number, len(body.results)) - self.assert_res(body.results[0], self.req_10d_later) - - def _query_period_one(self, body, number): - self.assertEqual(number, len(body.results)) - self.assert_res(body.results[0], self.req_d) - - def _create_error_start_date(self, start_date): - req = copy.deepcopy(self.req_d) - req.start_date = start_date - self.create(req) - return req - - def _create_changed_date(self, **kwargs): - req = copy.deepcopy(self.req_d) - req.start_date = datetime.now() + timedelta(**kwargs) - req.stop_date = str(req.start_date + timedelta(minutes=10)) - req.start_date = str(req.start_date) - self.create(req) - return req - - def _create_public_data(self, **kwargs): - req = copy.deepcopy(self.req_d) - req.public = 'true' - self.create(req) - return req - - def _create_private_data(self, **kwargs): - req = copy.deepcopy(self.req_d) - req.public = 'false' - self.create(req) - return req - - def _set_query(self, *args, **kwargs): - def get_value(arg): - return self.__getattribute__(arg) \ - if arg != 'trust_indicator' else self.trust_indicator.current - query = [] - for arg in args: - query.append((arg, get_value(arg))) - for k, v in kwargs.iteritems(): - query.append((k, v)) - return urllib.urlencode(query) - - -class TestResultUpdate(TestResultBase): - def setUp(self): - super(TestResultUpdate, self).setUp() - self.req_d_id = self._create_d() - - @executor.update(httplib.OK, '_assert_update_ti') - def test_success(self): - new_ti = copy.deepcopy(self.trust_indicator) - new_ti.current += self.update_step - new_ti.histories.append( - result_models.TIHistory(self.update_date, self.update_step)) - new_data = copy.deepcopy(self.req_d) - new_data.trust_indicator = new_ti - update = result_models.ResultUpdateRequest(trust_indicator=new_ti) - self.update_req = new_data - return update, self.req_d_id - - def _assert_update_ti(self, request, body): - ti = body.trust_indicator - self.assertEqual(ti.current, request.trust_indicator.current) - if ti.histories: - history = ti.histories[0] - self.assertEqual(history.date, self.update_date) - self.assertEqual(history.step, self.update_step) - - -if __name__ == '__main__': - unittest.main() diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_scenario.py b/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_scenario.py deleted file mode 100644 index de7777a83..000000000 --- a/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_scenario.py +++ /dev/null @@ -1,449 +0,0 @@ -import functools -import httplib -import json -import os - -from datetime import datetime - -from opnfv_testapi.common import message -import opnfv_testapi.models.scenario_models as models -from opnfv_testapi.tests.unit.handlers import test_base as base - - -def _none_default(check, default): - return check if check else default - - -class TestScenarioBase(base.TestBase): - def setUp(self): - super(TestScenarioBase, self).setUp() - self.get_res = models.Scenario - self.list_res = models.Scenarios - self.basePath = '/api/v1/scenarios' - self.req_d = self._load_request('scenario-c1.json') - self.req_2 = self._load_request('scenario-c2.json') - - def tearDown(self): - pass - - def assert_body(self, project, req=None): - pass - - @staticmethod - def _load_request(f_req): - abs_file = os.path.join(os.path.dirname(__file__), f_req) - with open(abs_file, 'r') as f: - loader = json.load(f) - f.close() - return loader - - def create_return_name(self, req): - _, res = self.create(req) - return res.href.split('/')[-1] - - def assert_res(self, code, scenario, req=None): - self.assertEqual(code, httplib.OK) - if req is None: - req = self.req_d - self.assertIsNotNone(scenario._id) - self.assertIsNotNone(scenario.creation_date) - self.assertEqual(scenario, models.Scenario.from_dict(req)) - - @staticmethod - def set_query(*args): - uri = '' - for arg in args: - uri += arg + '&' - return uri[0: -1] - - def get_and_assert(self, name): - code, body = self.get(name) - self.assert_res(code, body, self.req_d) - - -class TestScenarioCreate(TestScenarioBase): - def test_withoutBody(self): - (code, body) = self.create() - self.assertEqual(code, httplib.BAD_REQUEST) - - def test_emptyName(self): - req_empty = models.ScenarioCreateRequest('') - (code, body) = self.create(req_empty) - self.assertEqual(code, httplib.BAD_REQUEST) - self.assertIn(message.missing('name'), body) - - def test_noneName(self): - req_none = models.ScenarioCreateRequest(None) - (code, body) = self.create(req_none) - self.assertEqual(code, httplib.BAD_REQUEST) - self.assertIn(message.missing('name'), body) - - def test_success(self): - (code, body) = self.create_d() - self.assertEqual(code, httplib.OK) - self.assert_create_body(body) - - def test_alreadyExist(self): - self.create_d() - (code, body) = self.create_d() - self.assertEqual(code, httplib.FORBIDDEN) - self.assertIn(message.exist_base, body) - - -class TestScenarioGet(TestScenarioBase): - def setUp(self): - super(TestScenarioGet, self).setUp() - self.scenario_1 = self.create_return_name(self.req_d) - self.scenario_2 = self.create_return_name(self.req_2) - - def test_getByName(self): - self.get_and_assert(self.scenario_1) - - def test_getAll(self): - self._query_and_assert(query=None, reqs=[self.req_d, self.req_2]) - - def test_queryName(self): - query = self.set_query('name=nosdn-nofeature-ha') - self._query_and_assert(query, reqs=[self.req_d]) - - def test_queryInstaller(self): - query = self.set_query('installer=apex') - self._query_and_assert(query, reqs=[self.req_d]) - - def test_queryVersion(self): - query = self.set_query('version=master') - self._query_and_assert(query, reqs=[self.req_d]) - - def test_queryProject(self): - query = self.set_query('project=functest') - self._query_and_assert(query, reqs=[self.req_d, self.req_2]) - - # close due to random fail, open again after solve it in another patch - # def test_queryCombination(self): - # query = self._set_query('name=nosdn-nofeature-ha', - # 'installer=apex', - # 'version=master', - # 'project=functest') - # - # self._query_and_assert(query, reqs=[self.req_d]) - - def _query_and_assert(self, query, found=True, reqs=None): - code, body = self.query(query) - if not found: - self.assertEqual(code, httplib.OK) - self.assertEqual(0, len(body.scenarios)) - else: - self.assertEqual(len(reqs), len(body.scenarios)) - for req in reqs: - for scenario in body.scenarios: - if req['name'] == scenario.name: - self.assert_res(code, scenario, req) - - -class TestScenarioDelete(TestScenarioBase): - def test_notFound(self): - code, body = self.delete('notFound') - self.assertEqual(code, httplib.NOT_FOUND) - - def test_success(self): - scenario = self.create_return_name(self.req_d) - code, _ = self.delete(scenario) - self.assertEqual(code, httplib.OK) - code, _ = self.get(scenario) - self.assertEqual(code, httplib.NOT_FOUND) - - -class TestScenarioUpdate(TestScenarioBase): - def setUp(self): - super(TestScenarioUpdate, self).setUp() - self.scenario = self.create_return_name(self.req_d) - self.scenario_2 = self.create_return_name(self.req_2) - self.update_url = '' - self.scenario_url = '/api/v1/scenarios/{}'.format(self.scenario) - self.installer = self.req_d['installers'][0]['installer'] - self.version = self.req_d['installers'][0]['versions'][0]['version'] - self.locate_project = 'installer={}&version={}&project={}'.format( - self.installer, - self.version, - 'functest') - - def update_url_fixture(item): - def _update_url_fixture(xstep): - def wrapper(self, *args, **kwargs): - self.update_url = '{}/{}'.format(self.scenario_url, item) - locator = None - if item in ['projects', 'owner']: - locator = 'installer={}&version={}'.format( - self.installer, - self.version) - elif item in ['versions']: - locator = 'installer={}'.format( - self.installer) - elif item in ['rename']: - self.update_url = self.scenario_url - - if locator: - self.update_url = '{}?{}'.format(self.update_url, locator) - - xstep(self, *args, **kwargs) - return wrapper - return _update_url_fixture - - def update_partial(operate, expected): - def _update_partial(set_update): - @functools.wraps(set_update) - def wrapper(self): - update = set_update(self) - code, body = getattr(self, operate)(update) - getattr(self, expected)(code) - return wrapper - return _update_partial - - @update_partial('_add', '_success') - def test_addScore(self): - add = models.ScenarioScore(date=str(datetime.now()), score='11/12') - projects = self.req_d['installers'][0]['versions'][0]['projects'] - functest = filter(lambda f: f['project'] == 'functest', projects)[0] - functest['scores'].append(add.format()) - self.update_url = '{}/scores?{}'.format(self.scenario_url, - self.locate_project) - - return add - - @update_partial('_add', '_success') - def test_addTrustIndicator(self): - add = models.ScenarioTI(date=str(datetime.now()), status='gold') - projects = self.req_d['installers'][0]['versions'][0]['projects'] - functest = filter(lambda f: f['project'] == 'functest', projects)[0] - functest['trust_indicators'].append(add.format()) - self.update_url = '{}/trust_indicators?{}'.format(self.scenario_url, - self.locate_project) - - return add - - @update_partial('_add', '_success') - def test_addCustoms(self): - adds = ['odl', 'parser', 'vping_ssh'] - projects = self.req_d['installers'][0]['versions'][0]['projects'] - functest = filter(lambda f: f['project'] == 'functest', projects)[0] - functest['customs'] = list(set(functest['customs'] + adds)) - self.update_url = '{}/customs?{}'.format(self.scenario_url, - self.locate_project) - return adds - - @update_partial('_update', '_success') - def test_updateCustoms(self): - updates = ['odl', 'parser', 'vping_ssh'] - projects = self.req_d['installers'][0]['versions'][0]['projects'] - functest = filter(lambda f: f['project'] == 'functest', projects)[0] - functest['customs'] = updates - self.update_url = '{}/customs?{}'.format(self.scenario_url, - self.locate_project) - - return updates - - @update_partial('_delete', '_success') - def test_deleteCustoms(self): - deletes = ['vping_ssh'] - projects = self.req_d['installers'][0]['versions'][0]['projects'] - functest = filter(lambda f: f['project'] == 'functest', projects)[0] - functest['customs'] = ['healthcheck'] - self.update_url = '{}/customs?{}'.format(self.scenario_url, - self.locate_project) - - return deletes - - @update_url_fixture('projects') - @update_partial('_add', '_success') - def test_addProjects_succ(self): - add = models.ScenarioProject(project='qtip').format() - self.req_d['installers'][0]['versions'][0]['projects'].append(add) - return [add] - - @update_url_fixture('projects') - @update_partial('_add', '_conflict') - def test_addProjects_already_exist(self): - add = models.ScenarioProject(project='functest').format() - return [add] - - @update_url_fixture('projects') - @update_partial('_add', '_bad_request') - def test_addProjects_bad_schema(self): - add = models.ScenarioProject(project='functest').format() - add['score'] = None - return [add] - - @update_url_fixture('projects') - @update_partial('_update', '_success') - def test_updateProjects_succ(self): - update = models.ScenarioProject(project='qtip').format() - self.req_d['installers'][0]['versions'][0]['projects'] = [update] - return [update] - - @update_url_fixture('projects') - @update_partial('_update', '_conflict') - def test_updateProjects_duplicated(self): - update = models.ScenarioProject(project='qtip').format() - return [update, update] - - @update_url_fixture('projects') - @update_partial('_update', '_bad_request') - def test_updateProjects_bad_schema(self): - update = models.ScenarioProject(project='functest').format() - update['score'] = None - return [update] - - @update_url_fixture('projects') - @update_partial('_delete', '_success') - def test_deleteProjects(self): - deletes = ['functest'] - projects = self.req_d['installers'][0]['versions'][0]['projects'] - self.req_d['installers'][0]['versions'][0]['projects'] = filter( - lambda f: f['project'] != 'functest', - projects) - return deletes - - @update_url_fixture('owner') - @update_partial('_update', '_success') - def test_changeOwner(self): - new_owner = 'new_owner' - update = models.ScenarioChangeOwnerRequest(new_owner).format() - self.req_d['installers'][0]['versions'][0]['owner'] = new_owner - return update - - @update_url_fixture('versions') - @update_partial('_add', '_success') - def test_addVersions_succ(self): - add = models.ScenarioVersion(version='Euphrates').format() - self.req_d['installers'][0]['versions'].append(add) - return [add] - - @update_url_fixture('versions') - @update_partial('_add', '_conflict') - def test_addVersions_already_exist(self): - add = models.ScenarioVersion(version='master').format() - return [add] - - @update_url_fixture('versions') - @update_partial('_add', '_bad_request') - def test_addVersions_bad_schema(self): - add = models.ScenarioVersion(version='euphrates').format() - add['notexist'] = None - return [add] - - @update_url_fixture('versions') - @update_partial('_update', '_success') - def test_updateVersions_succ(self): - update = models.ScenarioVersion(version='euphrates').format() - self.req_d['installers'][0]['versions'] = [update] - return [update] - - @update_url_fixture('versions') - @update_partial('_update', '_conflict') - def test_updateVersions_duplicated(self): - update = models.ScenarioVersion(version='euphrates').format() - return [update, update] - - @update_url_fixture('versions') - @update_partial('_update', '_bad_request') - def test_updateVersions_bad_schema(self): - update = models.ScenarioVersion(version='euphrates').format() - update['not_owner'] = 'Iam' - return [update] - - @update_url_fixture('versions') - @update_partial('_delete', '_success') - def test_deleteVersions(self): - deletes = ['master'] - versions = self.req_d['installers'][0]['versions'] - self.req_d['installers'][0]['versions'] = filter( - lambda f: f['version'] != 'master', - versions) - return deletes - - @update_url_fixture('installers') - @update_partial('_add', '_success') - def test_addInstallers_succ(self): - add = models.ScenarioInstaller(installer='daisy').format() - self.req_d['installers'].append(add) - return [add] - - @update_url_fixture('installers') - @update_partial('_add', '_conflict') - def test_addInstallers_already_exist(self): - add = models.ScenarioInstaller(installer='apex').format() - return [add] - - @update_url_fixture('installers') - @update_partial('_add', '_bad_request') - def test_addInstallers_bad_schema(self): - add = models.ScenarioInstaller(installer='daisy').format() - add['not_exist'] = 'not_exist' - return [add] - - @update_url_fixture('installers') - @update_partial('_update', '_success') - def test_updateInstallers_succ(self): - update = models.ScenarioInstaller(installer='daisy').format() - self.req_d['installers'] = [update] - return [update] - - @update_url_fixture('installers') - @update_partial('_update', '_conflict') - def test_updateInstallers_duplicated(self): - update = models.ScenarioInstaller(installer='daisy').format() - return [update, update] - - @update_url_fixture('installers') - @update_partial('_update', '_bad_request') - def test_updateInstallers_bad_schema(self): - update = models.ScenarioInstaller(installer='daisy').format() - update['not_exist'] = 'not_exist' - return [update] - - @update_url_fixture('installers') - @update_partial('_delete', '_success') - def test_deleteInstallers(self): - deletes = ['apex'] - installers = self.req_d['installers'] - self.req_d['installers'] = filter( - lambda f: f['installer'] != 'apex', - installers) - return deletes - - @update_url_fixture('rename') - @update_partial('_update', '_success') - def test_renameScenario(self): - new_name = 'new_scenario_name' - update = models.ScenarioUpdateRequest(name=new_name) - self.req_d['name'] = new_name - return update - - @update_url_fixture('rename') - @update_partial('_update', '_forbidden') - def test_renameScenario_exist(self): - new_name = self.req_d['name'] - update = models.ScenarioUpdateRequest(name=new_name) - return update - - def _add(self, update_req): - return self.post_direct_url(self.update_url, update_req) - - def _update(self, update_req): - return self.update_direct_url(self.update_url, update_req) - - def _delete(self, update_req): - return self.delete_direct_url(self.update_url, update_req) - - def _success(self, status): - self.assertEqual(status, httplib.OK) - self.get_and_assert(self.req_d['name']) - - def _forbidden(self, status): - self.assertEqual(status, httplib.FORBIDDEN) - - def _bad_request(self, status): - self.assertEqual(status, httplib.BAD_REQUEST) - - def _conflict(self, status): - self.assertEqual(status, httplib.CONFLICT) diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_testcase.py b/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_testcase.py deleted file mode 100644 index e4c668e7a..000000000 --- a/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_testcase.py +++ /dev/null @@ -1,201 +0,0 @@ -############################################################################## -# Copyright (c) 2016 ZTE Corporation -# feng.xiaowei@zte.com.cn -# 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 copy -import httplib -import unittest - -from opnfv_testapi.common import message -from opnfv_testapi.models import project_models -from opnfv_testapi.models import testcase_models -from opnfv_testapi.tests.unit import executor -from opnfv_testapi.tests.unit.handlers import test_base as base - - -class TestCaseBase(base.TestBase): - def setUp(self): - super(TestCaseBase, self).setUp() - self.req_d = testcase_models.TestcaseCreateRequest('vping_1', - '/cases/vping_1', - 'vping-ssh test') - self.req_e = testcase_models.TestcaseCreateRequest('doctor_1', - '/cases/doctor_1', - 'create doctor') - self.update_d = testcase_models.TestcaseUpdateRequest('vping_1', - 'vping-ssh test', - 'functest') - self.update_e = testcase_models.TestcaseUpdateRequest('doctor_1', - 'create doctor', - 'functest') - self.get_res = testcase_models.Testcase - self.list_res = testcase_models.Testcases - self.update_res = testcase_models.Testcase - self.basePath = '/api/v1/projects/%s/cases' - self.create_project() - - def assert_body(self, case, req=None): - if not req: - req = self.req_d - self.assertEqual(case.name, req.name) - self.assertEqual(case.description, req.description) - self.assertEqual(case.url, req.url) - self.assertIsNotNone(case._id) - self.assertIsNotNone(case.creation_date) - - def assert_update_body(self, old, new, req=None): - if not req: - req = self.req_d - self.assertEqual(new.name, req.name) - self.assertEqual(new.description, req.description) - self.assertEqual(new.url, old.url) - self.assertIsNotNone(new._id) - self.assertIsNotNone(new.creation_date) - - def create_project(self): - req_p = project_models.ProjectCreateRequest('functest', - 'vping-ssh test') - self.create_help('/api/v1/projects', req_p) - self.project = req_p.name - - def create_d(self): - return super(TestCaseBase, self).create_d(self.project) - - def create_e(self): - return super(TestCaseBase, self).create_e(self.project) - - def get(self, case=None): - return super(TestCaseBase, self).get(self.project, case) - - def create(self, req=None, *args): - return super(TestCaseBase, self).create(req, self.project) - - def update(self, new=None, case=None): - return super(TestCaseBase, self).update(new, self.project, case) - - def delete(self, case): - return super(TestCaseBase, self).delete(self.project, case) - - -class TestCaseCreate(TestCaseBase): - @executor.create(httplib.BAD_REQUEST, message.no_body()) - def test_noBody(self): - return None - - @executor.create(httplib.FORBIDDEN, message.not_found_base) - def test_noProject(self): - self.project = 'noProject' - return self.req_d - - @executor.create(httplib.BAD_REQUEST, message.missing('name')) - def test_emptyName(self): - req_empty = testcase_models.TestcaseCreateRequest('') - return req_empty - - @executor.create(httplib.BAD_REQUEST, message.missing('name')) - def test_noneName(self): - req_none = testcase_models.TestcaseCreateRequest(None) - return req_none - - @executor.create(httplib.OK, '_assert_success') - def test_success(self): - return self.req_d - - def _assert_success(self, body): - self.assert_create_body(body, self.req_d, self.project) - - @executor.create(httplib.FORBIDDEN, message.exist_base) - def test_alreadyExist(self): - self.create_d() - return self.req_d - - -class TestCaseGet(TestCaseBase): - def setUp(self): - super(TestCaseGet, self).setUp() - self.create_d() - self.create_e() - - @executor.get(httplib.NOT_FOUND, message.not_found_base) - def test_notExist(self): - return 'notExist' - - @executor.get(httplib.OK, 'assert_body') - def test_getOne(self): - return self.req_d.name - - @executor.get(httplib.OK, '_list') - def test_list(self): - return None - - def _list(self, body): - for case in body.testcases: - if self.req_d.name == case.name: - self.assert_body(case) - else: - self.assert_body(case, self.req_e) - - -class TestCaseUpdate(TestCaseBase): - def setUp(self): - super(TestCaseUpdate, self).setUp() - self.create_d() - - @executor.update(httplib.BAD_REQUEST, message.no_body()) - def test_noBody(self): - return None, 'noBody' - - @executor.update(httplib.NOT_FOUND, message.not_found_base) - def test_notFound(self): - return self.update_e, 'notFound' - - @executor.update(httplib.FORBIDDEN, message.exist_base) - def test_newNameExist(self): - self.create_e() - return self.update_e, self.req_d.name - - @executor.update(httplib.FORBIDDEN, message.no_update()) - def test_noUpdate(self): - return self.update_d, self.req_d.name - - @executor.update(httplib.OK, '_update_success') - def test_success(self): - return self.update_e, self.req_d.name - - @executor.update(httplib.OK, '_update_success') - def test_with_dollar(self): - update = copy.deepcopy(self.update_d) - update.description = {'2. change': 'dollar change'} - return update, self.req_d.name - - def _update_success(self, request, body): - self.assert_update_body(self.req_d, body, request) - _, new_body = self.get(request.name) - self.assert_update_body(self.req_d, new_body, request) - - -class TestCaseDelete(TestCaseBase): - def setUp(self): - super(TestCaseDelete, self).setUp() - self.create_d() - - @executor.delete(httplib.NOT_FOUND, message.not_found_base) - def test_notFound(self): - return 'notFound' - - @executor.delete(httplib.OK, '_delete_success') - def test_success(self): - return self.req_d.name - - def _delete_success(self, body): - self.assertEqual(body, '') - code, body = self.get(self.req_d.name) - self.assertEqual(code, httplib.NOT_FOUND) - - -if __name__ == '__main__': - unittest.main() diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_token.py b/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_token.py deleted file mode 100644 index e8b746dfc..000000000 --- a/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_token.py +++ /dev/null @@ -1,52 +0,0 @@ -# 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 httplib -import unittest - -from tornado import web - -from opnfv_testapi.common import message -from opnfv_testapi.tests.unit import executor -from opnfv_testapi.tests.unit import fake_pymongo -from opnfv_testapi.tests.unit.handlers import test_result - - -class TestTokenCreateResult(test_result.TestResultBase): - def get_app(self): - from opnfv_testapi.router import url_mappings - return web.Application( - url_mappings.mappings, - db=fake_pymongo, - debug=True, - auth=True - ) - - def setUp(self): - super(TestTokenCreateResult, self).setUp() - fake_pymongo.tokens.insert({"access_token": "12345"}) - - @executor.create(httplib.FORBIDDEN, message.invalid_token()) - def test_resultCreateTokenInvalid(self): - self.headers['X-Auth-Token'] = '1234' - return self.req_d - - @executor.create(httplib.UNAUTHORIZED, message.unauthorized()) - def test_resultCreateTokenUnauthorized(self): - if 'X-Auth-Token' in self.headers: - self.headers.pop('X-Auth-Token') - return self.req_d - - @executor.create(httplib.OK, '_create_success') - def test_resultCreateTokenSuccess(self): - self.headers['X-Auth-Token'] = '12345' - return self.req_d - - def _create_success(self, body): - self.assertIn('CreateResponse', str(type(body))) - - -if __name__ == '__main__': - unittest.main() diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_version.py b/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_version.py deleted file mode 100644 index 6ef810f0e..000000000 --- a/utils/test/testapi/opnfv_testapi/tests/unit/handlers/test_version.py +++ /dev/null @@ -1,36 +0,0 @@ -############################################################################## -# Copyright (c) 2016 ZTE Corporation -# feng.xiaowei@zte.com.cn -# 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 httplib -import unittest - -from opnfv_testapi.models import base_models -from opnfv_testapi.tests.unit import executor -from opnfv_testapi.tests.unit.handlers import test_base as base - - -class TestVersionBase(base.TestBase): - def setUp(self): - super(TestVersionBase, self).setUp() - self.list_res = base_models.Versions - self.basePath = '/versions' - - -class TestVersion(TestVersionBase): - @executor.get(httplib.OK, '_get_success') - def test_success(self): - return None - - def _get_success(self, body): - self.assertEqual(len(body.versions), 1) - self.assertEqual(body.versions[0].version, 'v1.0') - self.assertEqual(body.versions[0].description, 'basics') - - -if __name__ == '__main__': - unittest.main() diff --git a/utils/test/testapi/opnfv_testapi/tornado_swagger/README.md b/utils/test/testapi/opnfv_testapi/tornado_swagger/README.md deleted file mode 100644 index d815f2161..000000000 --- a/utils/test/testapi/opnfv_testapi/tornado_swagger/README.md +++ /dev/null @@ -1,273 +0,0 @@ -# tornado-swagger - -## What is tornado-swagger? -tornado is a wrapper for tornado which enables swagger-ui support. - -In essense, you just need to wrap the Api instance and add a few python decorators to -get full swagger support.http://swagger.io/ - - -## How to use: - - -```python -from tornado.web import RequestHandler, HTTPError -from tornado_swagger import swagger - -swagger.docs() - -# You may decorate your operation with @swagger.operation and use docs to inform information -class ItemNoParamHandler(GenericApiHandler): - @swagger.operation(nickname='create') - def post(self): - """ - @param body: create test results for a item. - @type body: L{Item} - @return 200: item is created. - @raise 400: invalid input - """ - -# Operations not decorated with @swagger.operation do not get added to the swagger docs - -class ItemNoParamHandler(GenericApiHandler): - def options(self): - """ - I'm not visible in the swagger docs - """ - pass - - -# Then you use swagger.Application instead of tornado.web.Application -# and do other operations as usual - -def make_app(): - return swagger.Application([ - (r"/items", ItemNoParamHandler), - (r"/items/([^/]+)", ItemHandler), - (r"/items/([^/]+)/cases/([^/]+)", ItemOptionParamHandler), - ]) - -# You define models like this: -@swagger.model -class Item: - """ - @descriptin: - This is an example of a model class that has parameters in its constructor - and the fields in the swagger spec are derived from the parameters to __init__. - @notes: - In this case we would have property1, property2 as required parameters - and property3 as optional parameter. - @property property3: Item decription - @ptype property3: L{PropertySubclass} - """ - def __init__(self, property1, property2=None): - self.property1 = property1 - self.property2 = property2 - -# Swagger json: - "models": { - "Item": { - "description": "A description...", - "id": "Item", - "required": [ - "property1", - ], - "properties": [ - "property1": { - "type": "string" - }, - "property2": { - "type": "string" - "default": null - } - ] - } - } - -# If you declare an __init__ method with meaningful arguments -# then those args could be used to deduce the swagger model fields. -# just as shown above - -# if you declare an @property in docs, this property property2 will also be used -# to deduce the swagger model fields -class Item: - """ - @property property3: Item description - """ - def __init__(self, property1, property2): - self.property1 = property1 - self.property2 = property2 - -# Swagger json: - "models": { - "Item": { - "description": "A description...", - "id": "Item", - "required": [ - "property1", - ], - "properties": [ - "property1": { - "type": "string" - }, - "property2": { - "type": "string" - } - "property3": { - "type": "string" - } - ] - } - } - -# if you declare an argument with @ptype, the type of this argument will be specified -# rather than the default 'string' -class Item: - """ - @ptype property3: L{PropertySubclass} - """ - def __init__(self, property1, property2, property3=None): - self.property1 = property1 - self.property2 = property2 - self.property3 = property3 - -# Swagger json: - "models": { - "Item": { - "description": "A description...", - "id": "Item", - "required": [ - "property1", - ], - "properties": [ - "property1": { - "type": "string" - }, - "property2": { - "type": "string" - }, - "property3": { - "type": "PropertySubclass" - "default": null - } - ] - } - } - -# if you want to declare an list property, you can do it like this: -class Item: - """ - @ptype property3: L{PropertySubclass} - @ptype property4: C{list} of L{PropertySubclass} - """ - def __init__(self, property1, property2, property3, property4=None): - self.property1 = property1 - self.property2 = property2 - self.property3 = property3 - self.property4 = property4 - -# Swagger json: - "models": { - "Item": { - "description": "A description...", - "id": "Item", - "required": [ - "property1", - ], - "properties": [ - "property1": { - "type": "string" - }, - "property2": { - "type": "string" - }, - "property3": { - "type": "PropertySubclass" - "default": null - }, - "property4": { - "default": null, - "items": { - "type": "PropertySubclass"}, - "type": "array" - } - } - ] - } - } - -# if it is a query: -class ItemQueryHandler(GenericApiHandler): - @swagger.operation(nickname='query') - def get(self): - """ - @param property1: - @type property1: L{string} - @in property1: query - @required property1: False - - @param property2: - @type property2: L{string} - @in property2: query - @required property2: True - @rtype: L{Item} - - @notes: GET /item?property1=1&property2=1 - """ - -# Swagger json: - "apis": [ - { - "operations": [ - { - "parameters": [ - { - "name": "property1", - "dataType": "string", - "paramType": "query", - "description": "" - }, - { - "name": "property2", - "dataType": "string", - "paramType": "query", - "required": true, - "description": "" - } - ], - "responseClass": "Item", - "notes": null, - "responseMessages": [], - "summary": null, - "httpMethod": "GET", - "nickname": "query" - } - ], - "path": "/item", - "description": null - }, - .... - ] -``` - -# Running and testing - -Now run your tornado app - -``` -python main.py -``` - -And visit: - -``` -curl http://ip:port/swagger/spec -``` - -access to web -``` -http://ip:port/swagger/spec.html -``` - -# Passing more metadata to swagger -customized arguments used in creating the 'swagger.docs' object will be supported later diff --git a/utils/test/testapi/opnfv_testapi/tornado_swagger/__init__.py b/utils/test/testapi/opnfv_testapi/tornado_swagger/__init__.py deleted file mode 100644 index 363bc388e..000000000 --- a/utils/test/testapi/opnfv_testapi/tornado_swagger/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -############################################################################## -# Copyright (c) 2016 ZTE Corporation -# feng.xiaowei@zte.com.cn -# 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 -############################################################################## diff --git a/utils/test/testapi/opnfv_testapi/tornado_swagger/handlers.py b/utils/test/testapi/opnfv_testapi/tornado_swagger/handlers.py deleted file mode 100644 index a04de07f7..000000000 --- a/utils/test/testapi/opnfv_testapi/tornado_swagger/handlers.py +++ /dev/null @@ -1,38 +0,0 @@ -############################################################################## -# Copyright (c) 2016 ZTE Corporation -# feng.xiaowei@zte.com.cn -# 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.web - -from opnfv_testapi.tornado_swagger import settings -from opnfv_testapi.tornado_swagger import views - - -def swagger_handlers(): - prefix = settings.docs_settings.get('swagger_prefix', '/swagger') - if prefix[-1] != '/': - prefix += '/' - - def _path(suffix): - return prefix + suffix - return [ - tornado.web.URLSpec( - _path(r'spec.html$'), - views.SwaggerUIHandler, - settings.docs_settings, - name=settings.API_DOCS_NAME), - tornado.web.URLSpec( - _path(r'models.json$'), - views.SwaggerResourcesHandler, - settings.docs_settings, - name=settings.RESOURCE_LISTING_NAME), - tornado.web.URLSpec( - _path(r'APIs$'), - views.SwaggerApiHandler, - settings.docs_settings, - name=settings.API_DECLARATION_NAME), - ] diff --git a/utils/test/testapi/opnfv_testapi/tornado_swagger/settings.py b/utils/test/testapi/opnfv_testapi/tornado_swagger/settings.py deleted file mode 100644 index 284226116..000000000 --- a/utils/test/testapi/opnfv_testapi/tornado_swagger/settings.py +++ /dev/null @@ -1,25 +0,0 @@ -############################################################################## -# Copyright (c) 2016 ZTE Corporation -# feng.xiaowei@zte.com.cn -# 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 -############################################################################## - -API_DOCS_NAME = 'swagger-api-docs' -RESOURCE_LISTING_NAME = 'swagger-resource-listing' -API_DECLARATION_NAME = 'swagger-api-declaration' - -docs_settings = { - 'base_url': '', - 'static_path': '', - 'swagger_prefix': '/swagger', - 'api_version': 'v1.0', - 'swagger_version': '1.2', - 'api_key': '', - 'enabled_methods': ['get', 'post', 'put', 'patch', 'delete'], - 'exclude_namespaces': [], -} - -models = [] diff --git a/utils/test/testapi/opnfv_testapi/tornado_swagger/swagger.py b/utils/test/testapi/opnfv_testapi/tornado_swagger/swagger.py deleted file mode 100644 index 6125c9554..000000000 --- a/utils/test/testapi/opnfv_testapi/tornado_swagger/swagger.py +++ /dev/null @@ -1,298 +0,0 @@ -############################################################################## -# Copyright (c) 2016 ZTE Corporation -# feng.xiaowei@zte.com.cn -# 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 HTMLParser import HTMLParser -from functools import wraps -import inspect - -import epydoc.markup -import tornado.web - -from opnfv_testapi.tornado_swagger import handlers -from opnfv_testapi.tornado_swagger import settings - - -class EpytextParser(HTMLParser): - a_text = False - - def __init__(self, tag): - HTMLParser.__init__(self) - self.tag = tag - self.data = None - - def handle_starttag(self, tag, attr): - if tag == self.tag: - self.a_text = True - - def handle_endtag(self, tag): - if tag == self.tag: - self.a_text = False - - def handle_data(self, data): - if self.a_text: - self.data = data - - def get_data(self): - return self.data - - -class DocParser(object): - def __init__(self): - self.notes = None - self.summary = None - self.responseClass = None - self.responseMessages = [] - self.params = {} - self.properties = {} - - def parse_docstring(self, text): - if text is None: - return - - errors = [] - doc = epydoc.markup.parse(text, markup='epytext', errors=errors) - _, fields = doc.split_fields(errors) - - for field in fields: - tag = field.tag() - arg = field.arg() - body = field.body() - self._get_parser(tag)(arg=arg, body=body) - return doc - - def _get_parser(self, tag): - parser = { - 'param': self._parse_param, - 'type': self._parse_type, - 'in': self._parse_in, - 'required': self._parse_required, - 'rtype': self._parse_rtype, - 'property': self._parse_property, - 'ptype': self._parse_ptype, - 'return': self._parse_return, - 'raise': self._parse_return, - 'notes': self._parse_notes, - 'description': self._parse_description, - } - return parser.get(tag, self._not_supported) - - def _parse_param(self, **kwargs): - arg = kwargs.get('arg', None) - body = self._get_body(**kwargs) - self.params.setdefault(arg, {}).update({ - 'name': arg, - 'description': body, - }) - - if 'paramType' not in self.params[arg]: - self.params[arg]['paramType'] = 'query' - - def _parse_type(self, **kwargs): - arg = kwargs.get('arg', None) - code = self._parse_epytext_para('code', **kwargs) - link = self._parse_epytext_para('link', **kwargs) - if code is None: - self.params.setdefault(arg, {}).update({ - 'name': arg, - 'type': link - }) - elif code == 'list': - self.params.setdefault(arg, {}).update({ - 'type': 'array', - 'items': {'type': link} - }) - - def _parse_in(self, **kwargs): - arg = kwargs.get('arg', None) - body = self._get_body(**kwargs) - self.params.setdefault(arg, {}).update({ - 'name': arg, - 'paramType': body - }) - - def _parse_required(self, **kwargs): - arg = kwargs.get('arg', None) - body = self._get_body(**kwargs) - self.params.setdefault(arg, {}).update({ - 'name': arg, - 'required': False if body in ['False', 'false'] else True - }) - - def _parse_rtype(self, **kwargs): - body = self._get_body(**kwargs) - self.responseClass = body - - def _parse_property(self, **kwargs): - arg = kwargs.get('arg', None) - self.properties.setdefault(arg, {}).update({ - 'type': 'string' - }) - - def _parse_ptype(self, **kwargs): - arg = kwargs.get('arg', None) - code = self._parse_epytext_para('code', **kwargs) - link = self._parse_epytext_para('link', **kwargs) - if code is None: - self.properties.setdefault(arg, {}).update({ - 'type': link - }) - elif code == 'list': - self.properties.setdefault(arg, {}).update({ - 'type': 'array', - 'items': {'type': link} - }) - - def _parse_return(self, **kwargs): - arg = kwargs.get('arg', None) - body = self._get_body(**kwargs) - self.responseMessages.append({ - 'code': arg, - 'message': body - }) - - def _parse_notes(self, **kwargs): - body = self._get_body(**kwargs) - self.notes = self._sanitize_doc(body) - - def _parse_description(self, **kwargs): - body = self._get_body(**kwargs) - self.summary = self._sanitize_doc(body) - - def _not_supported(self, **kwargs): - pass - - @staticmethod - def _sanitize_doc(comment): - return comment.replace('\n', '<br/>') if comment else comment - - @staticmethod - def _get_body(**kwargs): - body = kwargs.get('body', None) - return body.to_plaintext(None).strip() if body else body - - @staticmethod - def _parse_epytext_para(tag, **kwargs): - def _parse_epytext(tag, body): - epytextParser = EpytextParser(tag) - epytextParser.feed(str(body)) - data = epytextParser.get_data() - epytextParser.close() - return data - - body = kwargs.get('body', None) - return _parse_epytext(tag, body) if body else body - - -class model(DocParser): - def __init__(self, *args, **kwargs): - super(model, self).__init__() - self.args = args - self.kwargs = kwargs - self.required = [] - self.cls = None - - def __call__(self, *args): - if self.cls: - return self.cls - - cls = args[0] - self._parse_model(cls) - - return cls - - def _parse_model(self, cls): - self.id = cls.__name__ - self.cls = cls - if '__init__' in dir(cls): - self._parse_args(cls.__init__) - self.parse_docstring(inspect.getdoc(cls)) - settings.models.append(self) - - def _parse_args(self, func): - argspec = inspect.getargspec(func) - argspec.args.remove("self") - defaults = {} - if argspec.defaults: - defaults = list(zip(argspec.args[-len(argspec.defaults):], - argspec.defaults)) - required_args_count = len(argspec.args) - len(defaults) - for arg in argspec.args[:required_args_count]: - self.required.append(arg) - self.properties.setdefault(arg, {'type': 'string'}) - for arg, default in defaults: - self.properties.setdefault(arg, { - 'type': 'string', - "default": default - }) - - -class operation(DocParser): - def __init__(self, nickname='apis', **kwds): - super(operation, self).__init__() - self.nickname = nickname - self.func = None - self.func_args = [] - self.kwds = kwds - - def __call__(self, *args, **kwds): - if self.func: - return self.func(*args, **kwds) - - func = args[0] - self._parse_operation(func) - - @wraps(func) - def __wrapper__(*in_args, **in_kwds): - return self.func(*in_args, **in_kwds) - - __wrapper__.rest_api = self - return __wrapper__ - - def _parse_operation(self, func): - self.func = func - - self.__name__ = func.__name__ - self._parse_args(func) - self.parse_docstring(inspect.getdoc(self.func)) - - def _parse_args(self, func): - argspec = inspect.getargspec(func) - argspec.args.remove("self") - - defaults = [] - if argspec.defaults: - defaults = argspec.args[-len(argspec.defaults):] - - for arg in argspec.args: - if arg in defaults: - required = False - else: - required = True - self.params.setdefault(arg, { - 'name': arg, - 'required': required, - 'paramType': 'path', - 'dataType': 'string' - }) - self.func_args = argspec.args - - -def docs(**opts): - settings.docs_settings.update(opts) - - -class Application(tornado.web.Application): - def __init__(self, app_handlers=None, - default_host="", - transforms=None, - **settings): - super(Application, self).__init__( - handlers.swagger_handlers() + app_handlers, - default_host, - transforms, - **settings) diff --git a/utils/test/testapi/opnfv_testapi/tornado_swagger/views.py b/utils/test/testapi/opnfv_testapi/tornado_swagger/views.py deleted file mode 100644 index 793999700..000000000 --- a/utils/test/testapi/opnfv_testapi/tornado_swagger/views.py +++ /dev/null @@ -1,134 +0,0 @@ -############################################################################## -# Copyright (c) 2016 ZTE Corporation -# feng.xiaowei@zte.com.cn -# 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 inspect -import json - -import tornado.template -import tornado.web - -from opnfv_testapi.tornado_swagger import settings - - -def json_dumps(obj, pretty=False): - return json.dumps(obj, - sort_keys=True, - indent=4, - separators=(',', ': ')) if pretty else json.dumps(obj) - - -class SwaggerUIHandler(tornado.web.RequestHandler): - def initialize(self, **kwargs): - self.static_path = kwargs.get('static_path') - self.base_url = kwargs.get('base_url') - - def get_template_path(self): - return self.static_path - - def get(self): - resource_url = self.reverse_url(settings.RESOURCE_LISTING_NAME) - discovery_url = self.base_url + resource_url - self.render('swagger/index.html', discovery_url=discovery_url) - - -class SwaggerResourcesHandler(tornado.web.RequestHandler): - def initialize(self, **kwargs): - self.api_version = kwargs.get('api_version') - self.swagger_version = kwargs.get('swagger_version') - self.base_url = kwargs.get('base_url') - self.exclude_namespaces = kwargs.get('exclude_namespaces') - - def get(self): - self.set_header('content-type', 'application/json') - resources = { - 'apiVersion': self.api_version, - 'swaggerVersion': self.swagger_version, - 'basePath': self.base_url, - 'apis': [{ - 'path': self.reverse_url(settings.API_DECLARATION_NAME), - 'description': 'Restful APIs Specification' - }] - } - - self.finish(json_dumps(resources, self.get_arguments('pretty'))) - - -class SwaggerApiHandler(tornado.web.RequestHandler): - def initialize(self, **kwargs): - self.api_version = kwargs.get('api_version') - self.swagger_version = kwargs.get('swagger_version') - self.base_url = kwargs.get('base_url') - - def get(self): - self.set_header('content-type', 'application/json') - apis = self.find_api(self.application.handlers) - if apis is None: - raise tornado.web.HTTPError(404) - - specs = { - 'apiVersion': self.api_version, - 'swaggerVersion': self.swagger_version, - 'basePath': self.base_url, - 'resourcePath': '/', - 'produces': ["application/json"], - 'apis': [self.__get_api_spec__(path, spec, operations) - for path, spec, operations in apis], - 'models': self.__get_models_spec(settings.models) - } - self.finish(json_dumps(specs, self.get_arguments('pretty'))) - - def __get_models_spec(self, models): - models_spec = {} - for model in models: - models_spec.setdefault(model.id, self.__get_model_spec(model)) - return models_spec - - @staticmethod - def __get_model_spec(model): - return { - 'description': model.summary, - 'id': model.id, - 'notes': model.notes, - 'properties': model.properties, - 'required': model.required - } - - @staticmethod - def __get_api_spec__(path, spec, operations): - return { - 'path': path, - 'description': spec.handler_class.__doc__, - 'operations': [{ - 'httpMethod': api.func.__name__.upper(), - 'nickname': api.nickname, - 'parameters': api.params.values(), - 'summary': api.summary, - 'notes': api.notes, - 'responseClass': api.responseClass, - 'responseMessages': api.responseMessages, - } for api in operations] - } - - @staticmethod - def find_api(host_handlers): - def get_path(url, args): - return url % tuple(['{%s}' % arg for arg in args]) - - def get_operations(cls): - return [member.rest_api - for (_, member) in inspect.getmembers(cls) - if hasattr(member, 'rest_api')] - - for host, handlers in host_handlers: - for spec in handlers: - for (_, mbr) in inspect.getmembers(spec.handler_class): - if inspect.ismethod(mbr) and hasattr(mbr, 'rest_api'): - path = get_path(spec._path, mbr.rest_api.func_args) - operations = get_operations(spec.handler_class) - yield path, spec, operations - break diff --git a/utils/test/testapi/opnfv_testapi/ui/about/about.html b/utils/test/testapi/opnfv_testapi/ui/about/about.html deleted file mode 100644 index 65860a8cc..000000000 --- a/utils/test/testapi/opnfv_testapi/ui/about/about.html +++ /dev/null @@ -1,32 +0,0 @@ -<h1>TestAPI Documentation</h1> - -<p>TestAPI is a source of tools for test results collection of OPNFV clouds.</p> -<p>To learn more about TestAPI, visit the links below.</p> - -<ol> - <li> - <a href="https://wiki.opnfv.org/pages/viewpage.action?pageId=2926452#testapi" - target="_blank" - </a> - <strong>About TestAPI</strong> - </li> - <li> - <a href="https://wiki.opnfv.org/pages/viewpage.action?pageId=6825128#how-to-declare-test-project-in-testapi" - target="_blank" - </a> - <strong>How do I declare project in TestAPI</strong> - </li> - <li> - <a href="https://#how-to-declare-test-case-in-testapi" - target="_blank" - </a> - <strong>How do I declare test case in TestAPI</strong> - </li> - <li> - <a href="https://wiki.opnfv.org/pages/viewpage.action?pageId=6825133#how-to-push-result-to-testapi" - target="_blank" - </a> - <strong>How do I push my results to TestAPI</strong> - </li> -</ol> - diff --git a/utils/test/testapi/opnfv_testapi/ui/auth-failure/authFailureController.js b/utils/test/testapi/opnfv_testapi/ui/auth-failure/authFailureController.js deleted file mode 100644 index 29d1d70fa..000000000 --- a/utils/test/testapi/opnfv_testapi/ui/auth-failure/authFailureController.js +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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. - */ - -(function () { - 'use strict'; - - angular - .module('testapiApp') - .controller('AuthFailureController', AuthFailureController); - - AuthFailureController.$inject = ['$location', '$state', 'raiseAlert']; - /** - * TestAPI Auth Failure Controller - * This controller handles messages from TestAPI API if user auth fails. - */ - function AuthFailureController($location, $state, raiseAlert) { - var ctrl = this; - ctrl.message = $location.search().message; - raiseAlert('danger', 'Authentication Failure:', ctrl.message); - $state.go('home'); - } -})(); diff --git a/utils/test/testapi/opnfv_testapi/ui/home/home.html b/utils/test/testapi/opnfv_testapi/ui/home/home.html deleted file mode 100644 index 47d747fd8..000000000 --- a/utils/test/testapi/opnfv_testapi/ui/home/home.html +++ /dev/null @@ -1,23 +0,0 @@ -<div class="jumbotron openstack-intro"> - <div class="pull-right right openstack-intro__logo"> - <img src="testapi-ui/assets/img/opnfv-logo.png" alt="OPNFV"> - </div> - <div class="pull-left left openstack-intro__content"> - <h1>Results Collection</h1> - <p>TestAPI is a source of tools for OPNFV test results collection</p> - </div> - <div class="clearfix"></div> -</div> - -<div class="row"> - <div class="col-lg-6"> - <h4>What is TestAPI?</h4> - <ul> - <li>Toolset for testing interoperability between OPNFV test projects.</li> - <li>Database backed website supporting collection and publication of - community test results for OPNFV.</li> - <li>User interface to display individual test run results.</li> - </ul> - </div> -</div> - diff --git a/utils/test/testapi/opnfv_testapi/ui/logout/logout.html b/utils/test/testapi/opnfv_testapi/ui/logout/logout.html deleted file mode 100644 index 38a5c3698..000000000 --- a/utils/test/testapi/opnfv_testapi/ui/logout/logout.html +++ /dev/null @@ -1 +0,0 @@ -<div cg-busy="{promise:ctrl.redirectWait,message:'Logging you out...'}"></div> diff --git a/utils/test/testapi/opnfv_testapi/ui/logout/logoutController.js b/utils/test/testapi/opnfv_testapi/ui/logout/logoutController.js deleted file mode 100644 index 1b6d78c63..000000000 --- a/utils/test/testapi/opnfv_testapi/ui/logout/logoutController.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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. - */ - -(function () { - 'use strict'; - - angular - .module('testapiApp') - .controller('LogoutController', LogoutController); - - LogoutController.$inject = [ - '$location', '$window', '$timeout' - ]; - - /** - * TestAPI Logout Controller - * This controller handles logging out. In order to fully logout, the - * openstackid_session cookie must also be removed. The way to do that - * is to have the user's browser make a request to the openstackid logout - * page. We do this by placing the logout link as the src for an html - * image. After some time, the user is redirected home. - */ - function LogoutController($location, $window, $timeout) { - var ctrl = this; - - ctrl.openid_logout_url = $location.search().openid_logout; - var img = new Image(0, 0); - img.src = ctrl.openid_logout_url; - ctrl.redirectWait = $timeout(function() { - $window.location.href = '/'; - }, 500); - } -})(); diff --git a/utils/test/testapi/opnfv_testapi/ui/pods/pods.html b/utils/test/testapi/opnfv_testapi/ui/pods/pods.html deleted file mode 100644 index 22f29347b..000000000 --- a/utils/test/testapi/opnfv_testapi/ui/pods/pods.html +++ /dev/null @@ -1,76 +0,0 @@ -<h3>Pods</h3> -<p>This page is used to create or query pods.<br> - Querying pods is open to everybody.<br> - But only login users are granted the privilege to create the new pod. -</p> - -<div class="row" style="margin-bottom:24px;"></div> - -<div class="pod-create" ng-class="{ 'hidden': ! auth.isAuthenticated }"> - <h4>Create</h4> - <div class="row"> - <div ng-repeat="require in ctrl.createRequirements"> - <div class="create-pod" style="margin-left:24px;"> - <p class="input-group"> - <label for="cpid">{{require.label|capitalize}}: </label> - <a ng-if="require.type == 'select'"> - <select dynamic-model="'ctrl.' + require.label" ng-options="option for option in require.selects"></select> - </a> - <a ng-if="require.type == 'text'"> - <input type="text" dynamic-model="'ctrl.' + require.label"/> - </a> - <a ng-if="require.type == 'textarea'"> - <textarea rows="2" cols="50" dynamic-model="'ctrl.' + require.label"> - </textarea> - </a> - </p> - </div> - </div> - - <div class="col-md-3" style="margin-top:12px; margin-left:8px;"> - <button type="submit" class="btn btn-primary" ng-click="ctrl.create()">Create</button> - </div> - </div> -</div> - -<div class="pods-filters" style="margin-top:36px;"> - <h4>Filters</h4> - <div class="row"> - <div class="col-md-3" style="margin-top:12px; margin-left:8px;"> - <button type="submit" class="btn btn-primary" ng-click="ctrl.update()">Filter</button> - <button type="submit" class="btn btn-primary btn-danger" ng-click="ctrl.clearFilters()">Clear</button> - </div> - </div> -</div> - -<div cg-busy="{promise:ctrl.authRequest,message:'Loading'}"></div> -<div cg-busy="{promise:ctrl.podsRequest,message:'Loading'}"></div> - -<div ng-show="ctrl.data" class="pods-table" style="margin-top:24px; margin-left:8px;"> - <table ng-data="ctrl.data.pods" ng-show="ctrl.data" class="table table-striped table-hover"> - <tbody> - <tr ng-repeat-start="(index, pod) in ctrl.data.pods"> - <td> - <a href="#" ng-click="showPod = !showPod">{{pod.name}}</a> - <div class="show-pod" ng-class="{ 'hidden': ! showPod }" style="margin-left:24px;"> - <p> - owner: {{pod.owner}}<br> - role: {{pod.role}}<br> - mode: {{pod.mode}}<br> - create_date: {{pod.creation_date}}<br> - details: {{pod.details}} - </p> - </div> - </td> - </tr> - <tr ng-repeat-end=> - </tr> - </tbody> - </table> -</div> -<br> -<div ng-show="ctrl.showError" class="alert alert-danger" role="alert"> - <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> - <span class="sr-only">Error:</span> - {{ctrl.error}} -</div> diff --git a/utils/test/testapi/opnfv_testapi/ui/pods/podsController.js b/utils/test/testapi/opnfv_testapi/ui/pods/podsController.js deleted file mode 100644 index 489fa8a8d..000000000 --- a/utils/test/testapi/opnfv_testapi/ui/pods/podsController.js +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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. - */ - -(function () { - 'use strict'; - - angular - .module('testapiApp') - .controller('PodsController', PodsController); - - PodsController.$inject = [ - '$scope', '$http', '$filter', '$state', 'testapiApiUrl','raiseAlert' - ]; - - /** - * TestAPI Pods Controller - * This controller is for the '/pods' page where a user can browse - * through pods declared in TestAPI. - */ - function PodsController($scope, $http, $filter, $state, testapiApiUrl, - raiseAlert) { - var ctrl = this; - ctrl.url = testapiApiUrl + '/pods'; - - ctrl.create = create; - ctrl.update = update; - ctrl.open = open; - ctrl.clearFilters = clearFilters; - - ctrl.roles = ['community-ci', 'production-ci']; - ctrl.modes = ['metal', 'virtual']; - ctrl.createRequirements = [ - {label: 'name', type: 'text', required: true}, - {label: 'mode', type: 'select', selects: ctrl.modes}, - {label: 'role', type: 'select', selects: ctrl.roles}, - {label: 'details', type: 'textarea', required: false} - ]; - - ctrl.name = ''; - ctrl.role = 'community-ci'; - ctrl.mode = 'metal'; - ctrl.details = ''; - - /** - * This is called when the date filter calendar is opened. It - * does some event handling, and sets a scope variable so the UI - * knows which calendar was opened. - * @param {Object} $event - The Event object - * @param {String} openVar - Tells which calendar was opened - */ - function open($event, openVar) { - $event.preventDefault(); - $event.stopPropagation(); - ctrl[openVar] = true; - } - - /** - * This function will clear all filters and update the results - * listing. - */ - function clearFilters() { - ctrl.update(); - } - - /** - * This will contact the TestAPI to create a new pod. - */ - function create() { - ctrl.showError = false; - - if(ctrl.name != ""){ - var pods_url = ctrl.url; - var body = { - name: ctrl.name, - mode: ctrl.mode, - role: ctrl.role, - details: ctrl.details - }; - ctrl.podsRequest = - $http.post(pods_url, body).error(function (data, status) { - ctrl.showError = true; - if(status == 403){ - ctrl.error = - 'Error creating the new pod from server: Pod\'s name already exists' - } - }); - } - else{ - ctrl.showError = true; - ctrl.error = 'Name is missing.' - } - } - - /** - * This will contact the TestAPI to get a listing of declared pods. - */ - function update() { - ctrl.showError = false; - ctrl.podsRequest = - $http.get(ctrl.url).success(function (data) { - ctrl.data = data; - }).error(function (error) { - ctrl.data = null; - ctrl.showError = true; - ctrl.error = - 'Error retrieving pods from server: ' + - angular.toJson(error); - }); - } - } -})(); diff --git a/utils/test/testapi/opnfv_testapi/ui/profile/importPubKeyModal.html b/utils/test/testapi/opnfv_testapi/ui/profile/importPubKeyModal.html deleted file mode 100644 index 0f55c27fd..000000000 --- a/utils/test/testapi/opnfv_testapi/ui/profile/importPubKeyModal.html +++ /dev/null @@ -1,27 +0,0 @@ -<div class="modal-header"> - <h4>Import Public Key</h4> - <p>Instructions for adding a public key and signature can be found - <a href="https://github.com/openstack/refstack/blob/master/doc/source/uploading_private_results.rst#generate-ssh-keys-locally" - target="_blank" - title="How to generate and upload SSH key and signature with testapi-client">here. - </a> - </p> -</div> -<div class="modal-body container-fluid"> - <div class="row"> - <div class="col-md-2">Public Key</div> - <div class="col-md-9 pull-right"> - <textarea type="text" rows="10" cols="42" ng-model="modal.raw_key" required></textarea> - </div> - </div> - <div class="row"> - <div class="col-md-2">Signature</div> - <div class="col-md-9 pull-right"> - <textarea type="text" rows="10" cols="42" ng-model="modal.self_signature" required></textarea> - </div> - </div> - <div class="modal-footer"> - <button class="btn btn-warning btn-sm" ng-click="modal.cancel()">Cancel</button> - <button type="button" class="btn btn-default btn-sm" ng-click="modal.importPubKey()">Import Public Key</button> - </div> -</div> diff --git a/utils/test/testapi/opnfv_testapi/ui/profile/profile.html b/utils/test/testapi/opnfv_testapi/ui/profile/profile.html deleted file mode 100644 index 763f5d120..000000000 --- a/utils/test/testapi/opnfv_testapi/ui/profile/profile.html +++ /dev/null @@ -1,44 +0,0 @@ -<h3>User profile</h3> -<div cg-busy="{promise:ctrl.authRequest,message:'Loading'}"></div> -<div> - <table class="table table-striped table-hover"> - <tbody> - <tr> <td>User</td> <td>{{auth.currentUser.user}}</td> </tr> - <tr> <td>Fullname</td> <td>{{auth.currentUser.fullname}}</td> </tr> - <tr> <td>Email</td> <td>{{auth.currentUser.email}}</td> </tr> - <tr> <td>Groups</td> - <td> - <div ng-repeat="group in auth.currentUser.groups"> - {{group}}</br> - </div> - </td> - </tr> - </tbody> - </table> -</div> -<div ng-show="ctrl.pubkeys"> - <div class="container-fluid"> - <div class="row"> - <div class="col-md-4"> - <h4>User Public Keys</h4> - </div> - <div class="col-md-2 pull-right"> - <button type="button" class="btn btn-default btn-sm" ng-click="ctrl.openImportPubKeyModal()"> - <span class="glyphicon glyphicon-plus"></span> Import Public Key - </button> - </div> - </div> - </div> - - <div> - <table class="table table-striped table-hover"> - <tbody> - <tr ng-repeat="pubKey in ctrl.pubkeys" ng-click="ctrl.openShowPubKeyModal(pubKey)"> - <td>{{pubKey.format}}</td> - <td>{{pubKey.shortKey}}</td> - <td>{{pubKey.comment}}</td> - </tr> - </tbody> - </table> - </div> -</div> diff --git a/utils/test/testapi/opnfv_testapi/ui/profile/profileController.js b/utils/test/testapi/opnfv_testapi/ui/profile/profileController.js deleted file mode 100644 index 5dbdf7b1a..000000000 --- a/utils/test/testapi/opnfv_testapi/ui/profile/profileController.js +++ /dev/null @@ -1,219 +0,0 @@ -/* - * - * 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. - */ - -(function () { - 'use strict'; - - angular - .module('testapiApp') - .factory('PubKeys', PubKeys); - - PubKeys.$inject = ['$resource', 'testapiApiUrl']; - - /** - * This is a provider for the user's uploaded public keys. - */ - function PubKeys($resource, testapiApiUrl) { - return $resource(testapiApiUrl + '/user/pubkeys/:id', null, null); - } - - angular - .module('testapiApp') - .controller('ProfileController', ProfileController); - - ProfileController.$inject = [ - '$scope', '$http', 'testapiApiUrl', 'PubKeys', - '$uibModal', 'raiseAlert', '$state' - ]; - - /** - * TestAPI Profile Controller - * This controller handles user's profile page, where a user can view - * account-specific information. - */ - function ProfileController($scope, $http, testapiApiUrl, - PubKeys, $uibModal, raiseAlert, $state) { - - var ctrl = this; - - ctrl.updatePubKeys = updatePubKeys; - ctrl.openImportPubKeyModal = openImportPubKeyModal; - ctrl.openShowPubKeyModal = openShowPubKeyModal; - - // Must be authenticated to view this page. - if (!$scope.auth.isAuthenticated) { - $state.go('home'); - } - - /** - * This function will fetch all the user's public keys from the - * server and store them in an array. - */ - function updatePubKeys() { - var keys = PubKeys.query(function() { - ctrl.pubkeys = []; - angular.forEach(keys, function (key) { - ctrl.pubkeys.push({ - 'resource': key, - 'format': key.format, - 'shortKey': [ - key.pubkey.slice(0, 10), - '.', - key.pubkey.slice(-10) - ].join('.'), - 'pubkey': key.pubkey, - 'comment': key.comment - }); - }); - }); - } - - /** - * This function will open the modal that will give the user a form - * for importing a public key. - */ - function openImportPubKeyModal() { - $uibModal.open({ - templateUrl: '/components/profile/importPubKeyModal.html', - backdrop: true, - windowClass: 'modal', - controller: 'ImportPubKeyModalController as modal' - }).result.finally(function() { - ctrl.updatePubKeys(); - }); - } - - /** - * This function will open the modal that will give the full - * information regarding a specific public key. - * @param {Object} pubKey resource - */ - function openShowPubKeyModal(pubKey) { - $uibModal.open({ - templateUrl: '/components/profile/showPubKeyModal.html', - backdrop: true, - windowClass: 'modal', - controller: 'ShowPubKeyModalController as modal', - resolve: { - pubKey: function() { - return pubKey; - } - } - }).result.finally(function() { - ctrl.updatePubKeys(); - }); - } - - ctrl.authRequest = $scope.auth.doSignCheck().then(ctrl.updatePubKeys); - } - - angular - .module('testapiApp') - .controller('ImportPubKeyModalController', ImportPubKeyModalController); - - ImportPubKeyModalController.$inject = [ - '$uibModalInstance', 'PubKeys', 'raiseAlert' - ]; - - /** - * Import Pub Key Modal Controller - * This controller is for the modal that appears if a user wants to import - * a public key. - */ - function ImportPubKeyModalController($uibModalInstance, - PubKeys, raiseAlert) { - - var ctrl = this; - - ctrl.importPubKey = importPubKey; - ctrl.cancel = cancel; - - /** - * This function will save a new public key resource to the API server. - */ - function importPubKey() { - var newPubKey = new PubKeys( - {raw_key: ctrl.raw_key, self_signature: ctrl.self_signature} - ); - newPubKey.$save( - function(newPubKey_) { - raiseAlert('success', '', 'Public key saved successfully'); - $uibModalInstance.close(newPubKey_); - }, - function(httpResp) { - raiseAlert('danger', - httpResp.statusText, httpResp.data.title); - ctrl.cancel(); - } - ); - } - - /** - * This function will dismiss the modal. - */ - function cancel() { - $uibModalInstance.dismiss('cancel'); - } - } - - angular - .module('testapiApp') - .controller('ShowPubKeyModalController', ShowPubKeyModalController); - - ShowPubKeyModalController.$inject = [ - '$uibModalInstance', 'raiseAlert', 'pubKey' - ]; - - /** - * Show Pub Key Modal Controller - * This controller is for the modal that appears if a user wants to see the - * full details of one of their public keys. - */ - function ShowPubKeyModalController($uibModalInstance, raiseAlert, pubKey) { - var ctrl = this; - - ctrl.deletePubKey = deletePubKey; - ctrl.cancel = cancel; - - ctrl.pubKey = pubKey.resource; - ctrl.rawKey = [pubKey.format, pubKey.pubkey, pubKey.comment].join('\n'); - - /** - * This function will delete a public key resource. - */ - function deletePubKey() { - ctrl.pubKey.$remove( - {id: ctrl.pubKey.id}, - function() { - raiseAlert('success', - '', 'Public key deleted successfully'); - $uibModalInstance.close(ctrl.pubKey.id); - }, - function(httpResp) { - raiseAlert('danger', - httpResp.statusText, httpResp.data.title); - ctrl.cancel(); - } - ); - } - - /** - * This method will dismiss the modal. - */ - function cancel() { - $uibModalInstance.dismiss('cancel'); - } - } -})(); diff --git a/utils/test/testapi/opnfv_testapi/ui/profile/showPubKeyModal.html b/utils/test/testapi/opnfv_testapi/ui/profile/showPubKeyModal.html deleted file mode 100644 index 5f63a5ef6..000000000 --- a/utils/test/testapi/opnfv_testapi/ui/profile/showPubKeyModal.html +++ /dev/null @@ -1,11 +0,0 @@ -<div class="modal-header"> - <h4>Public Key</h4> -</div> -<div class="modal-body container-fluid"> - <textarea type="text" rows="10" cols="67" readonly="readonly">{{modal.rawKey}}</textarea> - <div class="modal-footer"> - <button class="btn btn-warning" ng-click="modal.cancel()">Cancel</button> - <button type="button" class="btn btn-danger btn-sm" ng-click="modal.deletePubKey() " - confirm="Are you sure you want to delete this public key? You will lose management access to any test results signed with this key.">Delete</button> - </div> -</div> diff --git a/utils/test/testapi/opnfv_testapi/ui/results-report/partials/editTestModal.html b/utils/test/testapi/opnfv_testapi/ui/results-report/partials/editTestModal.html deleted file mode 100644 index 583c9b92b..000000000 --- a/utils/test/testapi/opnfv_testapi/ui/results-report/partials/editTestModal.html +++ /dev/null @@ -1,65 +0,0 @@ -<div class="modal-content"> - <div class="modal-header"> - <button type="button" class="close" aria-hidden="true" ng-click="modal.close()">×</button> - <h4>Edit Test Run Metadata</h4> - <p>Make changes to your test metadata.</p> - </div> - <div class="modal-body"> - <div class="form-group"> - <strong>Publicly Shared:</strong> - <select ng-model="modal.metaCopy.shared" - class="form-control"> - <option value="true">Yes</option> - <option value="">No</option> - </select> - <br /> - <strong>Associated Guideline:</strong> - <select ng-model="modal.metaCopy.guideline" - ng-options="o as o.slice(0, -5) for o in modal.versionList" - class="form-control"> - <option value="">None</option> - </select> - <br /> - <strong>Associated Target Program:</strong> - <select ng-model="modal.metaCopy.target" - class="form-control"> - <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> - <hr> - <strong>Associated Product:</strong> - <select ng-options="product as product.name for product in modal.products | arrayConverter | orderBy: 'name' track by product.id" - ng-model="modal.selectedProduct" - ng-change="modal.getProductVersions()" - class="form-control"> - <option value="">-- No Product --</option> - </select> - - <span ng-if="modal.productVersions.length"> - <strong>Product Version:</strong> - <select ng-options="version as version.version for version in modal.productVersions | orderBy: 'version' track by version.id" - ng-model="modal.selectedVersion" - class="form-control"> - </select> - - </span> - - </div> - <div ng-show="modal.showError" class="alert alert-danger" role="alert"> - <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> - <span class="sr-only">Error:</span> - {{modal.error}} - </div> - <div ng-show="modal.showSuccess" class="alert alert-success" role="success"> - <span class="glyphicon glyphicon-ok" aria-hidden="true"></span> - <span class="sr-only">Success:</span> - Changes saved successfully. - </div> - </div> - <div class="modal-footer"> - <button class="btn btn-primary" type="button" ng-click="modal.saveChanges()">Save Changes</button> - <button class="btn btn-primary" type="button" ng-click="modal.close()">Close</button> - </div> -</div> diff --git a/utils/test/testapi/opnfv_testapi/ui/results-report/partials/fullTestListModal.html b/utils/test/testapi/opnfv_testapi/ui/results-report/partials/fullTestListModal.html deleted file mode 100644 index 6db198b02..000000000 --- a/utils/test/testapi/opnfv_testapi/ui/results-report/partials/fullTestListModal.html +++ /dev/null @@ -1,13 +0,0 @@ -<div class="modal-content"> - <div class="modal-header"> - <h4>All Passed Tests ({{modal.tests.length}})</h4> - </div> - <div class="modal-body tests-modal-content"> - <div class="form-group"> - <textarea class="form-control" rows="20" id="tests" wrap="off">{{modal.getTestListString()}}</textarea> - </div> - </div> - <div class="modal-footer"> - <button class="btn btn-primary" type="button" ng-click="modal.close()">Close</button> - </div> -</div> diff --git a/utils/test/testapi/opnfv_testapi/ui/results-report/partials/reportDetails.html b/utils/test/testapi/opnfv_testapi/ui/results-report/partials/reportDetails.html deleted file mode 100644 index 517e569c7..000000000 --- a/utils/test/testapi/opnfv_testapi/ui/results-report/partials/reportDetails.html +++ /dev/null @@ -1,87 +0,0 @@ -<!-- -HTML for each accordion group that separates the status types on the results -report page. ---> - -<uib-accordion-group is-open="isOpen" is-disabled="ctrl.caps[status].caps.length == 0"> - <uib-accordion-heading> - {{status | capitalize}} - <small> - (<strong>Total:</strong> {{ctrl.caps[status].caps.length}} capabilities, {{ctrl.caps[status].count}} tests) - <span ng-if="ctrl.testStatus !== 'total'"> - (<strong>{{ctrl.testStatus | capitalize}}:</strong> {{ctrl.getStatusTestCount(status)}} tests) - </span> - </small> - <i class="pull-right glyphicon" - ng-class="{'glyphicon-chevron-down': isOpen, 'glyphicon-chevron-right': !isOpen}"> - </i> - </uib-accordion-heading> - <ol class="capabilities"> - <li ng-repeat="capability in ctrl.caps[status].caps | orderBy:'id'" - ng-if="ctrl.isCapabilityShown(capability)"> - - <a ng-click="showTests = !showTests" - title="{{ctrl.guidelineData.capabilities[capability.id].description}}"> - {{capability.id}} - </a> - <span ng-class="{'text-success': ctrl.testStatus === 'passed', - 'text-danger': ctrl.testStatus === 'not passed', - 'text-warning': ctrl.testStatus === 'flagged'}" - ng-if="ctrl.testStatus !== 'total'"> - [{{ctrl.getCapabilityTestCount(capability)}}] - </span> - <span ng-class="{'text-success': (capability.passedTests.length > 0 && - capability.notPassedTests.length == 0), - 'text-danger': (capability.passedTests.length == 0 && - capability.notPassedTests.length > 0), - 'text-warning': (capability.passedTests.length > 0 && - capability.notPassedTests.length > 0)}" - ng-if="ctrl.testStatus === 'total'"> - [{{capability.passedTests.length}}/{{capability.passedTests.length + - capability.notPassedTests.length}}] - </span> - - <ul class="list-unstyled" uib-collapse="!showTests"> - <!-- Start passed test list --> - <li ng-repeat="test in capability.passedTests | orderBy:'toString()'" - ng-if="ctrl.isTestShown(test, capability)"> - - <span class="glyphicon glyphicon-ok text-success" - aria-hidden="true"> - </span> - <span ng-class="{'glyphicon glyphicon-flag text-warning': - ctrl.isTestFlagged(test, ctrl.guidelineData.capabilities[capability.id])}" - title="{{ctrl.getFlaggedReason(test, ctrl.guidelineData.capabilities[capability.id])}}"> - </span> - {{test}} - <span ng-if="ctrl.guidelineData.capabilities[capability.id].tests[test].aliases"> — - <a ng-click="showAliases = !showAliases">[Aliases]</a> - <div class="test-detail-report" ng-if="ctrl.guidelineData.capabilities[capability.id].tests[test].aliases && showAliases"> - <ul><li ng-repeat="alias in ctrl.guidelineData.capabilities[capability.id].tests[test].aliases">{{alias}}</li></ul> - </div> - </span> - </li> - <!-- End passed test list --> - - <!-- Start not passed test list --> - <li ng-repeat="test in capability.notPassedTests | orderBy:'toString()'" - ng-if="ctrl.isTestShown(test, capability)"> - - <span class="glyphicon glyphicon-remove text-danger" aria-hidden="true"></span> - <span ng-class="{'glyphicon glyphicon-flag text-warning': - ctrl.isTestFlagged(test, ctrl.guidelineData.capabilities[capability.id])}" - title="{{ctrl.getFlaggedReason(test, ctrl.guidelineData.capabilities[capability.id])}}"> - </span> - {{test}} - <span ng-if="ctrl.guidelineData.capabilities[capability.id].tests[test].aliases"> — - <a ng-click="showAliases = !showAliases">[Aliases]</a> - <div class="test-detail-report" ng-if="ctrl.guidelineData.capabilities[capability.id].tests[test].aliases && showAliases"> - <ul><li ng-repeat="alias in ctrl.guidelineData.capabilities[capability.id].tests[test].aliases">{{alias}}</li></ul> - </div> - </span> - </li> - <!-- End not passed test list --> - </ul> - </li> - </ol> -</uib-accordion-group> diff --git a/utils/test/testapi/opnfv_testapi/ui/results-report/resultsReport.html b/utils/test/testapi/opnfv_testapi/ui/results-report/resultsReport.html deleted file mode 100644 index 5527121ba..000000000 --- a/utils/test/testapi/opnfv_testapi/ui/results-report/resultsReport.html +++ /dev/null @@ -1,185 +0,0 @@ -<h3>Test Run Results</h3> - -<div ng-show="ctrl.resultsData" class="container-fluid"> - <div class="row"> - <div class="pull-left"> - <div class="test-report"> - <strong>Test ID:</strong> {{ctrl.testId}}<br /> - <div ng-if="ctrl.isResultAdmin()"><strong>Cloud ID:</strong> {{ctrl.resultsData.cpid}}<br /></div> - <strong>Upload Date:</strong> {{ctrl.resultsData.created_at}} UTC<br /> - <strong>Duration:</strong> {{ctrl.resultsData.duration_seconds}} seconds<br /> - <strong>Total Number of Passed Tests:</strong> - <a title="See all passed tests" ng-click="ctrl.openFullTestListModal()"> - {{ctrl.resultsData.results.length}} - </a> - </div> - <hr> - <div ng-show="ctrl.isResultAdmin()"> - <strong>Publicly Shared:</strong> - <span ng-if="ctrl.resultsData.meta.shared">Yes</span> - <span ng-if="!ctrl.resultsData.meta.shared">No</span> - <br /> - </div> - <div ng-show="ctrl.resultsData.product_version"> - <strong>Product:</strong> - {{ctrl.resultsData.product_version.product_info.name}} - <span ng-if="ctrl.resultsData.product_version.version"> - ({{ctrl.resultsData.product_version.version}}) - </span><br /> - </div> - <div ng-show="ctrl.resultsData.meta.guideline"> - <strong>Associated Guideline:</strong> - {{ctrl.resultsData.meta.guideline.slice(0, -5)}} - </div> - <div ng-show="ctrl.resultsData.meta.target"> - <strong>Associated Target Program:</strong> - {{ctrl.targetMappings[ctrl.resultsData.meta.target]}} - </div> - <div ng-show="ctrl.resultsData.verification_status"> - <strong>Verified:</strong> - <span class="yes">YES</span> - </div> - <hr> - </div> - - <div class="pull-right"> - <div ng-show="ctrl.isResultAdmin() && !ctrl.resultsData.verification_status"> - <button class="btn btn-info" ng-click="ctrl.openEditTestModal()">Edit</button> - <button type="button" class="btn btn-danger" ng-click="ctrl.deleteTestRun()" confirm="Are you sure you want to delete these test run results?">Delete</button> - </div> - <div ng-show="ctrl.resultsData.user_role === 'foundation'"> - <hr> - <div class="checkbox checkbox-verified"> - <label><input type="checkbox" - ng-model="ctrl.isVerified" - ng-change="ctrl.updateVerificationStatus()" - ng-true-value="1" - ng-false-value="0"> - <strong>Verified</strong> - </label> - </div> - </div> - </div> - </div> -</div> - -<div ng-show="ctrl.resultsData"> - <p>See how these results stack up against Interop Working Group capabilities and OpenStack - <a target="_blank" href="http://www.openstack.org/brand/interop/">target marketing programs.</a> - </p> - - <!-- User Options --> - <div class="row"> - <div class="col-md-3"> - <strong>Guideline Version:</strong> - <!-- Slicing the version file name here gets rid of the '.json' file extension --> - <select ng-model="ctrl.version" - ng-change="ctrl.updateGuidelines()" - class="form-control" - ng-options="versionFile.slice(0,-5) for versionFile in ctrl.versionList"> - </select> - </div> - <div class="col-md-4"> - <strong>Target Program:</strong> - <select ng-model="ctrl.target" class="form-control" ng-change="ctrl.buildCapabilitiesObject()"> - <option value="platform">OpenStack Powered Platform</option> - <option value="compute">OpenStack Powered Compute</option> - <option value="object">OpenStack Powered Object Storage</option> - </select> - </div> - </div> - <!-- End User Options --> - - <br /> - <div ng-if="ctrl.guidelineData"> - <strong>Guideline Status:</strong> - {{ctrl.guidelineData.status | capitalize}} - </div> - - <strong>Corresponding OpenStack Releases:</strong> - <ul class="list-inline"> - <li ng-repeat="release in ctrl.guidelineData.releases"> - {{release | capitalize}} - </li> - </ul> - <hr > - - <div ng-show="ctrl.guidelineData"> - <strong>Status:</strong> - <p>This cloud passes <strong>{{ctrl.requiredPassPercent | number:1}}% </strong> - ({{ctrl.caps.required.passedCount}}/{{ctrl.caps.required.count}}) - of the tests in the <strong>{{ctrl.version.slice(0, -5)}}</strong> <em>required</em> capabilities for the - <strong>{{ctrl.targetMappings[target]}}</strong> program. <br /> - Excluding flagged tests, this cloud passes - <strong>{{ctrl.nonFlagRequiredPassPercent | number:1}}%</strong> - ({{ctrl.nonFlagPassCount}}/{{ctrl.totalNonFlagCount}}) - of the <em>required</em> tests. - </p> - - <p>Compliance with <strong>{{ctrl.version.slice(0, -5)}}</strong>: - <strong> - <span ng-if="ctrl.nonFlagPassCount === ctrl.totalNonFlagCount" class="yes">YES</span> - <span ng-if="ctrl.nonFlagPassCount !== ctrl.totalNonFlagCount" class="no">NO</span> - </strong> - </p> - - <hr> - <h4>Capability Overview</h4> - - Test Filters:<br /> - <div class="btn-group button-margin" data-toggle="buttons"> - <label class="btn btn-default" ng-class="{'active': ctrl.testStatus === 'total'}"> - <input type="radio" ng-model="ctrl.testStatus" value="total"> - <span class="text-primary">All</span> - </label> - <label class="btn btn-default" ng-class="{'active': ctrl.testStatus === 'passed'}"> - <input type="radio" ng-model="ctrl.testStatus" value="passed"> - <span class="text-success">Passed</span> - </label> - <label class="btn btn-default" ng-class="{'active': ctrl.testStatus === 'not passed'}"> - <input type="radio" ng-model="ctrl.testStatus" value="not passed"> - <span class="text-danger">Not Passed</span> - </label> - <label class="btn btn-default" ng-class="{'active': ctrl.testStatus === 'flagged'}"> - <input type="radio" ng-model="ctrl.testStatus" value="flagged"> - <span class="text-warning">Flagged</span> - </label> - </div> - - <uib-accordion close-others=false> - <!-- The ng-repeat is used to pass in a local variable to the template. --> - <ng-include - ng-repeat="status in ['required']" - src="ctrl.detailsTemplate" - onload="isOpen = true"> - </ng-include> - <br /> - <ng-include - ng-repeat="status in ['advisory']" - src="ctrl.detailsTemplate"> - </ng-include> - <br /> - <ng-include - ng-repeat="status in ['deprecated']" - src="ctrl.detailsTemplate"> - </ng-include> - <br /> - <ng-include - ng-repeat="status in ['removed']" - src="ctrl.detailsTemplate"> - </ng-include> - </uib-accordion> - </div> -</div> - -<div class="loading"> - <div cg-busy="{promise:versionsRequest,message:'Loading versions'}"></div> - <div cg-busy="{promise:capsRequest,message:'Loading capabilities'}"></div> - <div cg-busy="{promise:resultsRequest,message:'Loading results'}"></div> -</div> - -<div ng-show="ctrl.showError" class="alert alert-danger" role="alert"> - <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> - <span class="sr-only">Error:</span> - {{ctrl.error}} -</div> diff --git a/utils/test/testapi/opnfv_testapi/ui/results-report/resultsReportController.js b/utils/test/testapi/opnfv_testapi/ui/results-report/resultsReportController.js deleted file mode 100644 index 591ad402b..000000000 --- a/utils/test/testapi/opnfv_testapi/ui/results-report/resultsReportController.js +++ /dev/null @@ -1,869 +0,0 @@ -/* - * 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. - */ - -(function () { - 'use strict'; - - angular - .module('testapiApp') - .controller('ResultsReportController', ResultsReportController); - - ResultsReportController.$inject = [ - '$http', '$stateParams', '$window', - '$uibModal', 'testapiApiUrl', 'raiseAlert' - ]; - - /** - * TestAPI Results Report Controller - * This controller is for the '/results/<test run ID>' page where a user can - * view details for a specific test run. - */ - function ResultsReportController($http, $stateParams, $window, - $uibModal, testapiApiUrl, raiseAlert) { - - var ctrl = this; - - ctrl.getVersionList = getVersionList; - ctrl.getResults = getResults; - ctrl.isResultAdmin = isResultAdmin; - ctrl.isShared = isShared; - ctrl.shareTestRun = shareTestRun; - ctrl.deleteTestRun = deleteTestRun; - ctrl.updateVerificationStatus = updateVerificationStatus; - ctrl.updateGuidelines = updateGuidelines; - ctrl.getTargetCapabilities = getTargetCapabilities; - ctrl.buildCapabilityV1_2 = buildCapabilityV1_2; - ctrl.buildCapabilityV1_3 = buildCapabilityV1_3; - ctrl.buildCapabilitiesObject = buildCapabilitiesObject; - ctrl.isTestFlagged = isTestFlagged; - ctrl.getFlaggedReason = getFlaggedReason; - ctrl.isCapabilityShown = isCapabilityShown; - ctrl.isTestShown = isTestShown; - ctrl.getCapabilityTestCount = getCapabilityTestCount; - ctrl.getStatusTestCount = getStatusTestCount; - ctrl.openFullTestListModal = openFullTestListModal; - ctrl.openEditTestModal = openEditTestModal; - - /** The testID extracted from the URL route. */ - ctrl.testId = $stateParams.testID; - - /** The target OpenStack marketing program to compare against. */ - ctrl.target = 'platform'; - - /** Mappings of Interop WG components to marketing program names. */ - ctrl.targetMappings = { - 'platform': 'Openstack Powered Platform', - 'compute': 'OpenStack Powered Compute', - 'object': 'OpenStack Powered Object Storage' - }; - - /** The schema version of the currently selected guideline data. */ - ctrl.schemaVersion = null; - - /** The selected test status used for test filtering. */ - ctrl.testStatus = 'total'; - - /** The HTML template that all accordian groups will use. */ - ctrl.detailsTemplate = 'components/results-report/partials/' + - 'reportDetails.html'; - - /** - * Retrieve an array of available guideline files from the TestAPI - * API server, sort this array reverse-alphabetically, and store it in - * a scoped variable. The scope's selected version is initialized to - * the latest (i.e. first) version here as well. After a successful API - * call, the function to update the capabilities is called. - * Sample API return array: ["2015.03.json", "2015.04.json"] - */ - function getVersionList() { - var content_url = testapiApiUrl + '/guidelines'; - ctrl.versionsRequest = - $http.get(content_url).success(function (data) { - ctrl.versionList = data.sort().reverse(); - if (!ctrl.version) { - // Default to the first approved guideline which is - // expected to be at index 1. - ctrl.version = ctrl.versionList[1]; - } - ctrl.updateGuidelines(); - }).error(function (error) { - ctrl.showError = true; - ctrl.error = 'Error retrieving version list: ' + - angular.toJson(error); - }); - } - - /** - * Retrieve results from the TestAPI API server based on the test - * run id in the URL. This function is the first function that will - * be called from the controller. Upon successful retrieval of results, - * the function that gets the version list will be called. - */ - function getResults() { - var content_url = testapiApiUrl + '/results/' + ctrl.testId; - ctrl.resultsRequest = - $http.get(content_url).success(function (data) { - ctrl.resultsData = data; - ctrl.version = ctrl.resultsData.meta.guideline; - ctrl.isVerified = ctrl.resultsData.verification_status; - if (ctrl.resultsData.meta.target) { - ctrl.target = ctrl.resultsData.meta.target; - } - getVersionList(); - }).error(function (error) { - ctrl.showError = true; - ctrl.resultsData = null; - ctrl.error = 'Error retrieving results from server: ' + - angular.toJson(error); - }); - } - - /** - * This tells you whether the current user has administrative - * privileges for the test result. - * @returns {Boolean} true if the user has admin privileges. - */ - function isResultAdmin() { - return Boolean(ctrl.resultsData && - (ctrl.resultsData.user_role === 'owner' || - ctrl.resultsData.user_role === 'foundation')); - } - /** - * This tells you whether the current results are shared with the - * community or not. - * @returns {Boolean} true if the results are shared - */ - function isShared() { - return Boolean(ctrl.resultsData && - 'shared' in ctrl.resultsData.meta); - } - - /** - * This will send an API request in order to share or unshare the - * current results based on the passed in shareState. - * @param {Boolean} shareState - Whether to share or unshare results. - */ - function shareTestRun(shareState) { - var content_url = [ - testapiApiUrl, '/results/', ctrl.testId, '/meta/shared' - ].join(''); - if (shareState) { - ctrl.shareRequest = - $http.post(content_url, 'true').success(function () { - ctrl.resultsData.meta.shared = 'true'; - raiseAlert('success', '', 'Test run shared!'); - }).error(function (error) { - raiseAlert('danger', error.title, error.detail); - }); - } else { - ctrl.shareRequest = - $http.delete(content_url).success(function () { - delete ctrl.resultsData.meta.shared; - raiseAlert('success', '', 'Test run unshared!'); - }).error(function (error) { - raiseAlert('danger', error.title, error.detail); - }); - } - } - - /** - * This will send a request to the API to delete the current - * test results set. - */ - function deleteTestRun() { - var content_url = [ - testapiApiUrl, '/results/', ctrl.testId - ].join(''); - ctrl.deleteRequest = - $http.delete(content_url).success(function () { - $window.history.back(); - }).error(function (error) { - raiseAlert('danger', error.title, error.detail); - }); - } - - /** - * This will send a request to the API to delete the current - * test results set. - */ - function updateVerificationStatus() { - var content_url = [ - testapiApiUrl, '/results/', ctrl.testId - ].join(''); - var data = {'verification_status': ctrl.isVerified}; - ctrl.updateRequest = - $http.put(content_url, data).success( - function () { - ctrl.resultsData.verification_status = ctrl.isVerified; - raiseAlert('success', '', - 'Verification status changed!'); - }).error(function (error) { - ctrl.isVerified = ctrl.resultsData.verification_status; - raiseAlert('danger', error.title, error.detail); - }); - } - - /** - * This will contact the TestAPI API server to retrieve the JSON - * content of the guideline file corresponding to the selected - * version. A function to construct an object from the capability - * data will be called upon successful retrieval. - */ - function updateGuidelines() { - ctrl.guidelineData = null; - ctrl.showError = false; - var content_url = testapiApiUrl + '/guidelines/' + - ctrl.version; - ctrl.capsRequest = - $http.get(content_url).success(function (data) { - ctrl.guidelineData = data; - ctrl.schemaVersion = data.schema; - ctrl.buildCapabilitiesObject(); - }).error(function (error) { - ctrl.showError = true; - ctrl.guidelineData = null; - ctrl.error = 'Error retrieving guideline date: ' + - angular.toJson(error); - }); - } - - /** - * This will get all the capabilities relevant to the target and - * their corresponding statuses. - * @returns {Object} Object containing each capability and their status - */ - function getTargetCapabilities() { - var components = ctrl.guidelineData.components; - var targetCaps = {}; - - // The 'platform' target is comprised of multiple components, so - // we need to get the capabilities belonging to each of its - // components. - if (ctrl.target === 'platform') { - var platform_components = - ctrl.guidelineData.platform.required; - - // This will contain status priority values, where lower - // values mean higher priorities. - var statusMap = { - required: 1, - advisory: 2, - deprecated: 3, - removed: 4 - }; - - // For each component required for the platform program. - angular.forEach(platform_components, function (component) { - // Get each capability list belonging to each status. - angular.forEach(components[component], - function (caps, status) { - // For each capability. - angular.forEach(caps, function(cap) { - // If the capability has already been added. - if (cap in targetCaps) { - // If the status priority value is less - // than the saved priority value, update - // the value. - if (statusMap[status] < - statusMap[targetCaps[cap]]) { - targetCaps[cap] = status; - } - } - else { - targetCaps[cap] = status; - } - }); - }); - }); - } - else { - angular.forEach(components[ctrl.target], - function (caps, status) { - angular.forEach(caps, function(cap) { - targetCaps[cap] = status; - }); - }); - } - return targetCaps; - } - - /** - * This will build the a capability object for schema version 1.2. - * This object will contain the information needed to form a report in - * the HTML template. - * @param {String} capId capability ID - */ - function buildCapabilityV1_2(capId) { - var cap = { - 'id': capId, - 'passedTests': [], - 'notPassedTests': [], - 'passedFlagged': [], - 'notPassedFlagged': [] - }; - var capDetails = ctrl.guidelineData.capabilities[capId]; - // Loop through each test belonging to the capability. - angular.forEach(capDetails.tests, - function (testId) { - // If the test ID is in the results' test list, add - // it to the passedTests array. - if (ctrl.resultsData.results.indexOf(testId) > -1) { - cap.passedTests.push(testId); - if (capDetails.flagged.indexOf(testId) > -1) { - cap.passedFlagged.push(testId); - } - } - else { - cap.notPassedTests.push(testId); - if (capDetails.flagged.indexOf(testId) > -1) { - cap.notPassedFlagged.push(testId); - } - } - }); - return cap; - } - - /** - * This will build the a capability object for schema version 1.3 and - * above. This object will contain the information needed to form a - * report in the HTML template. - * @param {String} capId capability ID - */ - function buildCapabilityV1_3(capId) { - var cap = { - 'id': capId, - 'passedTests': [], - 'notPassedTests': [], - 'passedFlagged': [], - 'notPassedFlagged': [] - }; - - // For cases where a capability listed in components is not - // in the capabilities object. - if (!(capId in ctrl.guidelineData.capabilities)) { - return cap; - } - - // Loop through each test belonging to the capability. - angular.forEach(ctrl.guidelineData.capabilities[capId].tests, - function (details, testId) { - var passed = false; - - // If the test ID is in the results' test list. - if (ctrl.resultsData.results.indexOf(testId) > -1) { - passed = true; - } - else if ('aliases' in details) { - var len = details.aliases.length; - for (var i = 0; i < len; i++) { - var alias = details.aliases[i]; - if (ctrl.resultsData.results.indexOf(alias) > -1) { - passed = true; - break; - } - } - } - - // Add to correct array based on whether the test was - // passed or not. - if (passed) { - cap.passedTests.push(testId); - if ('flagged' in details) { - cap.passedFlagged.push(testId); - } - } - else { - cap.notPassedTests.push(testId); - if ('flagged' in details) { - cap.notPassedFlagged.push(testId); - } - } - }); - return cap; - } - - /** - * This will check the schema version of the current capabilities file, - * and will call the correct method to build an object based on the - * capability data retrieved from the TestAPI API server. - */ - function buildCapabilitiesObject() { - // This is the object template where 'count' is the number of - // total tests that fall under the given status, and 'passedCount' - // is the number of tests passed. The 'caps' array will contain - // objects with details regarding each capability. - ctrl.caps = { - 'required': {'caps': [], 'count': 0, 'passedCount': 0, - 'flagFailCount': 0, 'flagPassCount': 0}, - 'advisory': {'caps': [], 'count': 0, 'passedCount': 0, - 'flagFailCount': 0, 'flagPassCount': 0}, - 'deprecated': {'caps': [], 'count': 0, 'passedCount': 0, - 'flagFailCount': 0, 'flagPassCount': 0}, - 'removed': {'caps': [], 'count': 0, 'passedCount': 0, - 'flagFailCount': 0, 'flagPassCount': 0} - }; - - switch (ctrl.schemaVersion) { - case '1.2': - var capMethod = 'buildCapabilityV1_2'; - break; - case '1.3': - case '1.4': - case '1.5': - case '1.6': - capMethod = 'buildCapabilityV1_3'; - break; - default: - ctrl.showError = true; - ctrl.guidelineData = null; - ctrl.error = 'The schema version for the guideline ' + - 'file selected (' + ctrl.schemaVersion + - ') is currently not supported.'; - return; - } - - // Get test details for each relevant capability and store - // them in the scope's 'caps' object. - var targetCaps = ctrl.getTargetCapabilities(); - angular.forEach(targetCaps, function(status, capId) { - var cap = ctrl[capMethod](capId); - ctrl.caps[status].count += - cap.passedTests.length + cap.notPassedTests.length; - ctrl.caps[status].passedCount += cap.passedTests.length; - ctrl.caps[status].flagPassCount += cap.passedFlagged.length; - ctrl.caps[status].flagFailCount += - cap.notPassedFlagged.length; - ctrl.caps[status].caps.push(cap); - }); - - ctrl.requiredPassPercent = (ctrl.caps.required.passedCount * - 100 / ctrl.caps.required.count); - - ctrl.totalRequiredFailCount = ctrl.caps.required.count - - ctrl.caps.required.passedCount; - ctrl.totalRequiredFlagCount = - ctrl.caps.required.flagFailCount + - ctrl.caps.required.flagPassCount; - ctrl.totalNonFlagCount = ctrl.caps.required.count - - ctrl.totalRequiredFlagCount; - ctrl.nonFlagPassCount = ctrl.totalNonFlagCount - - (ctrl.totalRequiredFailCount - - ctrl.caps.required.flagFailCount); - - ctrl.nonFlagRequiredPassPercent = (ctrl.nonFlagPassCount * - 100 / ctrl.totalNonFlagCount); - } - - /** - * This will check if a given test is flagged. - * @param {String} test ID of the test to check - * @param {Object} capObj capability that test is under - * @returns {Boolean} truthy value if test is flagged - */ - function isTestFlagged(test, capObj) { - if (!capObj) { - return false; - } - return (((ctrl.schemaVersion === '1.2') && - (capObj.flagged.indexOf(test) > -1)) || - ((ctrl.schemaVersion >= '1.3') && - (capObj.tests[test].flagged))); - } - - /** - * This will return the reason a test is flagged. An empty string - * will be returned if the passed in test is not flagged. - * @param {String} test ID of the test to check - * @param {String} capObj capability that test is under - * @returns {String} reason - */ - function getFlaggedReason(test, capObj) { - if ((ctrl.schemaVersion === '1.2') && - (ctrl.isTestFlagged(test, capObj))) { - - // Return a generic message since schema 1.2 does not - // provide flag reasons. - return 'Interop Working Group has flagged this test.'; - } - else if ((ctrl.schemaVersion >= '1.3') && - (ctrl.isTestFlagged(test, capObj))) { - - return capObj.tests[test].flagged.reason; - } - else { - return ''; - } - } - - /** - * This will check the if a capability should be shown based on the - * test filter selected. If a capability does not have any tests - * belonging under the given filter, it should not be shown. - * @param {Object} capability Built object for capability - * @returns {Boolean} true if capability should be shown - */ - function isCapabilityShown(capability) { - return ((ctrl.testStatus === 'total') || - (ctrl.testStatus === 'passed' && - capability.passedTests.length > 0) || - (ctrl.testStatus === 'not passed' && - capability.notPassedTests.length > 0) || - (ctrl.testStatus === 'flagged' && - (capability.passedFlagged.length + - capability.notPassedFlagged.length > 0))); - } - - /** - * This will check the if a test should be shown based on the test - * filter selected. - * @param {String} test ID of the test - * @param {Object} capability Built object for capability - * @return {Boolean} true if test should be shown - */ - function isTestShown(test, capability) { - return ((ctrl.testStatus === 'total') || - (ctrl.testStatus === 'passed' && - capability.passedTests.indexOf(test) > -1) || - (ctrl.testStatus === 'not passed' && - capability.notPassedTests.indexOf(test) > -1) || - (ctrl.testStatus === 'flagged' && - (capability.passedFlagged.indexOf(test) > -1 || - capability.notPassedFlagged.indexOf(test) > -1))); - } - - /** - * This will give the number of tests belonging under the selected - * test filter for a given capability. - * @param {Object} capability Built object for capability - * @returns {Number} number of tests under filter - */ - function getCapabilityTestCount(capability) { - if (ctrl.testStatus === 'total') { - return capability.passedTests.length + - capability.notPassedTests.length; - } - else if (ctrl.testStatus === 'passed') { - return capability.passedTests.length; - } - else if (ctrl.testStatus === 'not passed') { - return capability.notPassedTests.length; - } - else if (ctrl.testStatus === 'flagged') { - return capability.passedFlagged.length + - capability.notPassedFlagged.length; - } - else { - return 0; - } - } - - /** - * This will give the number of tests belonging under the selected - * test filter for a given status. - * @param {String} capability status - * @returns {Number} number of tests for status under filter - */ - function getStatusTestCount(status) { - if (!ctrl.caps) { - return -1; - } - else if (ctrl.testStatus === 'total') { - return ctrl.caps[status].count; - } - else if (ctrl.testStatus === 'passed') { - return ctrl.caps[status].passedCount; - } - else if (ctrl.testStatus === 'not passed') { - return ctrl.caps[status].count - - ctrl.caps[status].passedCount; - } - else if (ctrl.testStatus === 'flagged') { - return ctrl.caps[status].flagFailCount + - ctrl.caps[status].flagPassCount; - } - else { - return -1; - } - } - - /** - * This will open the modal that will show the full list of passed - * tests for the current results. - */ - function openFullTestListModal() { - $uibModal.open({ - templateUrl: '/components/results-report/partials' + - '/fullTestListModal.html', - backdrop: true, - windowClass: 'modal', - animation: true, - controller: 'FullTestListModalController as modal', - size: 'lg', - resolve: { - tests: function () { - return ctrl.resultsData.results; - } - } - }); - } - - /** - * This will open the modal that will all a user to edit test run - * metadata. - */ - function openEditTestModal() { - $uibModal.open({ - templateUrl: '/components/results-report/partials' + - '/editTestModal.html', - backdrop: true, - windowClass: 'modal', - animation: true, - controller: 'EditTestModalController as modal', - size: 'lg', - resolve: { - resultsData: function () { - return ctrl.resultsData; - } - } - }); - } - - getResults(); - } - - angular - .module('testapiApp') - .controller('FullTestListModalController', FullTestListModalController); - - FullTestListModalController.$inject = ['$uibModalInstance', 'tests']; - - /** - * Full Test List Modal Controller - * This controller is for the modal that appears if a user wants to see the - * full list of passed tests on a report page. - */ - function FullTestListModalController($uibModalInstance, tests) { - var ctrl = this; - - ctrl.tests = tests; - - /** - * This function will close/dismiss the modal. - */ - ctrl.close = function () { - $uibModalInstance.dismiss('exit'); - }; - - /** - * This function will return a string representing the sorted - * tests list separated by newlines. - */ - ctrl.getTestListString = function () { - return ctrl.tests.sort().join('\n'); - }; - } - - angular - .module('testapiApp') - .controller('EditTestModalController', EditTestModalController); - - EditTestModalController.$inject = [ - '$uibModalInstance', '$http', '$state', 'raiseAlert', - 'testapiApiUrl', 'resultsData' - ]; - - /** - * Edit Test Modal Controller - * This controller is for the modal that appears if a user wants to edit - * test run metadata. - */ - function EditTestModalController($uibModalInstance, $http, $state, - raiseAlert, testapiApiUrl, resultsData) { - - var ctrl = this; - - ctrl.getVersionList = getVersionList; - ctrl.getUserProducts = getUserProducts; - ctrl.associateProductVersion = associateProductVersion; - ctrl.getProductVersions = getProductVersions; - ctrl.saveChanges = saveChanges; - - ctrl.resultsData = resultsData; - ctrl.metaCopy = angular.copy(resultsData.meta); - ctrl.prodVersionCopy = angular.copy(resultsData.product_version); - - ctrl.getVersionList(); - ctrl.getUserProducts(); - - /** - * Retrieve an array of available capability files from the TestAPI - * API server, sort this array reverse-alphabetically, and store it in - * a scoped variable. - * Sample API return array: ["2015.03.json", "2015.04.json"] - */ - function getVersionList() { - if (ctrl.versionList) { - return; - } - var content_url = testapiApiUrl + '/guidelines'; - ctrl.versionsRequest = - $http.get(content_url).success(function (data) { - ctrl.versionList = data.sort().reverse(); - }).error(function (error) { - raiseAlert('danger', error.title, - 'Unable to retrieve version list'); - }); - } - - /** - * Get products user has management rights to or all products depending - * on the passed in parameter value. - */ - function getUserProducts() { - var contentUrl = testapiApiUrl + '/products'; - ctrl.productsRequest = - $http.get(contentUrl).success(function (data) { - ctrl.products = {}; - angular.forEach(data.products, function(prod) { - if (prod.can_manage) { - ctrl.products[prod.id] = prod; - } - }); - if (ctrl.prodVersionCopy) { - ctrl.selectedProduct = ctrl.products[ - ctrl.prodVersionCopy.product_info.id - ]; - } - ctrl.getProductVersions(); - }).error(function (error) { - ctrl.products = null; - ctrl.showError = true; - ctrl.error = - 'Error retrieving Products listing from server: ' + - angular.toJson(error); - }); - } - - /** - * Send a PUT request to the API server to associate a product with - * a test result. - */ - function associateProductVersion() { - var verId = (ctrl.selectedVersion ? - ctrl.selectedVersion.id : null); - var testId = resultsData.id; - var url = testapiApiUrl + '/results/' + testId; - ctrl.associateRequest = $http.put(url, {'product_version_id': - verId}) - .error(function (error) { - ctrl.showError = true; - ctrl.showSuccess = false; - ctrl.error = - 'Error associating product version with test run: ' + - angular.toJson(error); - }); - } - - /** - * Get all versions for a product. - */ - function getProductVersions() { - if (!ctrl.selectedProduct) { - ctrl.productVersions = []; - ctrl.selectedVersion = null; - return; - } - - var url = testapiApiUrl + '/products/' + - ctrl.selectedProduct.id + '/versions'; - ctrl.getVersionsRequest = $http.get(url) - .success(function (data) { - ctrl.productVersions = data; - if (ctrl.prodVersionCopy && - ctrl.prodVersionCopy.product_info.id == - ctrl.selectedProduct.id) { - ctrl.selectedVersion = ctrl.prodVersionCopy; - } - else { - angular.forEach(data, function(ver) { - if (!ver.version) { - ctrl.selectedVersion = ver; - } - }); - } - }).error(function (error) { - raiseAlert('danger', error.title, error.detail); - }); - } - - /** - * Send a PUT request to the server with the changes. - */ - function saveChanges() { - ctrl.showError = false; - ctrl.showSuccess = false; - var metaBaseUrl = [ - testapiApiUrl, '/results/', resultsData.id, '/meta/' - ].join(''); - var metaFields = ['target', 'guideline', 'shared']; - var meta = ctrl.metaCopy; - angular.forEach(metaFields, function(field) { - var oldMetaValue = (field in ctrl.resultsData.meta) ? - ctrl.resultsData.meta[field] : ''; - if (field in meta && oldMetaValue != meta[field]) { - var metaUrl = metaBaseUrl + field; - if (meta[field]) { - ctrl.assocRequest = $http.post(metaUrl, meta[field]) - .success(function(data) { - ctrl.resultsData.meta[field] = meta[field]; - }) - .error(function (error) { - ctrl.showError = true; - ctrl.showSuccess = false; - ctrl.error = - 'Error associating metadata with ' + - 'test run: ' + angular.toJson(error); - }); - } - else { - ctrl.unassocRequest = $http.delete(metaUrl) - .success(function (data) { - delete ctrl.resultsData.meta[field]; - delete meta[field]; - }) - .error(function (error) { - ctrl.showError = true; - ctrl.showSuccess = false; - ctrl.error = - 'Error associating metadata with ' + - 'test run: ' + angular.toJson(error); - }); - } - } - }); - ctrl.associateProductVersion(); - if (!ctrl.showError) { - ctrl.showSuccess = true; - $state.reload(); - } - } - - /** - * This function will close/dismiss the modal. - */ - ctrl.close = function () { - $uibModalInstance.dismiss('exit'); - }; - } -})(); diff --git a/utils/test/testapi/opnfv_testapi/ui/results/results.html b/utils/test/testapi/opnfv_testapi/ui/results/results.html deleted file mode 100644 index 2ae5339a0..000000000 --- a/utils/test/testapi/opnfv_testapi/ui/results/results.html +++ /dev/null @@ -1,115 +0,0 @@ -<h3>{{ctrl.pageHeader}}</h3> -<p>{{ctrl.pageParagraph}}</p> -<form class="form-inline" ng-show="ctrl.isUserResults"> -<h4>Upload Results</h4> -<div class="form-group col-m-3"> - <input class="form-contrl btn btn-default" type = "file" file-model = "resultFile"/> -</div> -<div class="checkbox col-m-1"> - <label> - <input type="checkbox" ng-model="ctrl.isPublic">public - </label> -</div> -<div class="form-group col-m-3"> - <button class="btn btn-primary" ng-click = "ctrl.uploadFile()">upload result</button> -</div> -<div> -<lable>{{ctrl.uploadState}}</label> -</div> -</form> -<div class="row" style="margin-bottom:24px;"></div> -<div class="result-filters"> - <h4>Filters</h4> - <div class="row"> - <div class="col-md-3"> - <label for="cpid">Start Date</label> - <p class="input-group"> - <input type="text" class="form-control" - uib-datepicker-popup="{{ctrl.format}}" - ng-model="ctrl.startDate" is-open="ctrl.startOpen" - close-text="Close" /> - <span class="input-group-btn"> - <button type="button" class="btn btn-default" ng-click="ctrl.open($event, 'startOpen')"> - <i class="glyphicon glyphicon-calendar"></i> - </button> - </span> - </p> - </div> - <div class="col-md-3"> - <label for="cpid">End Date</label> - <p class="input-group"> - <input type="text" class="form-control" - uib-datepicker-popup="{{ctrl.format}}" - ng-model="ctrl.endDate" is-open="ctrl.endOpen" - close-text="Close" /> - <span class="input-group-btn"> - <button type="button" class="btn btn-default" ng-click="ctrl.open($event, 'endOpen')"> - <i class="glyphicon glyphicon-calendar"></i> - </button> - </span> - </p> - </div> - <div class="col-md-3" style="margin-top:24px;"> - <button type="submit" class="btn btn-primary" ng-click="ctrl.update()">Filter</button> - <button type="submit" class="btn btn-primary btn-danger" ng-click="ctrl.clearFilters()">Clear</button> - </div> - </div> -</div> - -<div cg-busy="{promise:ctrl.authRequest,message:'Loading'}"></div> -<div cg-busy="{promise:ctrl.resultsRequest,message:'Loading'}"></div> -<div ng-show="ctrl.data" class="results-table"> - <table ng-data="ctrl.data.result" ng-show="ctrl.data" class="table table-striped table-hover"> - <thead> - <tr> - <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>{{ 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-repeat-end=> - </tr> - </tbody> - </table> - - <div class="pages"> - <uib-pagination - total-items="ctrl.totalItems" - ng-model="ctrl.currentPage" - items-per-page="ctrl.itemsPerPage" - max-size="ctrl.maxSize" - class="pagination-sm" - boundary-links="true" - rotate="false" - num-pages="ctrl.numPages" - ng-change="ctrl.update()"> - </uib-pagination> - </div> -</div> - -<div ng-show="ctrl.showError" class="alert alert-danger" role="alert"> - <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> - <span class="sr-only">Error:</span> - {{ctrl.error}} -</div> diff --git a/utils/test/testapi/opnfv_testapi/ui/results/resultsController.js b/utils/test/testapi/opnfv_testapi/ui/results/resultsController.js deleted file mode 100644 index cc6cc0b6e..000000000 --- a/utils/test/testapi/opnfv_testapi/ui/results/resultsController.js +++ /dev/null @@ -1,370 +0,0 @@ -/* - * 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. - */ - -(function () { - 'use strict'; - - angular - .module('testapiApp') - .controller('ResultsController', ResultsController); - - angular - .module('testapiApp') - .directive('fileModel', ['$parse', function ($parse) { - return { - restrict: 'A', - link: function(scope, element, attrs) { - var model = $parse(attrs.fileModel); - var modelSetter = model.assign; - - element.bind('change', function(){ - scope.$apply(function(){ - modelSetter(scope, element[0].files[0]); - }); - }); - } - }; - }]); - - ResultsController.$inject = [ - '$scope', '$http', '$filter', '$state', 'testapiApiUrl','raiseAlert' - ]; - - /** - * TestAPI Results Controller - * This controller is for the '/results' page where a user can browse - * a listing of community uploaded results. - */ - function ResultsController($scope, $http, $filter, $state, testapiApiUrl, - raiseAlert) { - var ctrl = this; - - ctrl.uploadFile=uploadFile; - ctrl.update = update; - ctrl.open = open; - ctrl.clearFilters = clearFilters; - ctrl.associateMeta = associateMeta; - ctrl.getVersionList = getVersionList; - ctrl.getUserProducts = getUserProducts; - ctrl.associateProductVersion = associateProductVersion; - ctrl.getProductVersions = getProductVersions; - ctrl.prepVersionEdit = prepVersionEdit; - - /** Mappings of Interop WG components to marketing program names. */ - ctrl.targetMappings = { - 'platform': 'Openstack Powered Platform', - 'compute': 'OpenStack Powered Compute', - 'object': 'OpenStack Powered Object Storage' - }; - - /** Initial page to be on. */ - ctrl.currentPage = 1; - - /** - * How many results should display on each page. Since pagination - * is server-side implemented, this value should match the - * 'results_per_page' configuration of the TestAPI server which - * defaults to 20. - */ - ctrl.itemsPerPage = 20; - - /** - * How many page buttons should be displayed at max before adding - * the '...' button. - */ - ctrl.maxSize = 5; - - /** The upload date lower limit to be used in filtering results. */ - ctrl.startDate = ''; - - /** The upload date upper limit to be used in filtering results. */ - ctrl.endDate = ''; - - /** The date format for the date picker. */ - ctrl.format = 'yyyy-MM-dd'; - - /** Check to see if this page should display user-specific results. */ - // ctrl.isUserResults = $state.current.name === 'userResults'; - // need auth to browse - ctrl.isUserResults = $state.current.name === 'userResults'; - - // Should only be on user-results-page if authenticated. - if (ctrl.isUserResults && !$scope.auth.isAuthenticated) { - $state.go('home'); - } - - ctrl.pageHeader = ctrl.isUserResults ? - 'Private test results' : 'Community test results'; - - ctrl.pageParagraph = ctrl.isUserResults ? - 'Your most recently uploaded test results are listed here.' : - 'The most recently uploaded community test results are listed ' + - 'here.'; - - ctrl.uploadState = ''; - - ctrl.isPublic = false; - - if (ctrl.isUserResults) { - ctrl.authRequest = $scope.auth.doSignCheck() - .then(ctrl.update); - // ctrl.getUserProducts(); - } else { - ctrl.update(); - } - - - function uploadFileToUrl(file, uploadUrl){ - var fd = new FormData(); - fd.append('file', file); - fd.append('public', ctrl.isPublic) - - $http.post(uploadUrl, fd, { - transformRequest: angular.identity, - headers: {'Content-Type': undefined} - }) - - .success(function(data){ - var id = data.href.substr(data.href.lastIndexOf('/')+1); - ctrl.uploadState = "Upload succeed. Result id is " + id; - ctrl.update(); - }) - - .error(function(data, status){ - ctrl.uploadState = "Upload failed. Error code is " + status; - }); - } - - function uploadFile(){ - var file = $scope.resultFile; - console.log('file is ' ); - console.dir(file); - - var uploadUrl = testapiApiUrl + "/results/upload"; - uploadFileToUrl(file, uploadUrl); - }; - - /** - * This will contact the TestAPI API to get a listing of test run - * results. - */ - function update() { - ctrl.showError = false; - // Construct the API URL based on user-specified filters. - var content_url = testapiApiUrl + '/results' + - '?page=' + ctrl.currentPage; - var start = $filter('date')(ctrl.startDate, 'yyyy-MM-dd'); - if (start) { - content_url = - content_url + '&from=' + start + ' 00:00:00'; - } - var end = $filter('date')(ctrl.endDate, 'yyyy-MM-dd'); - if (end) { - content_url = content_url + '&to=' + end + ' 23:59:59'; - } - if (ctrl.isUserResults) { - content_url = content_url + '&signed'; - } - ctrl.resultsRequest = - $http.get(content_url).success(function (data) { - ctrl.data = data; - ctrl.totalItems = ctrl.data.pagination.total_pages * ctrl.itemsPerPage; - ctrl.currentPage = ctrl.data.pagination.current_page; - }).error(function (error) { - ctrl.data = null; - ctrl.totalItems = 0; - ctrl.showError = true; - ctrl.error = - 'Error retrieving results listing from server: ' + - angular.toJson(error); - }); - } - - /** - * This is called when the date filter calendar is opened. It - * does some event handling, and sets a scope variable so the UI - * knows which calendar was opened. - * @param {Object} $event - The Event object - * @param {String} openVar - Tells which calendar was opened - */ - function open($event, openVar) { - $event.preventDefault(); - $event.stopPropagation(); - ctrl[openVar] = true; - } - - /** - * This function will clear all filters and update the results - * listing. - */ - function clearFilters() { - ctrl.startDate = null; - ctrl.endDate = null; - ctrl.update(); - } - - /** - * This will send an API request in order to associate a metadata - * key-value pair with the given testId - * @param {Number} index - index of the test object in the results list - * @param {String} key - metadata key - * @param {String} value - metadata value - */ - function associateMeta(index, key, value) { - var testId = ctrl.data.results[index].id; - var metaUrl = [ - testapiApiUrl, '/results/', testId, '/meta/', key - ].join(''); - - var editFlag = key + 'Edit'; - if (value) { - ctrl.associateRequest = $http.post(metaUrl, value) - .success(function () { - ctrl.data.results[index][editFlag] = false; - }).error(function (error) { - raiseAlert('danger', error.title, error.detail); - }); - } - else { - ctrl.unassociateRequest = $http.delete(metaUrl) - .success(function () { - ctrl.data.results[index][editFlag] = false; - }).error(function (error) { - if (error.code == 404) { - // Key doesn't exist, so count it as a success, - // and don't raise an alert. - ctrl.data.results[index][editFlag] = false; - } - else { - raiseAlert('danger', error.title, error.detail); - } - }); - } - } - - /** - * Retrieve an array of available capability files from the TestAPI - * API server, sort this array reverse-alphabetically, and store it in - * a scoped variable. - * Sample API return array: ["2015.03.json", "2015.04.json"] - */ - function getVersionList() { - if (ctrl.versionList) { - return; - } - var content_url = testapiApiUrl + '/guidelines'; - ctrl.versionsRequest = - $http.get(content_url).success(function (data) { - ctrl.versionList = data.sort().reverse(); - }).error(function (error) { - raiseAlert('danger', error.title, - 'Unable to retrieve version list'); - }); - } - - /** - * Get products user has management rights to or all products depending - * on the passed in parameter value. - */ - function getUserProducts() { - if (ctrl.products) { - return; - } - var contentUrl = testapiApiUrl + '/products'; - ctrl.productsRequest = - $http.get(contentUrl).success(function (data) { - ctrl.products = {}; - angular.forEach(data.products, function(prod) { - if (prod.can_manage) { - ctrl.products[prod.id] = prod; - } - }); - }).error(function (error) { - ctrl.products = null; - ctrl.showError = true; - ctrl.error = - 'Error retrieving Products listing from server: ' + - angular.toJson(error); - }); - } - - /** - * Send a PUT request to the API server to associate a product with - * a test result. - */ - function associateProductVersion(result) { - var verId = (result.selectedVersion ? - result.selectedVersion.id : null); - var testId = result.id; - var url = testapiApiUrl + '/results/' + testId; - ctrl.associateRequest = $http.put(url, {'product_version_id': - verId}) - .success(function (data) { - result.product_version = result.selectedVersion; - if (result.selectedVersion) { - result.product_version.product_info = - result.selectedProduct; - } - result.productEdit = false; - }).error(function (error) { - raiseAlert('danger', error.title, error.detail); - }); - } - - /** - * Get all versions for a product. - */ - function getProductVersions(result) { - if (!result.selectedProduct) { - result.productVersions = []; - result.selectedVersion = null; - return; - } - - var url = testapiApiUrl + '/products/' + - result.selectedProduct.id + '/versions'; - ctrl.getVersionsRequest = $http.get(url) - .success(function (data) { - result.productVersions = data; - - // If the test result isn't already associated to a - // version, default it to the null version. - if (!result.product_version) { - angular.forEach(data, function(ver) { - if (!ver.version) { - result.selectedVersion = ver; - } - }); - } - }).error(function (error) { - raiseAlert('danger', error.title, error.detail); - }); - } - - /** - * Instantiate variables needed for editing product/version - * associations. - */ - function prepVersionEdit(result) { - result.productEdit = true; - if (result.product_version) { - result.selectedProduct = - ctrl.products[result.product_version.product_info.id]; - } - result.selectedVersion = result.product_version; - ctrl.getProductVersions(result); - } - - } -})(); |