Fix for levels mismatch in set request and environment

Error is rased now if nonexistent level specified in the set
resource value request. For instance we have env levels: ['a'].
Request to set resource value with levels ['a', 'b'] raises error
now.

Change-Id: I6ce8dc99b288196092a7e4cf69be9756d5b0f6dd
Closes-Bug: #1624271
Closes-Bug: #1614551
This commit is contained in:
Alexander Kislitsky 2016-09-16 16:07:55 +03:00
parent db53fcb187
commit 9390d0ad2b
6 changed files with 73 additions and 17 deletions

View File

@ -86,17 +86,15 @@ def get_resource_values(environment, levels, res_def):
if not res_values: if not res_values:
raise errors.TuningboxNotFound( raise errors.TuningboxNotFound(
"Resource values not found by environment {0}, " "Resource values not found by environment {0}, "
"resource definition {1}, level {2} with value {3}".format( "resource definition {1} for levels {2}".format(
environment.id, res_def.id, level_value.level.name, environment.id, res_def.id, levels
level_value.value
) )
) )
elif len(res_values) > 1: elif len(res_values) > 1:
raise errors.TuningboxIntegrityError( raise errors.TuningboxIntegrityError(
"Found more than one resource values for environment {0}, " "Found more than one resource values for environment {0}, "
"resource definition {1}, level {2} with value {3}".format( "resource definition {1} for levels {2}".format(
environment.id, res_def.id, level_value.level.name, environment.id, res_def.id, levels
level_value.value
) )
) )
return res_values[0] return res_values[0]

View File

