diff options
Diffstat (limited to 'utils/test/testapi')
5 files changed, 406 insertions, 100 deletions
diff --git a/utils/test/testapi/opnfv_testapi/resources/models.py b/utils/test/testapi/opnfv_testapi/resources/models.py index 6f04cc236..e70a6ed23 100644 --- a/utils/test/testapi/opnfv_testapi/resources/models.py +++ b/utils/test/testapi/opnfv_testapi/resources/models.py @@ -61,11 +61,11 @@ class ModelBase(object): '{} 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) + 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(item)) + value.append(attr_parser[k].from_dict_with_raise(item)) t.__setattr__(k, value) diff --git a/utils/test/testapi/opnfv_testapi/resources/scenario_handlers.py b/utils/test/testapi/opnfv_testapi/resources/scenario_handlers.py index d215d18b9..e9c19a7a4 100644 --- a/utils/test/testapi/opnfv_testapi/resources/scenario_handlers.py +++ b/utils/test/testapi/opnfv_testapi/resources/scenario_handlers.py @@ -114,8 +114,21 @@ class ScenarioGURHandler(GenericScenarioHandler): self._get_one(query={'name': name}) pass + @swagger.operation(nickname="updateScenarioName") def put(self, name): - pass + """ + @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): @@ -147,6 +160,12 @@ class ScenarioUpdater(object): ('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) @@ -210,42 +229,16 @@ class ScenarioUpdater(object): @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)) + version.projects = self._update_with_body(models.ScenarioProject, + 'project', + version.projects) @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 + version.projects = self._update_with_body(models.ScenarioProject, + 'project', + list()) @iter_installers @iter_versions @@ -257,12 +250,66 @@ class ScenarioUpdater(object): 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) @@ -602,3 +649,127 @@ class ScenarioOwnerHandler(GenericScenarioUpdateHandler): 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/resources/scenario_models.py b/utils/test/testapi/opnfv_testapi/resources/scenario_models.py index c6da76b81..d950ed1d7 100644 --- a/utils/test/testapi/opnfv_testapi/resources/scenario_models.py +++ b/utils/test/testapi/opnfv_testapi/resources/scenario_models.py @@ -167,6 +167,12 @@ class ScenarioChangeOwnerRequest(models.ModelBase): @swagger.model() +class ScenarioUpdateRequest(models.ModelBase): + def __init__(self, name=None): + self.name = name + + +@swagger.model() class Scenario(models.ModelBase): """ @property installers: diff --git a/utils/test/testapi/opnfv_testapi/router/url_mappings.py b/utils/test/testapi/opnfv_testapi/router/url_mappings.py index 9c9556c6b..3e3ab87aa 100644 --- a/utils/test/testapi/opnfv_testapi/router/url_mappings.py +++ b/utils/test/testapi/opnfv_testapi/router/url_mappings.py @@ -64,6 +64,10 @@ mappings = [ 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))', diff --git a/utils/test/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py b/utils/test/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py index 50a8c8d2d..1367fc669 100644 --- a/utils/test/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py +++ b/utils/test/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py @@ -2,7 +2,7 @@ import functools import httplib import json import os -from copy import deepcopy + from datetime import datetime from opnfv_testapi.common import message @@ -50,15 +50,15 @@ class TestScenarioBase(base.TestBase): self.assertEqual(scenario, models.Scenario.from_dict(req)) @staticmethod - def _set_query(*args): + def set_query(*args): uri = '' for arg in args: uri += arg + '&' return uri[0: -1] - def _get_and_assert(self, name, req=None): + def get_and_assert(self, name): code, body = self.get(name) - self.assert_res(code, body, req) + self.assert_res(code, body, self.req_d) class TestScenarioCreate(TestScenarioBase): @@ -97,25 +97,25 @@ class TestScenarioGet(TestScenarioBase): self.scenario_2 = self.create_return_name(self.req_2) def test_getByName(self): - self._get_and_assert(self.scenario_1, self.req_d) + 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') + 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') + 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') + 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') + 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 @@ -170,14 +170,21 @@ class TestScenarioUpdate(TestScenarioBase): 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) - self.update_url = '{}/{}?{}'.format(self.scenario_url, - item, - locator) + 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 @@ -186,139 +193,257 @@ class TestScenarioUpdate(TestScenarioBase): def _update_partial(set_update): @functools.wraps(set_update) def wrapper(self): - update, scenario = set_update(self, deepcopy(self.req_d)) - code, body = getattr(self, operate)(update, self.scenario) - getattr(self, expected)(code, scenario) + 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, scenario): + def test_addScore(self): add = models.ScenarioScore(date=str(datetime.now()), score='11/12') - projects = scenario['installers'][0]['versions'][0]['projects'] + 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, scenario + return add @update_partial('_add', '_success') - def test_addTrustIndicator(self, scenario): + def test_addTrustIndicator(self): add = models.ScenarioTI(date=str(datetime.now()), status='gold') - projects = scenario['installers'][0]['versions'][0]['projects'] + 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, scenario + return add @update_partial('_add', '_success') - def test_addCustoms(self, scenario): - add = ['odl', 'parser', 'vping_ssh'] - projects = scenario['installers'][0]['versions'][0]['projects'] + 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'] + add)) + functest['customs'] = list(set(functest['customs'] + adds)) self.update_url = '{}/customs?{}'.format(self.scenario_url, self.locate_project) - return add, scenario + return adds @update_partial('_update', '_success') - def test_updateCustoms(self, scenario): - news = ['odl', 'parser', 'vping_ssh'] - projects = scenario['installers'][0]['versions'][0]['projects'] + 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'] = news + functest['customs'] = updates self.update_url = '{}/customs?{}'.format(self.scenario_url, self.locate_project) - return news, scenario + return updates @update_partial('_delete', '_success') - def test_deleteCustoms(self, scenario): - obsoletes = ['vping_ssh'] - projects = scenario['installers'][0]['versions'][0]['projects'] + 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 obsoletes, scenario + return deletes @update_url_fixture('projects') @update_partial('_add', '_success') - def test_addProjects_succ(self, scenario): + def test_addProjects_succ(self): add = models.ScenarioProject(project='qtip').format() - scenario['installers'][0]['versions'][0]['projects'].append(add) - return [add], scenario + 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, scenario): + def test_addProjects_already_exist(self): add = models.ScenarioProject(project='functest').format() - scenario['installers'][0]['versions'][0]['projects'].append(add) - return [add], scenario + return [add] @update_url_fixture('projects') @update_partial('_add', '_bad_request') - def test_addProjects_bad_schema(self, scenario): + def test_addProjects_bad_schema(self): add = models.ScenarioProject(project='functest').format() add['score'] = None - scenario['installers'][0]['versions'][0]['projects'].append(add) - return [add], scenario + return [add] @update_url_fixture('projects') @update_partial('_update', '_success') - def test_updateProjects_succ(self, scenario): + def test_updateProjects_succ(self): update = models.ScenarioProject(project='qtip').format() - scenario['installers'][0]['versions'][0]['projects'] = [update] - return [update], scenario + 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, scenario): + def test_updateProjects_bad_schema(self): update = models.ScenarioProject(project='functest').format() update['score'] = None - scenario['installers'][0]['versions'][0]['projects'] = [update] - return [update], scenario + return [update] @update_url_fixture('projects') @update_partial('_delete', '_success') - def test_deleteProjects(self, scenario): + def test_deleteProjects(self): deletes = ['functest'] - projects = scenario['installers'][0]['versions'][0]['projects'] - scenario['installers'][0]['versions'][0]['projects'] = filter( + 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, scenario + return deletes @update_url_fixture('owner') @update_partial('_update', '_success') - def test_changeOwner(self, scenario): + def test_changeOwner(self): new_owner = 'new_owner' update = models.ScenarioChangeOwnerRequest(new_owner).format() - scenario['installers'][0]['versions'][0]['owner'] = new_owner - return update, scenario + 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] - def _add(self, update_req, new_scenario): + @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, new_scenario): + def _update(self, update_req): return self.update_direct_url(self.update_url, update_req) - def _delete(self, update_req, new_scenario): + def _delete(self, update_req): return self.delete_direct_url(self.update_url, update_req) - def _success(self, status, new_scenario): + def _success(self, status): self.assertEqual(status, httplib.OK) - self._get_and_assert(new_scenario.get('name'), new_scenario) + self.get_and_assert(self.req_d['name']) - def _forbidden(self, status, new_scenario): + def _forbidden(self, status): self.assertEqual(status, httplib.FORBIDDEN) - def _bad_request(self, status, new_scenario): + def _bad_request(self, status): self.assertEqual(status, httplib.BAD_REQUEST) - def _conflict(self, status, new_scenario): + def _conflict(self, status): self.assertEqual(status, httplib.CONFLICT) |