Merge "Fix sort of *list command output"

This commit is contained in:
Zuul
2018-03-30 07:42:52 +00:00
committed by Gerrit Code Review
17 changed files with 331 additions and 122 deletions

View File

@@ -205,7 +205,7 @@ class ActionCollection(collection.Collection):
collection = ActionCollection() collection = ActionCollection()
collection.actions = [Action.convert_with_links(p, expand) collection.actions = [Action.convert_with_links(p, expand)
for p in actions] for p in actions]
collection.next = collection.get_next(limit, url=url, **kwargs)
return collection return collection
@classmethod @classmethod
@@ -232,6 +232,10 @@ class ActionsController(rest.RestController):
sort_key, sort_dir, expand=False, sort_key, sort_dir, expand=False,
resource_url=None, resource_url=None,
action_plan_uuid=None, audit_uuid=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) limit = api_utils.validate_limit(limit)
api_utils.validate_sort_dir(sort_dir) api_utils.validate_sort_dir(sort_dir)
@@ -247,7 +251,10 @@ class ActionsController(rest.RestController):
if audit_uuid: if audit_uuid:
filters['audit_uuid'] = 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, actions = objects.Action.list(pecan.request.context,
limit, limit,
@@ -255,11 +262,15 @@ class ActionsController(rest.RestController):
sort_dir=sort_dir, sort_dir=sort_dir,
filters=filters) filters=filters)
return ActionCollection.convert_with_links(actions, limit, actions_collection = ActionCollection.convert_with_links(
url=resource_url, actions, limit, url=resource_url, expand=expand,
expand=expand, sort_key=sort_key, sort_dir=sort_dir)
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, @wsme_pecan.wsexpose(ActionCollection, types.uuid, int,
wtypes.text, wtypes.text, types.uuid, wtypes.text, wtypes.text, types.uuid,

View File

@@ -305,17 +305,6 @@ class ActionPlanCollection(collection.Collection):
ap_collection = ActionPlanCollection() ap_collection = ActionPlanCollection()
ap_collection.action_plans = [ActionPlan.convert_with_links( ap_collection.action_plans = [ActionPlan.convert_with_links(
p, expand) for p in rpc_action_plans] 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) ap_collection.next = ap_collection.get_next(limit, url=url, **kwargs)
return ap_collection return ap_collection
@@ -344,7 +333,10 @@ class ActionPlansController(rest.RestController):
sort_key, sort_dir, expand=False, sort_key, sort_dir, expand=False,
resource_url=None, audit_uuid=None, resource_url=None, audit_uuid=None,
strategy=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) limit = api_utils.validate_limit(limit)
api_utils.validate_sort_dir(sort_dir) api_utils.validate_sort_dir(sort_dir)
@@ -363,10 +355,10 @@ class ActionPlansController(rest.RestController):
else: else:
filters['strategy_name'] = strategy filters['strategy_name'] = strategy
if sort_key == 'audit_uuid': need_api_sort = api_utils.check_need_api_sort(sort_key,
sort_db_key = None additional_fields)
else: sort_db_key = (sort_key if not need_api_sort
sort_db_key = sort_key else None)
action_plans = objects.ActionPlan.list( action_plans = objects.ActionPlan.list(
pecan.request.context, pecan.request.context,
@@ -374,12 +366,15 @@ class ActionPlansController(rest.RestController):
marker_obj, sort_key=sort_db_key, marker_obj, sort_key=sort_db_key,
sort_dir=sort_dir, filters=filters) sort_dir=sort_dir, filters=filters)
return ActionPlanCollection.convert_with_links( action_plans_collection = ActionPlanCollection.convert_with_links(
action_plans, limit, action_plans, limit, url=resource_url, expand=expand,
url=resource_url, sort_key=sort_key, sort_dir=sort_dir)
expand=expand,
sort_key=sort_key, if need_api_sort:
sort_dir=sort_dir) 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, @wsme_pecan.wsexpose(ActionPlanCollection, types.uuid, int, wtypes.text,
wtypes.text, types.uuid, wtypes.text) wtypes.text, types.uuid, wtypes.text)

View File

@@ -389,17 +389,6 @@ class AuditCollection(collection.Collection):
collection = AuditCollection() collection = AuditCollection()
collection.audits = [Audit.convert_with_links(p, expand) collection.audits = [Audit.convert_with_links(p, expand)
for p in rpc_audits] 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) collection.next = collection.get_next(limit, url=url, **kwargs)
return collection return collection
@@ -427,8 +416,14 @@ class AuditsController(rest.RestController):
sort_key, sort_dir, expand=False, sort_key, sort_dir, expand=False,
resource_url=None, goal=None, resource_url=None, goal=None,
strategy=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) limit = api_utils.validate_limit(limit)
api_utils.validate_sort_dir(sort_dir) api_utils.validate_sort_dir(sort_dir)
marker_obj = None marker_obj = None
if marker: if marker:
marker_obj = objects.Audit.get_by_uuid(pecan.request.context, 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. # TODO(michaelgugino): add method to get goal by name.
filters['strategy_name'] = strategy filters['strategy_name'] = strategy
if sort_key == 'goal_uuid': need_api_sort = api_utils.check_need_api_sort(sort_key,
sort_db_key = 'goal_id' additional_fields)
elif sort_key == 'strategy_uuid': sort_db_key = (sort_key if not need_api_sort
sort_db_key = 'strategy_id' else None)
else:
sort_db_key = sort_key
audits = objects.Audit.list(pecan.request.context, audits = objects.Audit.list(pecan.request.context,
limit, limit,
marker_obj, sort_key=sort_db_key, marker_obj, sort_key=sort_db_key,
sort_dir=sort_dir, filters=filters) sort_dir=sort_dir, filters=filters)
return AuditCollection.convert_with_links(audits, limit, audits_collection = AuditCollection.convert_with_links(
url=resource_url, audits, limit, url=resource_url, expand=expand,
expand=expand, sort_key=sort_key, sort_dir=sort_dir)
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, @wsme_pecan.wsexpose(AuditCollection, types.uuid, int, wtypes.text,
wtypes.text, wtypes.text, wtypes.text, int) wtypes.text, wtypes.text, wtypes.text, int)

View File

@@ -474,9 +474,13 @@ class AuditTemplatesController(rest.RestController):
def _get_audit_templates_collection(self, filters, marker, limit, def _get_audit_templates_collection(self, filters, marker, limit,
sort_key, sort_dir, expand=False, sort_key, sort_dir, expand=False,
resource_url=None): 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( api_utils.validate_search_filters(
filters, list(objects.audit_template.AuditTemplate.fields) + filters, list(objects.AuditTemplate.fields) + additional_fields)
["goal_uuid", "goal_name", "strategy_uuid", "strategy_name"])
limit = api_utils.validate_limit(limit) limit = api_utils.validate_limit(limit)
api_utils.validate_sort_dir(sort_dir) api_utils.validate_sort_dir(sort_dir)
@@ -486,19 +490,26 @@ class AuditTemplatesController(rest.RestController):
pecan.request.context, pecan.request.context,
marker) marker)
audit_templates = objects.AuditTemplate.list( need_api_sort = api_utils.check_need_api_sort(sort_key,
pecan.request.context, additional_fields)
filters, sort_db_key = (sort_key if not need_api_sort
limit, else None)
marker_obj, sort_key=sort_key,
sort_dir=sort_dir)
return AuditTemplateCollection.convert_with_links(audit_templates, audit_templates = objects.AuditTemplate.list(
limit, pecan.request.context, filters, limit, marker_obj,
url=resource_url, sort_key=sort_db_key, sort_dir=sort_dir)
expand=expand,
sort_key=sort_key, audit_templates_collection = \
sort_dir=sort_dir) 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, @wsme_pecan.wsexpose(AuditTemplateCollection, wtypes.text, wtypes.text,
types.uuid, int, wtypes.text, wtypes.text) types.uuid, int, wtypes.text, wtypes.text)

