diff options
Diffstat (limited to 'utils')
-rw-r--r-- | utils/test/testapi/.gitignore | 3 | ||||
-rw-r--r-- | utils/test/testapi/docker/Dockerfile | 2 | ||||
-rwxr-xr-x | utils/test/testapi/install.sh | 30 | ||||
-rw-r--r-- | utils/test/testapi/opnfv_testapi/resources/scenario_handlers.py | 87 | ||||
-rw-r--r-- | utils/test/testapi/opnfv_testapi/resources/scenario_models.py | 6 | ||||
-rw-r--r-- | utils/test/testapi/opnfv_testapi/router/url_mappings.py | 2 | ||||
-rw-r--r-- | utils/test/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py | 247 | ||||
-rw-r--r-- | utils/test/testapi/setup.py | 9 |
8 files changed, 258 insertions, 128 deletions
diff --git a/utils/test/testapi/.gitignore b/utils/test/testapi/.gitignore index c7b63b5b1..00f8a03d0 100644 --- a/utils/test/testapi/.gitignore +++ b/utils/test/testapi/.gitignore @@ -1,4 +1,7 @@ AUTHORS ChangeLog setup.cfg-e +opnfv_testapi/static +build +*.egg-info diff --git a/utils/test/testapi/docker/Dockerfile b/utils/test/testapi/docker/Dockerfile index 5311f35b8..a46fce20a 100644 --- a/utils/test/testapi/docker/Dockerfile +++ b/utils/test/testapi/docker/Dockerfile @@ -47,5 +47,5 @@ RUN git clone https://gerrit.opnfv.org/gerrit/releng /home/releng WORKDIR /home/releng/utils/test/testapi/ RUN pip install -r requirements.txt -RUN bash install.sh +RUN python setup.py install CMD ["bash", "docker/start-server.sh"] diff --git a/utils/test/testapi/install.sh b/utils/test/testapi/install.sh deleted file mode 100755 index d470e38c3..000000000 --- a/utils/test/testapi/install.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -usage=" -Script to install opnfv_tesgtapi automatically. -This script should be run under root. - -usage: - bash $(basename "$0") [-h|--help] [-t <test_name>] - -where: - -h|--help show this help text" - -# Ref :- https://openstack.nimeyo.com/87286/openstack-packaging-all-definition-data-files-config-setup -if [ -z "$VIRTUAL_ENV" ]; -then - if [[ $(whoami) != "root" ]]; - then - echo "Error: This script must be run as root!" - exit 1 - fi -else - sed -i -e 's#/etc/opnfv_testapi =#etc/opnfv_testapi =#g' setup.cfg -fi - -cp -fr 3rd_party/static opnfv_testapi/static -python setup.py install -rm -fr opnfv_testapi/static -if [ ! -z "$VIRTUAL_ENV" ]; then - sed -i -e 's#etc/opnfv_testapi =#/etc/opnfv_testapi =#g' setup.cfg -fi
\ No newline at end of file diff --git a/utils/test/testapi/opnfv_testapi/resources/scenario_handlers.py b/utils/test/testapi/opnfv_testapi/resources/scenario_handlers.py index d6918a69b..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): @@ -150,6 +163,9 @@ class ScenarioUpdater(object): ('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) @@ -250,6 +266,19 @@ class ScenarioUpdater(object): 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() @@ -272,6 +301,9 @@ class ScenarioUpdater(object): 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) @@ -688,3 +720,56 @@ class ScenarioVersionsHandler(GenericScenarioUpdateHandler): '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 bdfc70154..3e3ab87aa 100644 --- a/utils/test/testapi/opnfv_testapi/router/url_mappings.py +++ b/utils/test/testapi/opnfv_testapi/router/url_mappings.py @@ -66,6 +66,8 @@ mappings = [ 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 360b4fa89..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,6 +170,7 @@ 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( @@ -178,10 +179,12 @@ class TestScenarioUpdate(TestScenarioBase): 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) - self.update_url = '{}/{}?{}'.format(self.scenario_url, - item, - locator) xstep(self, *args, **kwargs) return wrapper return _update_url_fixture @@ -190,203 +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, scenario): - update1 = models.ScenarioProject(project='qtip').format() - update2 = models.ScenarioProject(project='qtip').format() - scenario['installers'][0]['versions'][0]['projects'] = [update1, - update2] - return [update1, update2], scenario + 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, scenario): + def test_addVersions_succ(self): add = models.ScenarioVersion(version='Euphrates').format() - scenario['installers'][0]['versions'].append(add) - return [add], scenario + self.req_d['installers'][0]['versions'].append(add) + return [add] @update_url_fixture('versions') @update_partial('_add', '_conflict') - def test_addVersions_already_exist(self, scenario): + def test_addVersions_already_exist(self): add = models.ScenarioVersion(version='master').format() - scenario['installers'][0]['versions'].append(add) - return [add], scenario + return [add] @update_url_fixture('versions') @update_partial('_add', '_bad_request') - def test_addVersions_bad_schema(self, scenario): + def test_addVersions_bad_schema(self): add = models.ScenarioVersion(version='euphrates').format() add['notexist'] = None - scenario['installers'][0]['versions'].append(add) - return [add], scenario + return [add] @update_url_fixture('versions') @update_partial('_update', '_success') - def test_updateVersions_succ(self, scenario): + def test_updateVersions_succ(self): update = models.ScenarioVersion(version='euphrates').format() - scenario['installers'][0]['versions'] = [update] - return [update], scenario + self.req_d['installers'][0]['versions'] = [update] + return [update] @update_url_fixture('versions') @update_partial('_update', '_conflict') - def test_updateVersions_duplicated(self, scenario): - update1 = models.ScenarioVersion(version='euphrates').format() - update2 = models.ScenarioVersion(version='euphrates').format() - scenario['installers'][0]['versions'] = [update1, update2] - return [update1, update2], scenario + 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, scenario): + def test_updateVersions_bad_schema(self): update = models.ScenarioVersion(version='euphrates').format() update['not_owner'] = 'Iam' - scenario['installers'][0]['versions'] = [update] - return [update], scenario + return [update] @update_url_fixture('versions') @update_partial('_delete', '_success') - def test_deleteVersions(self, scenario): + def test_deleteVersions(self): deletes = ['master'] - versions = scenario['installers'][0]['versions'] - scenario['installers'][0]['versions'] = filter( + versions = self.req_d['installers'][0]['versions'] + self.req_d['installers'][0]['versions'] = filter( lambda f: f['version'] != 'master', versions) - return deletes, scenario + 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] - def _add(self, update_req, new_scenario): + @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) diff --git a/utils/test/testapi/setup.py b/utils/test/testapi/setup.py index f689cb30e..dd52373fd 100644 --- a/utils/test/testapi/setup.py +++ b/utils/test/testapi/setup.py @@ -1,5 +1,7 @@ -import setuptools +import os +import subprocess +import setuptools __author__ = 'serena' @@ -8,6 +10,11 @@ try: except ImportError: pass +dirpath = os.path.dirname(os.path.abspath(__file__)) +subprocess.call(['ln', '-s', + '{}/3rd_party/static'.format(dirpath), + '{}/opnfv_testapi/static'.format(dirpath)]) + setuptools.setup( setup_requires=['pbr==2.0.0'], pbr=True) |