summaryrefslogtreecommitdiffstats
path: root/testapi/opnfv_testapi/resources
diff options
context:
space:
mode:
Diffstat (limited to 'testapi/opnfv_testapi/resources')
-rw-r--r--testapi/opnfv_testapi/resources/handlers.py12
-rw-r--r--testapi/opnfv_testapi/resources/models.py23
-rw-r--r--testapi/opnfv_testapi/resources/scenario_handlers.py350
-rw-r--r--testapi/opnfv_testapi/resources/scenario_models.py7
4 files changed, 368 insertions, 24 deletions
diff --git a/testapi/opnfv_testapi/resources/handlers.py b/testapi/opnfv_testapi/resources/handlers.py
index 73afabe..ed55c70 100644
--- a/testapi/opnfv_testapi/resources/handlers.py
+++ b/testapi/opnfv_testapi/resources/handlers.py
@@ -50,7 +50,7 @@ class GenericApiHandler(web.RequestHandler):
self.auth = self.settings["auth"]
def prepare(self):
- if self.request.method != "GET" and self.request.method != "DELETE":
+ if self.request.body:
if self.request.headers.get("Content-Type") is not None:
if self.request.headers["Content-Type"].startswith(
DEFAULT_REPRESENTATION):
@@ -189,6 +189,16 @@ class GenericApiHandler(web.RequestHandler):
update_req['_id'] = str(data._id)
self.finish_request(update_req)
+ @check.authenticate
+ @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():
diff --git a/testapi/opnfv_testapi/resources/models.py b/testapi/opnfv_testapi/resources/models.py
index e8fc532..6f04cc2 100644
--- a/testapi/opnfv_testapi/resources/models.py
+++ b/testapi/opnfv_testapi/resources/models.py
@@ -48,6 +48,29 @@ class ModelBase(object):
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(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
+
@staticmethod
def attr_parser():
return {}
diff --git a/testapi/opnfv_testapi/resources/scenario_handlers.py b/testapi/opnfv_testapi/resources/scenario_handlers.py
index 66e8559..bd06400 100644
--- a/testapi/opnfv_testapi/resources/scenario_handlers.py
+++ b/testapi/opnfv_testapi/resources/scenario_handlers.py
@@ -1,5 +1,7 @@
import functools
+from opnfv_testapi.common import message
+from opnfv_testapi.common import raises
from opnfv_testapi.resources import handlers
import opnfv_testapi.resources.scenario_models as models
from opnfv_testapi.tornado_swagger import swagger
@@ -138,6 +140,13 @@ class ScenarioUpdater(object):
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,
}
updates[(item, action)](self.data)
@@ -178,6 +187,76 @@ class ScenarioUpdater(object):
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):
+ exists = list()
+ malformat = list()
+ for n in self.body:
+ try:
+ f_n = models.ScenarioProject.from_dict_with_raise(n)
+ if not any(o.project == f_n.project for o in version.projects):
+ version.projects.append(f_n)
+ else:
+ exists.append(n['project'])
+ except Exception as e:
+ malformat.append(e.message)
+ if malformat:
+ raises.BadRequest(message.bad_format(malformat))
+ elif exists:
+ raises.Conflict(message.exist('projects', exists))
+
+ @iter_installers
+ @iter_versions
+ def _update_requests_update_projects(self, version):
+ exists = list()
+ malformat = list()
+ projects = list()
+ for n in self.body:
+ try:
+ f_n = models.ScenarioProject.from_dict_with_raise(n)
+ if not any(o.project == f_n.project for o in projects):
+ projects.append(models.ScenarioProject.from_dict(n))
+ else:
+ exists.append(n['project'])
+ except:
+ malformat.append(n)
+ if malformat:
+ raises.BadRequest(message.bad_format(malformat))
+ elif exists:
+ raises.Forbidden(message.exist('projects', exists))
+ version.projects = projects
+
+ @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
+
def _filter_installers(self, installers):
return self._filter('installer', installers)
@@ -187,11 +266,19 @@ class ScenarioUpdater(object):
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):
@@ -204,15 +291,15 @@ class GenericScenarioUpdateHandler(GenericScenarioHandler):
self.item = None
self.action = None
- def do_post(self, scenario, item, action, locators):
+ def do_update(self, item, action, locators):
self.item = item
self.action = action
- for k in locators.keys():
- v = self.get_query_argument(k)
- setattr(self, k, v)
- locators[k] = v
- db_keys = ['name']
- self._update(query=self.set_query(locators=locators), db_keys=db_keys)
+ 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,
@@ -247,16 +334,15 @@ class ScenarioScoresHandler(GenericScenarioUpdateHandler):
@type project: L{string}
@in project: query
@required project: True
- @rtype: L{Scenario}
@return 200: score is created.
@raise 404: scenario/installer/version/project not existed
"""
- self.do_post(scenario,
- 'scores',
- 'post',
- locators={'installer': None,
- 'version': None,
- 'project': None})
+ self.do_update('scores',
+ 'post',
+ locators={'scenario': scenario,
+ 'installer': None,
+ 'version': None,
+ 'project': None})
class ScenarioTIsHandler(GenericScenarioUpdateHandler):
@@ -284,13 +370,235 @@ class ScenarioTIsHandler(GenericScenarioUpdateHandler):
@type project: L{string}
@in project: query
@required project: True
- @rtype: L{Scenario}
@return 200: trust indicator is added.
@raise 404: scenario/installer/version/project not existed
"""
- self.do_post(scenario,
- 'trust_indicators',
- 'post',
- locators={'installer': None,
- 'version': None,
- 'project': None})
+ 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{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: change owner success.
+ @raise 404: scenario/installer/version not existed
+ """
+ self.do_update('owner',
+ 'put',
+ locators={'scenario': scenario,
+ 'installer': None,
+ 'version': None})
diff --git a/testapi/opnfv_testapi/resources/scenario_models.py b/testapi/opnfv_testapi/resources/scenario_models.py
index 9f5a074..7d07707 100644
--- a/testapi/opnfv_testapi/resources/scenario_models.py
+++ b/testapi/opnfv_testapi/resources/scenario_models.py
@@ -74,7 +74,8 @@ class ScenarioVersion(models.ModelBase):
@property projects:
@ptype projects: C{list} of L{ScenarioProject}
"""
- def __init__(self, version=None, projects=None):
+ def __init__(self, owner=None, version=None, projects=None):
+ self.owner = owner
self.version = version
self.projects = list_default(projects)
@@ -83,7 +84,9 @@ class ScenarioVersion(models.ModelBase):
return {'projects': ScenarioProject}
def __eq__(self, other):
- return [self.version == other.version and self._projects_eq(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)