summaryrefslogtreecommitdiffstats
path: root/testapi
diff options
context:
space:
mode:
authorSerenaFeng <feng.xiaowei@zte.com.cn>2017-08-23 14:04:59 +0800
committerSerenaFeng <feng.xiaowei@zte.com.cn>2017-08-25 13:54:16 +0800
commit3fbd55c9b9550c0248827eb705d60ec2ce4cc658 (patch)
treead23ede8955e4ac439ae34e57f8f5ecde871e8fa /testapi
parent2eb503cb2e3496131c21954506da58b056c8fb46 (diff)
update versions under scenario
1. post, add one or more new versions 2. update, replace existed version as a totality 3. delete, delete one or more versions by name 4. in post&update, if schema is not consistent with ScenarioVersion model, BadRequest will be raised(only extra keys will be detected currently) 5. in post, if project already exist, return Conflict with already exist message 6. in update, if a version appears more than once, also return Conflict with already exist message 7. add update with conflict unittest for projects Change-Id: I0d2c8a5567f3abce7b0313a64e18303af02cc002 Signed-off-by: SerenaFeng <feng.xiaowei@zte.com.cn>
Diffstat (limited to 'testapi')
-rw-r--r--testapi/opnfv_testapi/resources/models.py4
-rw-r--r--testapi/opnfv_testapi/resources/scenario_handlers.py150
-rw-r--r--testapi/opnfv_testapi/router/url_mappings.py2
-rw-r--r--testapi/opnfv_testapi/tests/unit/resources/test_scenario.py68
4 files changed, 190 insertions, 34 deletions
diff --git a/testapi/opnfv_testapi/resources/models.py b/testapi/opnfv_testapi/resources/models.py
index 6f04cc2..e70a6ed 100644
--- a/testapi/opnfv_testapi/resources/models.py
+++ b/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/testapi/opnfv_testapi/resources/scenario_handlers.py b/testapi/opnfv_testapi/resources/scenario_handlers.py
index d215d18..d6918a6 100644
--- a/testapi/opnfv_testapi/resources/scenario_handlers.py
+++ b/testapi/opnfv_testapi/resources/scenario_handlers.py
@@ -147,6 +147,9 @@ 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,
}
updates[(item, action)](self.data)
@@ -210,42 +213,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 +234,50 @@ 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_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 _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 +617,74 @@ 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})
diff --git a/testapi/opnfv_testapi/router/url_mappings.py b/testapi/opnfv_testapi/router/url_mappings.py
index 9c9556c..bdfc701 100644
--- a/testapi/opnfv_testapi/router/url_mappings.py
+++ b/testapi/opnfv_testapi/router/url_mappings.py
@@ -64,6 +64,8 @@ mappings = [
scenario_handlers.ScenarioProjectsHandler),
(r"/api/v1/scenarios/([^/]+)/owner",
scenario_handlers.ScenarioOwnerHandler),
+ (r"/api/v1/scenarios/([^/]+)/versions",
+ scenario_handlers.ScenarioVersionsHandler),
# static path
(r'/(.*\.(css|png|gif|js|html|json|map|woff2|woff|ttf))',
diff --git a/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py b/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py
index 50a8c8d..360b4fa 100644
--- a/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py
+++ b/testapi/opnfv_testapi/tests/unit/resources/test_scenario.py
@@ -175,6 +175,10 @@ class TestScenarioUpdate(TestScenarioBase):
locator = 'installer={}&version={}'.format(
self.installer,
self.version)
+ elif item in ['versions']:
+ locator = 'installer={}'.format(
+ self.installer)
+
self.update_url = '{}/{}?{}'.format(self.scenario_url,
item,
locator)
@@ -276,6 +280,15 @@ class TestScenarioUpdate(TestScenarioBase):
return [update], scenario
@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
+
+ @update_url_fixture('projects')
@update_partial('_update', '_bad_request')
def test_updateProjects_bad_schema(self, scenario):
update = models.ScenarioProject(project='functest').format()
@@ -301,6 +314,61 @@ class TestScenarioUpdate(TestScenarioBase):
scenario['installers'][0]['versions'][0]['owner'] = new_owner
return update, scenario
+ @update_url_fixture('versions')
+ @update_partial('_add', '_success')
+ def test_addVersions_succ(self, scenario):
+ add = models.ScenarioVersion(version='Euphrates').format()
+ scenario['installers'][0]['versions'].append(add)
+ return [add], scenario
+
+ @update_url_fixture('versions')
+ @update_partial('_add', '_conflict')
+ def test_addVersions_already_exist(self, scenario):
+ add = models.ScenarioVersion(version='master').format()
+ scenario['installers'][0]['versions'].append(add)
+ return [add], scenario
+
+ @update_url_fixture('versions')
+ @update_partial('_add', '_bad_request')
+ def test_addVersions_bad_schema(self, scenario):
+ add = models.ScenarioVersion(version='euphrates').format()
+ add['notexist'] = None
+ scenario['installers'][0]['versions'].append(add)
+ return [add], scenario
+
+ @update_url_fixture('versions')
+ @update_partial('_update', '_success')
+ def test_updateVersions_succ(self, scenario):
+ update = models.ScenarioVersion(version='euphrates').format()
+ scenario['installers'][0]['versions'] = [update]
+ return [update], scenario
+
+ @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
+
+ @update_url_fixture('versions')
+ @update_partial('_update', '_bad_request')
+ def test_updateVersions_bad_schema(self, scenario):
+ update = models.ScenarioVersion(version='euphrates').format()
+ update['not_owner'] = 'Iam'
+ scenario['installers'][0]['versions'] = [update]
+ return [update], scenario
+
+ @update_url_fixture('versions')
+ @update_partial('_delete', '_success')
+ def test_deleteVersions(self, scenario):
+ deletes = ['master']
+ versions = scenario['installers'][0]['versions']
+ scenario['installers'][0]['versions'] = filter(
+ lambda f: f['version'] != 'master',
+ versions)
+ return deletes, scenario
+
def _add(self, update_req, new_scenario):
return self.post_direct_url(self.update_url, update_req)