@ -11,22 +11,33 @@
# under the License. # under the License.
import flask import flask
import werkzeug
import flask_restful import flask_restful
from flask_restful import fields from flask_restful import fields
from tuning_box import db from tuning_box import db
from tuning_box import errors
def iter_environment_level_values(environment, levels): def iter_environment_level_values(environment, levels):
env_levels = db.EnvironmentHierarchyLevel.get_for_environment(environment) env_levels = db.EnvironmentHierarchyLevel.get_for_environment(environment)
if len(env_levels) < len(levels):
raise errors.TuningboxNotFound(
"Levels {0} can't be matched with "
"environment {1} levels: {2}".format(
[l[0] for l in levels],
environment.id,
[l.name for l in env_levels]
)
)
level_pairs = zip(env_levels, levels) level_pairs = zip(env_levels, levels)
for env_level, (level_name, level_value) in level_pairs: for env_level, (level_name, level_value) in level_pairs:
if env_level.name != level_name: if env_level.name != level_name:
raise werkzeug.exceptions.BadRequest( raise errors.TuningboxNotFound(
"Unexpected level name '{0}'. Expected '{1}'.".format( "Unexpected level name '{0}'. Expected '{1}'.".format(
level_name, env_level.name)) level_name, env_level.name)
)
level_value_db = db.get_or_create( level_value_db = db.get_or_create(
db.EnvironmentHierarchyLevelValue, db.EnvironmentHierarchyLevelValue,
level=env_level, level=env_level,

View File

@ -10,9 +10,10 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import werkzeug import six
from tuning_box import db from tuning_box import db
from tuning_box import errors
from tuning_box.library import hierarchy_levels from tuning_box.library import hierarchy_levels
from tuning_box.tests.test_app import BaseTest from tuning_box.tests.test_app import BaseTest
@ -50,13 +51,13 @@ class TestLevelsHierarchy(BaseTest):
self._fixture() self._fixture()
with self.app.app_context(), db.db.session.begin(): with self.app.app_context(), db.db.session.begin():
exc = self.assertRaises( exc = self.assertRaises(
werkzeug.exceptions.BadRequest, errors.TuningboxNotFound,
hierarchy_levels.get_environment_level_value, hierarchy_levels.get_environment_level_value,
db.Environment(id=9), db.Environment(id=9),
[('lvlx', 'val1')], [('lvlx', 'val1')],
) )
self.assertEqual( self.assertEqual(
exc.description, six.text_type(exc),
"Unexpected level name 'lvlx'. Expected 'lvl1'.", "Unexpected level name 'lvlx'. Expected 'lvl1'.",
) )

View File

@ -105,3 +105,7 @@ class TestLibrary(BaseTest):
self.assertRaises(errors.TuningboxNotFound, self.assertRaises(errors.TuningboxNotFound,
library.get_resource_values, environment, library.get_resource_values, environment,
levels, res_def) levels, res_def)
# Test for empty levels
self.assertRaises(errors.TuningboxNotFound,
library.get_resource_values, environment,
(), res_def)

View File

@ -56,13 +56,14 @@ class TestResourceValues(BaseTest):
self.assertIsNone(level.parent) self.assertIsNone(level.parent)
def test_put_resource_values_bad_level(self): def test_put_resource_values_bad_level(self):
self.app.config["PROPAGATE_EXCEPTIONS"] = True
self._fixture() self._fixture()
res = self.client.put('/environments/9/lvlx/1/resources/5/values', res = self.client.put('/environments/9/lvlx/1/resources/5/values',
data={'k': 'v'}) data={'k': 'v'})
self.assertEqual(res.status_code, 400) self.assertEqual(res.status_code, 404)
self.assertEqual( self.assertEqual(
res.json, {"msg": "Unexpected level name 'lvlx'. Expected 'lvl1'."},
{"message": "Unexpected level name 'lvlx'. Expected 'lvl1'."}, res.json
) )
with self.app.app_context(): with self.app.app_context():
resource_values = db.ResourceValues.query.filter_by( resource_values = db.ResourceValues.query.filter_by(
@ -191,6 +192,46 @@ class TestResourceValues(BaseTest):
self.assertEqual({'key': 'key_value', 'key_x': 'key_x_value'}, self.assertEqual({'key': 'key_value', 'key_x': 'key_x_value'},
actual) actual)
def test_put_resource_values_levels_mismatch(self):
self.app.config["PROPAGATE_EXCEPTIONS"] = True
self._fixture()
env_id = 9
res_def_id = 5
levels = (('lvl1', 'val1'), ('lvl2', 'val2'), ('lvl3', 'val3'))
values = {'key': 'val'}
res = self._add_resource_values(
env_id, res_def_id, levels, values, expect_code=404)
self.assertEqual(
{'msg': "Levels [u'lvl1', u'lvl2', u'lvl3'] can't be matched with "
"environment 9 levels: [u'lvl1', u'lvl2']"},
res.json
)
def test_put_resource_values_levels_mismatch_for_empty_levels(self):
self.app.config["PROPAGATE_EXCEPTIONS"] = True
self._fixture()
env_id = 9
res_def_id = 5
levels = (('lvl1', 'val1'), ('lvl2', 'val2'), ('lvl3', 'val3'))
values = {'key': 'val'}
env_url = '/environments/{0}'.format(env_id)
res = self.client.put(env_url, data={'hierarchy_levels': []})
self.assertEqual(204, res.status_code)
res = self.client.get(env_url)
self.assertEqual(200, res.status_code)
self.assertEqual([], res.json['hierarchy_levels'])
res = self._add_resource_values(
env_id, res_def_id, levels, values, expect_code=404)
self.assertEqual(
{'msg': "Levels [u'lvl1', u'lvl2', u'lvl3'] can't be matched with "
"environment 9 levels: []"},
res.json
)
def test_put_resource_values_set_no_levels(self): def test_put_resource_values_set_no_levels(self):
self._fixture() self._fixture()
environment_id = 9 environment_id = 9

View File

@ -80,7 +80,7 @@ class BaseTest(base.TestCase):
return levels_url return levels_url
def _add_resource_values(self, environment_id, res_def_id, def _add_resource_values(self, environment_id, res_def_id,
levels, values): levels, values, expect_code=204):
res = self.client.put( res = self.client.put(
'/environments/{0}/{1}resources/{2}/values'.format( '/environments/{0}/{1}resources/{2}/values'.format(
environment_id, environment_id,
@ -89,7 +89,8 @@ class BaseTest(base.TestCase):
), ),
data=values data=values
) )
self.assertEqual(res.status_code, 204) self.assertEqual(expect_code, res.status_code)
return res
def _add_resource_overrides(self, environment_id, res_def_id, def _add_resource_overrides(self, environment_id, res_def_id,
levels, overrides): levels, overrides):