diff options
-rw-r--r-- | testapi/opnfv_testapi/resources/handlers.py | 11 | ||||
-rw-r--r-- | testapi/opnfv_testapi/resources/scenario_handlers.py | 168 | ||||
-rw-r--r-- | testapi/opnfv_testapi/router/url_mappings.py | 2 | ||||
-rw-r--r-- | testapi/opnfv_testapi/tests/unit/resources/test_base.py | 33 | ||||
-rw-r--r-- | testapi/opnfv_testapi/tests/unit/resources/test_scenario.py | 38 |
5 files changed, 222 insertions, 30 deletions
diff --git a/testapi/opnfv_testapi/resources/handlers.py b/testapi/opnfv_testapi/resources/handlers.py index 474a203..685687a 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): @@ -188,6 +188,15 @@ 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) + def _update_requests(self, data): request = dict() for k, v in self.json_args.iteritems(): diff --git a/testapi/opnfv_testapi/resources/scenario_handlers.py b/testapi/opnfv_testapi/resources/scenario_handlers.py index 66e8559..c3d471c 100644 --- a/testapi/opnfv_testapi/resources/scenario_handlers.py +++ b/testapi/opnfv_testapi/resources/scenario_handlers.py @@ -138,6 +138,9 @@ 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, } updates[(item, action)](self.data) @@ -178,6 +181,26 @@ 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) + def _filter_installers(self, installers): return self._filter('installer', installers) @@ -204,15 +227,16 @@ 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)) + self.finish_request() def _update_requests(self, data): return ScenarioUpdater(data, @@ -247,16 +271,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 +307,116 @@ 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}) diff --git a/testapi/opnfv_testapi/router/url_mappings.py b/testapi/opnfv_testapi/router/url_mappings.py index 4589425..4c30eb5 100644 --- a/testapi/opnfv_testapi/router/url_mappings.py +++ b/testapi/opnfv_testapi/router/url_mappings.py @@ -58,6 +58,8 @@ mappings = [ scenario_handlers.ScenarioScoresHandler), (r"/api/v1/scenarios/([^/]+)/trust_indicators", scenario_handlers.ScenarioTIsHandler), + (r"/api/v1/scenarios/([^/]+)/customs", + scenario_handlers.ScenarioCustomsHandler), # static path (r'/(.*\.(css|png|gif|js|html|json|map|woff2|woff|ttf))', diff --git a/testapi/opnfv_testapi/tests/unit/resources/test_base.py b/testapi/opnfv_testapi/tests/unit/resources/test_base.py index aa6b835..77a8d18 100644 --- a/testapi/opnfv_testapi/tests/unit/resources/test_base.py +++ b/testapi/opnfv_testapi/tests/unit/resources/test_base.py @@ -92,21 +92,35 @@ class TestBase(testing.AsyncHTTPTestCase): headers=self.headers) return self._get_return(res, self.list_res) - def update(self, new=None, *args): - if new: + def update_direct_url(self, url, new=None): + if new and hasattr(new, 'format'): new = new.format() - res = self.fetch(self._get_uri(*args), + res = self.fetch(url, method='PUT', body=json.dumps(new), headers=self.headers) return self._get_return(res, self.update_res) - def delete(self, *args): - res = self.fetch(self._get_uri(*args), - method='DELETE', - headers=self.headers) + 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]) @@ -132,7 +146,10 @@ class TestBase(testing.AsyncHTTPTestCase): def _get_return(self, res, cls): code = res.code body = res.body - return code, self._get_return_body(code, body, cls) + if body: + return code, self._get_return_body(code, body, cls) + else: + return code, None @staticmethod def _get_return_body(code, body, cls): diff --git a/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py b/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py index 0558ea3..ba45f4b 100644 --- a/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py +++ b/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py @@ -200,9 +200,47 @@ class TestScenarioUpdate(TestScenarioBase): return add, scenario + @update_partial('_add', '_success') + def test_addCustoms(self, scenario): + add = ['odl', 'parser', 'vping_ssh'] + projects = scenario['installers'][0]['versions'][0]['projects'] + functest = filter(lambda f: f['project'] == 'functest', projects)[0] + functest['customs'] = list(set(functest['customs'] + add)) + self.update_url = '{}/customs?{}'.format(self.scenario_url, + self.locate_project) + return add, scenario + + @update_partial('_update', '_success') + def test_updateCustoms(self, scenario): + news = ['odl', 'parser', 'vping_ssh'] + projects = scenario['installers'][0]['versions'][0]['projects'] + functest = filter(lambda f: f['project'] == 'functest', projects)[0] + functest['customs'] = news + self.update_url = '{}/customs?{}'.format(self.scenario_url, + self.locate_project) + + return news, scenario + + @update_partial('_delete', '_success') + def test_deleteCustoms(self, scenario): + obsoletes = ['vping_ssh'] + projects = scenario['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 obsoletes, scenario + def _add(self, update_req, new_scenario): return self.post_direct_url(self.update_url, update_req) + def _update(self, update_req, new_scenario): + return self.update_direct_url(self.update_url, update_req) + + def _delete(self, update_req, new_scenario): + return self.delete_direct_url(self.update_url, update_req) + def _success(self, status, new_scenario): self.assertEqual(status, httplib.OK) self._get_and_assert(new_scenario.get('name'), new_scenario) |