Fix sort of *list command output
While sorting output of list command ("audittemplate list", "strategy list", etc) by sort-key that is not belongs to specific model, this sort-key was passed to db what caused error (HTTP 500). We added check on such keys and now, if got one of them, then we make sort on API side instead of db side. We removed excess sort and changed all sorting routines to unified way. Also added sort tests on every model. Change-Id: I41faea1622605ee4fa8dc48cd572876d75be8383 Closes-Bug: 1662887
This commit is contained in:
parent
56bcba2dc0
commit
3075723da9
|
@ -205,7 +205,7 @@ class ActionCollection(collection.Collection):
|
|||
collection = ActionCollection()
|
||||
collection.actions = [Action.convert_with_links(p, expand)
|
||||
for p in actions]
|
||||
|
||||
collection.next = collection.get_next(limit, url=url, **kwargs)
|
||||
return collection
|
||||
|
||||
@classmethod
|
||||
|
@ -232,6 +232,10 @@ class ActionsController(rest.RestController):
|
|||
sort_key, sort_dir, expand=False,
|
||||
resource_url=None,
|
||||
action_plan_uuid=None, audit_uuid=None):
|
||||
additional_fields = ['action_plan_uuid']
|
||||
|
||||
api_utils.validate_sort_key(sort_key, list(objects.Action.fields) +
|
||||
additional_fields)
|
||||
limit = api_utils.validate_limit(limit)
|
||||
api_utils.validate_sort_dir(sort_dir)
|
||||
|
||||
|
@ -247,7 +251,10 @@ class ActionsController(rest.RestController):
|
|||
if audit_uuid:
|
||||
filters['audit_uuid'] = audit_uuid
|
||||
|
||||
sort_db_key = sort_key
|
||||
need_api_sort = api_utils.check_need_api_sort(sort_key,
|
||||
additional_fields)
|
||||
sort_db_key = (sort_key if not need_api_sort
|
||||
else None)
|
||||
|
||||
actions = objects.Action.list(pecan.request.context,
|
||||
limit,
|
||||
|
@ -255,11 +262,15 @@ class ActionsController(rest.RestController):
|
|||
sort_dir=sort_dir,
|
||||
filters=filters)
|
||||
|
||||
return ActionCollection.convert_with_links(actions, limit,
|
||||
url=resource_url,
|
||||
expand=expand,
|
||||
sort_key=sort_key,
|
||||
sort_dir=sort_dir)
|
||||
actions_collection = ActionCollection.convert_with_links(
|
||||
actions, limit, url=resource_url, expand=expand,
|
||||
sort_key=sort_key, sort_dir=sort_dir)
|
||||
|
||||
if need_api_sort:
|
||||
api_utils.make_api_sort(actions_collection.actions,
|
||||
sort_key, sort_dir)
|
||||
|
||||
return actions_collection
|
||||
|
||||
@wsme_pecan.wsexpose(ActionCollection, types.uuid, int,
|
||||
wtypes.text, wtypes.text, types.uuid,
|
||||
|
|
|
@ -305,17 +305,6 @@ class ActionPlanCollection(collection.Collection):
|
|||
ap_collection = ActionPlanCollection()
|
||||
ap_collection.action_plans = [ActionPlan.convert_with_links(
|
||||
p, expand) for p in rpc_action_plans]
|
||||
|
||||
if 'sort_key' in kwargs:
|
||||
reverse = False
|
||||
if kwargs['sort_key'] == 'audit_uuid':
|
||||
if 'sort_dir' in kwargs:
|
||||
reverse = True if kwargs['sort_dir'] == 'desc' else False
|
||||
ap_collection.action_plans = sorted(
|
||||
ap_collection.action_plans,
|
||||
key=lambda action_plan: action_plan.audit_uuid,
|
||||
reverse=reverse)
|
||||
|
||||
ap_collection.next = ap_collection.get_next(limit, url=url, **kwargs)
|
||||
return ap_collection
|
||||
|
||||
|
@ -344,7 +333,10 @@ class ActionPlansController(rest.RestController):
|
|||
sort_key, sort_dir, expand=False,
|
||||
resource_url=None, audit_uuid=None,
|
||||
strategy=None):
|
||||
additional_fields = ['audit_uuid', 'strategy_uuid', 'strategy_name']
|
||||
|
||||
api_utils.validate_sort_key(
|
||||
sort_key, list(objects.ActionPlan.fields) + additional_fields)
|
||||
limit = api_utils.validate_limit(limit)
|
||||
api_utils.validate_sort_dir(sort_dir)
|
||||
|
||||
|
@ -363,10 +355,10 @@ class ActionPlansController(rest.RestController):
|
|||
else:
|
||||
filters['strategy_name'] = strategy
|
||||
|
||||
if sort_key == 'audit_uuid':
|
||||
sort_db_key = None
|
||||
else:
|
||||
sort_db_key = sort_key
|
||||
need_api_sort = api_utils.check_need_api_sort(sort_key,
|
||||
additional_fields)
|
||||
sort_db_key = (sort_key if not need_api_sort
|
||||
else None)
|
||||
|
||||
action_plans = objects.ActionPlan.list(
|
||||
pecan.request.context,
|
||||
|
@ -374,12 +366,15 @@ class ActionPlansController(rest.RestController):
|
|||
marker_obj, sort_key=sort_db_key,
|
||||
sort_dir=sort_dir, filters=filters)
|
||||
|
||||
return ActionPlanCollection.convert_with_links(
|
||||
action_plans, limit,
|
||||
url=resource_url,
|
||||
expand=expand,
|
||||
sort_key=sort_key,
|
||||
sort_dir=sort_dir)
|
||||
action_plans_collection = ActionPlanCollection.convert_with_links(
|
||||
action_plans, limit, url=resource_url, expand=expand,
|
||||
sort_key=sort_key, sort_dir=sort_dir)
|
||||
|
||||
if need_api_sort:
|
||||
api_utils.make_api_sort(action_plans_collection.action_plans,
|
||||
sort_key, sort_dir)
|
||||
|
||||
return action_plans_collection
|
||||
|
||||
@wsme_pecan.wsexpose(ActionPlanCollection, types.uuid, int, wtypes.text,
|
||||
wtypes.text, types.uuid, wtypes.text)
|
||||
|
|
|
@ -389,17 +389,6 @@ class AuditCollection(collection.Collection):
|
|||
collection = AuditCollection()
|
||||
collection.audits = [Audit.convert_with_links(p, expand)
|
||||
for p in rpc_audits]
|
||||
|
||||
if 'sort_key' in kwargs:
|
||||
reverse = False
|
||||
if kwargs['sort_key'] == 'goal_uuid':
|
||||
if 'sort_dir' in kwargs:
|
||||
reverse = True if kwargs['sort_dir'] == 'desc' else False
|
||||
collection.audits = sorted(
|
||||
collection.audits,
|
||||
key=lambda audit: audit.goal_uuid,
|
||||
reverse=reverse)
|
||||
|
||||
collection.next = collection.get_next(limit, url=url, **kwargs)
|
||||
return collection
|
||||
|
||||
|
@ -427,8 +416,14 @@ class AuditsController(rest.RestController):
|
|||
sort_key, sort_dir, expand=False,
|
||||
resource_url=None, goal=None,
|
||||
strategy=None):
|
||||
additional_fields = ["goal_uuid", "goal_name", "strategy_uuid",
|
||||
"strategy_name"]
|
||||
|
||||
api_utils.validate_sort_key(
|
||||
sort_key, list(objects.Audit.fields) + additional_fields)
|
||||
limit = api_utils.validate_limit(limit)
|
||||
api_utils.validate_sort_dir(sort_dir)
|
||||
|
||||
marker_obj = None
|
||||
if marker:
|
||||
marker_obj = objects.Audit.get_by_uuid(pecan.request.context,
|
||||
|
@ -449,23 +444,25 @@ class AuditsController(rest.RestController):
|
|||
# TODO(michaelgugino): add method to get goal by name.
|
||||
filters['strategy_name'] = strategy
|
||||
|
||||
if sort_key == 'goal_uuid':
|
||||
sort_db_key = 'goal_id'
|
||||
elif sort_key == 'strategy_uuid':
|
||||
sort_db_key = 'strategy_id'
|
||||
else:
|
||||
sort_db_key = sort_key
|
||||
need_api_sort = api_utils.check_need_api_sort(sort_key,
|
||||
additional_fields)
|
||||
sort_db_key = (sort_key if not need_api_sort
|
||||
else None)
|
||||
|
||||
audits = objects.Audit.list(pecan.request.context,
|
||||
limit,
|
||||
marker_obj, sort_key=sort_db_key,
|
||||
sort_dir=sort_dir, filters=filters)
|
||||
|
||||
return AuditCollection.convert_with_links(audits, limit,
|
||||
url=resource_url,
|
||||
expand=expand,
|
||||
sort_key=sort_key,
|
||||
sort_dir=sort_dir)
|
||||
audits_collection = AuditCollection.convert_with_links(
|
||||
audits, limit, url=resource_url, expand=expand,
|
||||
sort_key=sort_key, sort_dir=sort_dir)
|
||||
|
||||
if need_api_sort:
|
||||
api_utils.make_api_sort(audits_collection.audits, sort_key,
|
||||
sort_dir)
|
||||
|
||||
return audits_collection
|
||||
|
||||
@wsme_pecan.wsexpose(AuditCollection, types.uuid, int, wtypes.text,
|
||||
wtypes.text, wtypes.text, wtypes.text, int)
|
||||
|
|
|
@ -474,9 +474,13 @@ class AuditTemplatesController(rest.RestController):
|
|||
def _get_audit_templates_collection(self, filters, marker, limit,
|
||||
sort_key, sort_dir, expand=False,
|
||||
resource_url=None):
|
||||
additional_fields = ["goal_uuid", "goal_name", "strategy_uuid",
|
||||
"strategy_name"]
|
||||
|
||||
api_utils.validate_sort_key(
|
||||
sort_key, list(objects.AuditTemplate.fields) + additional_fields)
|
||||
api_utils.validate_search_filters(
|
||||
filters, list(objects.audit_template.AuditTemplate.fields) +
|
||||
["goal_uuid", "goal_name", "strategy_uuid", "strategy_name"])
|
||||
filters, list(objects.AuditTemplate.fields) + additional_fields)
|
||||
limit = api_utils.validate_limit(limit)
|
||||
api_utils.validate_sort_dir(sort_dir)
|
||||
|
||||
|
@ -486,19 +490,26 @@ class AuditTemplatesController(rest.RestController):
|
|||
pecan.request.context,
|
||||
marker)
|
||||
|
||||
audit_templates = objects.AuditTemplate.list(
|
||||
pecan.request.context,
|
||||
filters,
|
||||
limit,
|
||||
marker_obj, sort_key=sort_key,
|
||||
sort_dir=sort_dir)
|
||||
need_api_sort = api_utils.check_need_api_sort(sort_key,
|
||||
additional_fields)
|
||||
sort_db_key = (sort_key if not need_api_sort
|
||||
else None)
|
||||
|
||||
return AuditTemplateCollection.convert_with_links(audit_templates,
|
||||
limit,
|
||||
url=resource_url,
|
||||
expand=expand,
|
||||
sort_key=sort_key,
|
||||
sort_dir=sort_dir)
|
||||
audit_templates = objects.AuditTemplate.list(
|
||||
pecan.request.context, filters, limit, marker_obj,
|
||||
sort_key=sort_db_key, sort_dir=sort_dir)
|
||||
|
||||
audit_templates_collection = \
|
||||
AuditTemplateCollection.convert_with_links(
|
||||
audit_templates, limit, url=resource_url, expand=expand,
|
||||
sort_key=sort_key, sort_dir=sort_dir)
|
||||
|
||||
if need_api_sort:
|
||||
api_utils.make_api_sort(
|
||||
audit_templates_collection.audit_templates, sort_key,
|
||||
sort_dir)
|
||||
|
||||
return audit_templates_collection
|
||||
|
||||
@wsme_pecan.wsexpose(AuditTemplateCollection, wtypes.text, wtypes.text,
|
||||
types.uuid, int, wtypes.text, wtypes.text)
|
||||
|
|
|
@ -130,17 +130,6 @@ class GoalCollection(collection.Collection):
|
|||
goal_collection = GoalCollection()
|
||||
goal_collection.goals = [
|
||||
Goal.convert_with_links(g, expand) for g in goals]
|
||||
|
||||
if 'sort_key' in kwargs:
|
||||
reverse = False
|
||||
if kwargs['sort_key'] == 'strategy':
|
||||
if 'sort_dir' in kwargs:
|
||||
reverse = True if kwargs['sort_dir'] == 'desc' else False
|
||||
goal_collection.goals = sorted(
|
||||
goal_collection.goals,
|
||||
key=lambda goal: goal.uuid,
|
||||
reverse=reverse)
|
||||
|
||||
goal_collection.next = goal_collection.get_next(
|
||||
limit, url=url, **kwargs)
|
||||
return goal_collection
|
||||
|
@ -167,17 +156,19 @@ class GoalsController(rest.RestController):
|
|||
|
||||
def _get_goals_collection(self, marker, limit, sort_key, sort_dir,
|
||||
expand=False, resource_url=None):
|
||||
api_utils.validate_sort_key(
|
||||
sort_key, list(objects.Goal.fields))
|
||||
limit = api_utils.validate_limit(limit)
|
||||
api_utils.validate_sort_dir(sort_dir)
|
||||
|
||||
sort_db_key = (sort_key if sort_key in objects.Goal.fields
|
||||
else None)
|
||||
|
||||
marker_obj = None
|
||||
if marker:
|
||||
marker_obj = objects.Goal.get_by_uuid(
|
||||
pecan.request.context, marker)
|
||||
|
||||
sort_db_key = (sort_key if sort_key in objects.Goal.fields
|
||||
else None)
|
||||
|
||||
goals = objects.Goal.list(pecan.request.context, limit, marker_obj,
|
||||
sort_key=sort_db_key, sort_dir=sort_dir)
|
||||
|
||||
|
|
|
@ -123,17 +123,6 @@ class ScoringEngineCollection(collection.Collection):
|
|||
collection = ScoringEngineCollection()
|
||||
collection.scoring_engines = [ScoringEngine.convert_with_links(
|
||||
se, expand) for se in scoring_engines]
|
||||
|
||||
if 'sort_key' in kwargs:
|
||||
reverse = False
|
||||
if kwargs['sort_key'] == 'name':
|
||||
if 'sort_dir' in kwargs:
|
||||
reverse = True if kwargs['sort_dir'] == 'desc' else False
|
||||
collection.goals = sorted(
|
||||
collection.scoring_engines,
|
||||
key=lambda se: se.name,
|
||||
reverse=reverse)
|
||||
|
||||
collection.next = collection.get_next(limit, url=url, **kwargs)
|
||||
return collection
|
||||
|
||||
|
@ -160,7 +149,8 @@ class ScoringEngineController(rest.RestController):
|
|||
def _get_scoring_engines_collection(self, marker, limit,
|
||||
sort_key, sort_dir, expand=False,
|
||||
resource_url=None):
|
||||
|
||||
api_utils.validate_sort_key(
|
||||
sort_key, list(objects.ScoringEngine.fields))
|
||||
limit = api_utils.validate_limit(limit)
|
||||
api_utils.validate_sort_dir(sort_dir)
|
||||
|
||||
|
@ -171,7 +161,8 @@ class ScoringEngineController(rest.RestController):
|
|||
|
||||
filters = {}
|
||||
|
||||
sort_db_key = sort_key
|
||||
sort_db_key = (sort_key if sort_key in objects.ScoringEngine.fields
|
||||
else None)
|
||||
|
||||
scoring_engines = objects.ScoringEngine.list(
|
||||
context=pecan.request.context,
|
||||
|
|
|
@ -154,17 +154,6 @@ class ServiceCollection(collection.Collection):
|
|||
service_collection = ServiceCollection()
|
||||
service_collection.services = [
|
||||
Service.convert_with_links(g, expand) for g in services]
|
||||
|
||||
if 'sort_key' in kwargs:
|
||||
reverse = False
|
||||
if kwargs['sort_key'] == 'service':
|
||||
if 'sort_dir' in kwargs:
|
||||
reverse = True if kwargs['sort_dir'] == 'desc' else False
|
||||
service_collection.services = sorted(
|
||||
service_collection.services,
|
||||
key=lambda service: service.id,
|
||||
reverse=reverse)
|
||||
|
||||
service_collection.next = service_collection.get_next(
|
||||
limit, url=url, marker_field='id', **kwargs)
|
||||
return service_collection
|
||||
|
@ -191,17 +180,19 @@ class ServicesController(rest.RestController):
|
|||
|
||||
def _get_services_collection(self, marker, limit, sort_key, sort_dir,
|
||||
expand=False, resource_url=None):
|
||||
api_utils.validate_sort_key(
|
||||
sort_key, list(objects.Service.fields))
|
||||
limit = api_utils.validate_limit(limit)
|
||||
api_utils.validate_sort_dir(sort_dir)
|
||||
|
||||
sort_db_key = (sort_key if sort_key in objects.Service.fields
|
||||
else None)
|
||||
|
||||
marker_obj = None
|
||||
if marker:
|
||||
marker_obj = objects.Service.get(
|
||||
pecan.request.context, marker)
|
||||
|
||||
sort_db_key = (sort_key if sort_key in objects.Service.fields
|
||||
else None)
|
||||
|
||||
services = objects.Service.list(
|
||||
pecan.request.context, limit, marker_obj,
|
||||
sort_key=sort_db_key, sort_dir=sort_dir)
|
||||
|
|
|
@ -173,17 +173,6 @@ class StrategyCollection(collection.Collection):
|
|||
strategy_collection = StrategyCollection()
|
||||
strategy_collection.strategies = [
|
||||
Strategy.convert_with_links(g, expand) for g in strategies]
|
||||
|
||||
if 'sort_key' in kwargs:
|
||||
reverse = False
|
||||
if kwargs['sort_key'] == 'strategy':
|
||||
if 'sort_dir' in kwargs:
|
||||
reverse = True if kwargs['sort_dir'] == 'desc' else False
|
||||
strategy_collection.strategies = sorted(
|
||||
strategy_collection.strategies,
|
||||
key=lambda strategy: strategy.uuid,
|
||||
reverse=reverse)
|
||||
|
||||
strategy_collection.next = strategy_collection.get_next(
|
||||
limit, url=url, **kwargs)
|
||||
return strategy_collection
|
||||
|
@ -211,28 +200,39 @@ class StrategiesController(rest.RestController):
|
|||
|
||||
def _get_strategies_collection(self, filters, marker, limit, sort_key,
|
||||
sort_dir, expand=False, resource_url=None):
|
||||
additional_fields = ["goal_uuid", "goal_name"]
|
||||
|
||||
api_utils.validate_sort_key(
|
||||
sort_key, list(objects.Strategy.fields) + additional_fields)
|
||||
api_utils.validate_search_filters(
|
||||
filters, list(objects.strategy.Strategy.fields) +
|
||||
["goal_uuid", "goal_name"])
|
||||
filters, list(objects.Strategy.fields) + additional_fields)
|
||||
limit = api_utils.validate_limit(limit)
|
||||
api_utils.validate_sort_dir(sort_dir)
|
||||
|
||||
sort_db_key = (sort_key if sort_key in objects.Strategy.fields
|
||||
else None)
|
||||
|
||||
marker_obj = None
|
||||
if marker:
|
||||
marker_obj = objects.Strategy.get_by_uuid(
|
||||
pecan.request.context, marker)
|
||||
|
||||
need_api_sort = api_utils.check_need_api_sort(sort_key,
|
||||
additional_fields)
|
||||
sort_db_key = (sort_key if not need_api_sort
|
||||
else None)
|
||||
|
||||
strategies = objects.Strategy.list(
|
||||
pecan.request.context, limit, marker_obj, filters=filters,
|
||||
sort_key=sort_db_key, sort_dir=sort_dir)
|
||||
|
||||
return StrategyCollection.convert_with_links(
|
||||
strategies_collection = StrategyCollection.convert_with_links(
|
||||
strategies, limit, url=resource_url, expand=expand,
|
||||
sort_key=sort_key, sort_dir=sort_dir)
|
||||
|
||||
if need_api_sort:
|
||||
api_utils.make_api_sort(strategies_collection.strategies,
|
||||
sort_key, sort_dir)
|
||||
|
||||
return strategies_collection
|
||||
|
||||
@wsme_pecan.wsexpose(StrategyCollection, wtypes.text, wtypes.text,
|
||||
int, wtypes.text, wtypes.text)
|
||||
def get_all(self, goal=None, marker=None, limit=None,
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from operator import attrgetter
|
||||
|
||||
import jsonpatch
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import reflection
|
||||
|
@ -54,6 +56,13 @@ def validate_sort_dir(sort_dir):
|
|||
"'asc' or 'desc'") % sort_dir)
|
||||
|
||||
|
||||
def validate_sort_key(sort_key, allowed_fields):
|
||||
# Very lightweight validation for now
|
||||
if sort_key not in allowed_fields:
|
||||
raise wsme.exc.ClientSideError(
|
||||
_("Invalid sort key: %s") % sort_key)
|
||||
|
||||
|
||||
def validate_search_filters(filters, allowed_fields):
|
||||
# Very lightweight validation for now
|
||||
# todo: improve this (e.g. https://www.parse.com/docs/rest/guide/#queries)
|
||||
|
@ -63,6 +72,19 @@ def validate_search_filters(filters, allowed_fields):
|
|||
_("Invalid filter: %s") % filter_name)
|
||||
|
||||
|
||||
def check_need_api_sort(sort_key, additional_fields):
|
||||
return sort_key in additional_fields
|
||||
|
||||
|
||||
def make_api_sort(sorting_list, sort_key, sort_dir):
|
||||
# First sort by uuid field, than sort by sort_key
|
||||
# sort() ensures stable sorting, so we could
|
||||
# make lexicographical sort
|
||||
reverse_direction = (sort_dir == 'desc')
|
||||
sorting_list.sort(key=attrgetter('uuid'), reverse=reverse_direction)
|
||||
sorting_list.sort(key=attrgetter(sort_key), reverse=reverse_direction)
|
||||
|
||||
|
||||
def apply_jsonpatch(doc, patch):
|
||||
for p in patch:
|
||||
if p['op'] == 'add' and p['path'].count('/') == 1:
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
# limitations under the License.
|
||||
|
||||
import datetime
|
||||
import itertools
|
||||
import mock
|
||||
|
||||
from oslo_config import cfg
|
||||
|
@ -267,6 +268,67 @@ class TestListAction(api_base.FunctionalTest):
|
|||
response = self.get_json(url, expect_errors=True)
|
||||
self.assertEqual(400, response.status_int)
|
||||
|
||||
def test_many_with_sort_key_uuid(self):
|
||||
action_plan = obj_utils.create_test_action_plan(
|
||||
self.context,
|
||||
uuid=utils.generate_uuid(),
|
||||
audit_id=self.audit.id)
|
||||
|
||||
actions_list = []
|
||||
for id_ in range(1, 3):
|
||||
action = obj_utils.create_test_action(
|
||||
self.context, id=id_,
|
||||
action_plan_id=action_plan.id,
|
||||
uuid=utils.generate_uuid())
|
||||
actions_list.append(action)
|
||||
|
||||
response = self.get_json('/actions?sort_key=%s' % 'uuid')
|
||||
names = [s['uuid'] for s in response['actions']]
|
||||
|
||||
self.assertEqual(
|
||||
sorted([a.uuid for a in actions_list]),
|
||||
names)
|
||||
|
||||
def test_many_with_sort_key_action_plan_uuid(self):
|
||||
action_plan_1 = obj_utils.create_test_action_plan(
|
||||
self.context,
|
||||
uuid=utils.generate_uuid(),
|
||||
audit_id=self.audit.id)
|
||||
|
||||
action_plan_2 = obj_utils.create_test_action_plan(
|
||||
self.context,
|
||||
uuid=utils.generate_uuid(),
|
||||
audit_id=self.audit.id)
|
||||
|
||||
action_plans_uuid_list = []
|
||||
for id_, action_plan_id in enumerate(itertools.chain.from_iterable([
|
||||
itertools.repeat(action_plan_1.id, 3),
|
||||
itertools.repeat(action_plan_2.id, 2)]), 1):
|
||||
action = obj_utils.create_test_action(
|
||||
self.context, id=id_,
|
||||
action_plan_id=action_plan_id,
|
||||
uuid=utils.generate_uuid())
|
||||
action_plans_uuid_list.append(action.action_plan.uuid)
|
||||
|
||||
for direction in ['asc', 'desc']:
|
||||
response = self.get_json(
|
||||
'/actions?sort_key={0}&sort_dir={1}'
|
||||
.format('action_plan_uuid', direction))
|
||||
|
||||
action_plan_uuids = \
|
||||
[s['action_plan_uuid'] for s in response['actions']]
|
||||
|
||||
self.assertEqual(
|
||||
sorted(action_plans_uuid_list, reverse=(direction == 'desc')),
|
||||
action_plan_uuids,
|
||||
message='Failed on %s direction' % direction)
|
||||
|
||||
def test_sort_key_validation(self):
|
||||
response = self.get_json(
|
||||
'/actions?sort_key=%s' % 'bad_name',
|
||||
expect_errors=True)
|
||||
self.assertEqual(400, response.status_int)
|
||||
|
||||
def test_many_with_soft_deleted_action_plan_uuid(self):
|
||||
action_plan1 = obj_utils.create_test_action_plan(
|
||||
self.context,
|
||||
|
|
|
@ -256,6 +256,12 @@ class TestListActionPlan(api_base.FunctionalTest):
|
|||
uuids = [s['audit_uuid'] for s in response['action_plans']]
|
||||
self.assertEqual(sorted(audit_list), uuids)
|
||||
|
||||
def test_sort_key_validation(self):
|
||||
response = self.get_json(
|
||||
'/action_plans?sort_key=%s' % 'bad_name',
|
||||
expect_errors=True)
|
||||
self.assertEqual(400, response.status_int)
|
||||
|
||||
def test_links(self):
|
||||
uuid = utils.generate_uuid()
|
||||
obj_utils.create_test_action_plan(self.context, id=1, uuid=uuid)
|
||||
|
|
|
@ -294,6 +294,50 @@ class TestListAuditTemplate(FunctionalTestWithSetup):
|
|||
'/audit_templates?strategy=%s' % self.fake_strategy2.name)
|
||||
self.assertEqual(2, len(response['audit_templates']))
|
||||
|
||||
def test_many_with_sort_key_name(self):
|
||||
audit_template_list = []
|
||||
for id_ in range(1, 6):
|
||||
audit_template = obj_utils.create_test_audit_template(
|
||||
self.context, id=id_, uuid=utils.generate_uuid(),
|
||||
name='My Audit Template {0}'.format(id_))
|
||||
audit_template_list.append(audit_template)
|
||||
|
||||
response = self.get_json('/audit_templates?sort_key=%s' % 'name')
|
||||
|
||||
names = [s['name'] for s in response['audit_templates']]
|
||||
|
||||
self.assertEqual(
|
||||
sorted([at.name for at in audit_template_list]),
|
||||
names)
|
||||
|
||||
def test_many_with_sort_key_goal_name(self):
|
||||
goal_names_list = []
|
||||
for id_, goal_id in enumerate(itertools.chain.from_iterable([
|
||||
itertools.repeat(self.fake_goal1.id, 3),
|
||||
itertools.repeat(self.fake_goal2.id, 2)]), 1):
|
||||
audit_template = obj_utils.create_test_audit_template(
|
||||
self.context, id=id_, uuid=utils.generate_uuid(),
|
||||
name='My Audit Template {0}'.format(id_),
|
||||
goal_id=goal_id)
|
||||
goal_names_list.append(audit_template.goal.name)
|
||||
|
||||
for direction in ['asc', 'desc']:
|
||||
response = self.get_json(
|
||||
'/audit_templates?sort_key={0}&sort_dir={1}'
|
||||
.format('goal_name', direction))
|
||||
|
||||
goal_names = [s['goal_name'] for s in response['audit_templates']]
|
||||
|
||||
self.assertEqual(
|
||||
sorted(goal_names_list, reverse=(direction == 'desc')),
|
||||
goal_names)
|
||||
|
||||
def test_sort_key_validation(self):
|
||||
response = self.get_json(
|
||||
'/audit_templates?sort_key=%s' % 'goal_bad_name',
|
||||
expect_errors=True)
|
||||
self.assertEqual(400, response.status_int)
|
||||
|
||||
|
||||
class TestPatch(FunctionalTestWithSetup):
|
||||
|
||||
|
|
|
@ -217,6 +217,12 @@ class TestListAudit(api_base.FunctionalTest):
|
|||
uuids = [s['goal_uuid'] for s in response['audits']]
|
||||
self.assertEqual(sorted(goal_list), uuids)
|
||||
|
||||
def test_sort_key_validation(self):
|
||||
response = self.get_json(
|
||||
'/audits?sort_key=%s' % 'bad_name',
|
||||
expect_errors=True)
|
||||
self.assertEqual(400, response.status_int)
|
||||
|
||||
def test_links(self):
|
||||
uuid = utils.generate_uuid()
|
||||
obj_utils.create_test_audit(
|
||||
|
|
|
@ -120,6 +120,27 @@ class TestListGoal(api_base.FunctionalTest):
|
|||
response = self.get_json('/goals')
|
||||
self.assertEqual(3, len(response['goals']))
|
||||
|
||||
def test_many_with_sort_key_uuid(self):
|
||||
goal_list = []
|
||||
for idx in range(1, 6):
|
||||
goal = obj_utils.create_test_goal(
|
||||
self.context, id=idx,
|
||||
uuid=utils.generate_uuid(),
|
||||
name='GOAL_{0}'.format(idx))
|
||||
goal_list.append(goal.uuid)
|
||||
|
||||
response = self.get_json('/goals/?sort_key=uuid')
|
||||
|
||||
self.assertEqual(5, len(response['goals']))
|
||||
uuids = [s['uuid'] for s in response['goals']]
|
||||
self.assertEqual(sorted(goal_list), uuids)
|
||||
|
||||
def test_sort_key_validation(self):
|
||||
response = self.get_json(
|
||||
'/goals?sort_key=%s' % 'bad_name',
|
||||
expect_errors=True)
|
||||
self.assertEqual(400, response.status_int)
|
||||
|
||||
|
||||
class TestGoalPolicyEnforcement(api_base.FunctionalTest):
|
||||
|
||||
|
|
|
@ -113,6 +113,26 @@ class TestListScoringEngine(api_base.FunctionalTest):
|
|||
response = self.get_json('/scoring_engines')
|
||||
self.assertEqual(3, len(response['scoring_engines']))
|
||||
|
||||
def test_many_with_sort_key_uuid(self):
|
||||
scoring_engine_list = []
|
||||
for idx in range(1, 6):
|
||||
scoring_engine = obj_utils.create_test_scoring_engine(
|
||||
self.context, id=idx, uuid=utils.generate_uuid(),
|
||||
name=str(idx), description='SE_{0}'.format(idx))
|
||||
scoring_engine_list.append(scoring_engine.uuid)
|
||||
|
||||
response = self.get_json('/scoring_engines/?sort_key=uuid')
|
||||
|
||||
self.assertEqual(5, len(response['scoring_engines']))
|
||||
uuids = [s['uuid'] for s in response['scoring_engines']]
|
||||
self.assertEqual(sorted(scoring_engine_list), uuids)
|
||||
|
||||
def test_sort_key_validation(self):
|
||||
response = self.get_json(
|
||||
'/goals?sort_key=%s' % 'bad_name',
|
||||
expect_errors=True)
|
||||
self.assertEqual(400, response.status_int)
|
||||
|
||||
|
||||
class TestScoringEnginePolicyEnforcement(api_base.FunctionalTest):
|
||||
|
||||
|
|
|
@ -131,6 +131,26 @@ class TestListService(api_base.FunctionalTest):
|
|||
response = self.get_json('/services')
|
||||
self.assertEqual(3, len(response['services']))
|
||||
|
||||
def test_many_with_sort_key_name(self):
|
||||
service_list = []
|
||||
for id_ in range(1, 4):
|
||||
service = obj_utils.create_test_service(
|
||||
self.context, id=id_, host='CONTROLLER',
|
||||
name='SERVICE_{0}'.format(id_))
|
||||
service_list.append(service.name)
|
||||
|
||||
response = self.get_json('/services/?sort_key=name')
|
||||
|
||||
self.assertEqual(3, len(response['services']))
|
||||
names = [s['name'] for s in response['services']]
|
||||
self.assertEqual(sorted(service_list), names)
|
||||
|
||||
def test_sort_key_validation(self):
|
||||
response = self.get_json(
|
||||
'/services?sort_key=%s' % 'bad_name',
|
||||
expect_errors=True)
|
||||
self.assertEqual(400, response.status_int)
|
||||
|
||||
|
||||
class TestServicePolicyEnforcement(api_base.FunctionalTest):
|
||||
|
||||
|
|
|
@ -221,6 +221,27 @@ class TestListStrategy(api_base.FunctionalTest):
|
|||
for strategy in strategies:
|
||||
self.assertEqual(goal1['uuid'], strategy['goal_uuid'])
|
||||
|
||||
def test_many_with_sort_key_goal_uuid(self):
|
||||
goals_uuid_list = []
|
||||
for idx in range(1, 6):
|
||||
strategy = obj_utils.create_test_strategy(
|
||||
self.context, id=idx,
|
||||
uuid=utils.generate_uuid(),
|
||||
name='STRATEGY_{0}'.format(idx))
|
||||
goals_uuid_list.append(strategy.goal.uuid)
|
||||
|
||||
response = self.get_json('/strategies/?sort_key=goal_uuid')
|
||||
|
||||
self.assertEqual(5, len(response['strategies']))
|
||||
goal_uuids = [s['goal_uuid'] for s in response['strategies']]
|
||||
self.assertEqual(sorted(goals_uuid_list), goal_uuids)
|
||||
|
||||
def test_sort_key_validation(self):
|
||||
response = self.get_json(
|
||||
'/strategies?sort_key=%s' % 'bad_name',
|
||||
expect_errors=True)
|
||||
self.assertEqual(400, response.status_int)
|
||||
|
||||
|
||||
class TestStrategyPolicyEnforcement(api_base.FunctionalTest):
|
||||
|
||||
|
|
Loading…
Reference in New Issue