View File

@@ -130,17 +130,6 @@ class GoalCollection(collection.Collection):
goal_collection = GoalCollection() goal_collection = GoalCollection()
goal_collection.goals = [ goal_collection.goals = [
Goal.convert_with_links(g, expand) for g in 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( goal_collection.next = goal_collection.get_next(
limit, url=url, **kwargs) limit, url=url, **kwargs)
return goal_collection return goal_collection
@@ -167,17 +156,19 @@ class GoalsController(rest.RestController):
def _get_goals_collection(self, marker, limit, sort_key, sort_dir, def _get_goals_collection(self, marker, limit, sort_key, sort_dir,
expand=False, resource_url=None): expand=False, resource_url=None):
api_utils.validate_sort_key(
sort_key, list(objects.Goal.fields))
limit = api_utils.validate_limit(limit) limit = api_utils.validate_limit(limit)
api_utils.validate_sort_dir(sort_dir) api_utils.validate_sort_dir(sort_dir)
sort_db_key = (sort_key if sort_key in objects.Goal.fields
else None)
marker_obj = None marker_obj = None
if marker: if marker:
marker_obj = objects.Goal.get_by_uuid( marker_obj = objects.Goal.get_by_uuid(
pecan.request.context, marker) 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, goals = objects.Goal.list(pecan.request.context, limit, marker_obj,
sort_key=sort_db_key, sort_dir=sort_dir) sort_key=sort_db_key, sort_dir=sort_dir)

View File

@@ -123,17 +123,6 @@ class ScoringEngineCollection(collection.Collection):
collection = ScoringEngineCollection() collection = ScoringEngineCollection()
collection.scoring_engines = [ScoringEngine.convert_with_links( collection.scoring_engines = [ScoringEngine.convert_with_links(
se, expand) for se in scoring_engines] 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) collection.next = collection.get_next(limit, url=url, **kwargs)
return collection return collection
@@ -160,7 +149,8 @@ class ScoringEngineController(rest.RestController):
def _get_scoring_engines_collection(self, marker, limit, def _get_scoring_engines_collection(self, marker, limit,
sort_key, sort_dir, expand=False, sort_key, sort_dir, expand=False,
resource_url=None): resource_url=None):
api_utils.validate_sort_key(
sort_key, list(objects.ScoringEngine.fields))
limit = api_utils.validate_limit(limit) limit = api_utils.validate_limit(limit)
api_utils.validate_sort_dir(sort_dir) api_utils.validate_sort_dir(sort_dir)
@@ -171,7 +161,8 @@ class ScoringEngineController(rest.RestController):
filters = {} 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( scoring_engines = objects.ScoringEngine.list(
context=pecan.request.context, context=pecan.request.context,

View File

@@ -154,17 +154,6 @@ class ServiceCollection(collection.Collection):
service_collection = ServiceCollection() service_collection = ServiceCollection()
service_collection.services = [ service_collection.services = [
Service.convert_with_links(g, expand) for g in 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( service_collection.next = service_collection.get_next(
limit, url=url, marker_field='id', **kwargs) limit, url=url, marker_field='id', **kwargs)
return service_collection return service_collection
@@ -191,17 +180,19 @@ class ServicesController(rest.RestController):
def _get_services_collection(self, marker, limit, sort_key, sort_dir, def _get_services_collection(self, marker, limit, sort_key, sort_dir,
expand=False, resource_url=None): expand=False, resource_url=None):
api_utils.validate_sort_key(
sort_key, list(objects.Service.fields))
limit = api_utils.validate_limit(limit) limit = api_utils.validate_limit(limit)
api_utils.validate_sort_dir(sort_dir) api_utils.validate_sort_dir(sort_dir)
sort_db_key = (sort_key if sort_key in objects.Service.fields
else None)
marker_obj = None marker_obj = None
if marker: if marker:
marker_obj = objects.Service.get( marker_obj = objects.Service.get(
pecan.request.context, marker) pecan.request.context, marker)
sort_db_key = (sort_key if sort_key in objects.Service.fields
else None)
services = objects.Service.list( services = objects.Service.list(
pecan.request.context, limit, marker_obj, pecan.request.context, limit, marker_obj,
sort_key=sort_db_key, sort_dir=sort_dir) sort_key=sort_db_key, sort_dir=sort_dir)

View File

@@ -173,17 +173,6 @@ class StrategyCollection(collection.Collection):
strategy_collection = StrategyCollection() strategy_collection = StrategyCollection()
strategy_collection.strategies = [ strategy_collection.strategies = [
Strategy.convert_with_links(g, expand) for g in 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( strategy_collection.next = strategy_collection.get_next(
limit, url=url, **kwargs) limit, url=url, **kwargs)
return strategy_collection return strategy_collection
@@ -211,28 +200,39 @@ class StrategiesController(rest.RestController):
def _get_strategies_collection(self, filters, marker, limit, sort_key, def _get_strategies_collection(self, filters, marker, limit, sort_key,
sort_dir, expand=False, resource_url=None): 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( api_utils.validate_search_filters(
filters, list(objects.strategy.Strategy.fields) + filters, list(objects.Strategy.fields) + additional_fields)
["goal_uuid", "goal_name"])
limit = api_utils.validate_limit(limit) limit = api_utils.validate_limit(limit)
api_utils.validate_sort_dir(sort_dir) api_utils.validate_sort_dir(sort_dir)
sort_db_key = (sort_key if sort_key in objects.Strategy.fields
else None)
marker_obj = None marker_obj = None
if marker: if marker:
marker_obj = objects.Strategy.get_by_uuid( marker_obj = objects.Strategy.get_by_uuid(
pecan.request.context, marker) 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( strategies = objects.Strategy.list(
pecan.request.context, limit, marker_obj, filters=filters, pecan.request.context, limit, marker_obj, filters=filters,
sort_key=sort_db_key, sort_dir=sort_dir) 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, strategies, limit, url=resource_url, expand=expand,
sort_key=sort_key, sort_dir=sort_dir) 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, @wsme_pecan.wsexpose(StrategyCollection, wtypes.text, wtypes.text,
int, wtypes.text, wtypes.text) int, wtypes.text, wtypes.text)
def get_all(self, goal=None, marker=None, limit=None, def get_all(self, goal=None, marker=None, limit=None,

View File

@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from operator import attrgetter
import jsonpatch import jsonpatch
from oslo_config import cfg from oslo_config import cfg
from oslo_utils import reflection from oslo_utils import reflection
@@ -54,6 +56,13 @@ def validate_sort_dir(sort_dir):
"'asc' or 'desc'") % 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): def validate_search_filters(filters, allowed_fields):
# Very lightweight validation for now # Very lightweight validation for now
# todo: improve this (e.g. https://www.parse.com/docs/rest/guide/#queries) # 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) _("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): def apply_jsonpatch(doc, patch):
for p in patch: for p in patch:
if p['op'] == 'add' and p['path'].count('/') == 1: if p['op'] == 'add' and p['path'].count('/') == 1:

View File

@@ -11,6 +11,7 @@
# limitations under the License. # limitations under the License.
import datetime import datetime
import itertools
import mock import mock
from oslo_config import cfg from oslo_config import cfg
@@ -267,6 +268,67 @@ class TestListAction(api_base.FunctionalTest):
response = self.get_json(url, expect_errors=True) response = self.get_json(url, expect_errors=True)
self.assertEqual(400, response.status_int) 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): def test_many_with_soft_deleted_action_plan_uuid(self):
action_plan1 = obj_utils.create_test_action_plan( action_plan1 = obj_utils.create_test_action_plan(
self.context, self.context,

View File

@@ -256,6 +256,12 @@ class TestListActionPlan(api_base.FunctionalTest):
uuids = [s['audit_uuid'] for s in response['action_plans']] uuids = [s['audit_uuid'] for s in response['action_plans']]
self.assertEqual(sorted(audit_list), uuids) 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): def test_links(self):
uuid = utils.generate_uuid() uuid = utils.generate_uuid()
obj_utils.create_test_action_plan(self.context, id=1, uuid=uuid) obj_utils.create_test_action_plan(self.context, id=1, uuid=uuid)

View File

@@ -294,6 +294,50 @@ class TestListAuditTemplate(FunctionalTestWithSetup):
'/audit_templates?strategy=%s' % self.fake_strategy2.name) '/audit_templates?strategy=%s' % self.fake_strategy2.name)
self.assertEqual(2, len(response['audit_templates'])) 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): class TestPatch(FunctionalTestWithSetup):

View File

@@ -217,6 +217,12 @@ class TestListAudit(api_base.FunctionalTest):
uuids = [s['goal_uuid'] for s in response['audits']] uuids = [s['goal_uuid'] for s in response['audits']]
self.assertEqual(sorted(goal_list), uuids) 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): def test_links(self):
uuid = utils.generate_uuid() uuid = utils.generate_uuid()
obj_utils.create_test_audit( obj_utils.create_test_audit(

View File

@@ -120,6 +120,27 @@ class TestListGoal(api_base.FunctionalTest):
response = self.get_json('/goals') response = self.get_json('/goals')
self.assertEqual(3, len(response['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): class TestGoalPolicyEnforcement(api_base.FunctionalTest):

View File

@@ -113,6 +113,26 @@ class TestListScoringEngine(api_base.FunctionalTest):
response = self.get_json('/scoring_engines') response = self.get_json('/scoring_engines')
self.assertEqual(3, len(response['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): class TestScoringEnginePolicyEnforcement(api_base.FunctionalTest):

View File

@@ -131,6 +131,26 @@ class TestListService(api_base.FunctionalTest):
response = self.get_json('/services') response = self.get_json('/services')
self.assertEqual(3, len(response['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): class TestServicePolicyEnforcement(api_base.FunctionalTest):

View File

@@ -221,6 +221,27 @@ class TestListStrategy(api_base.FunctionalTest):
for strategy in strategies: for strategy in strategies:
self.assertEqual(goal1['uuid'], strategy['goal_uuid']) 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): class TestStrategyPolicyEnforcement(api_base.FunctionalTest):