Merge "Fix API sort key for complex columns" into stable/stein
This commit is contained in:
commit
2ac913cd19
|
@ -311,13 +311,26 @@ class PaginationHelper(object):
|
||||||
self.sort_keys.append((key, self.sort_dir))
|
self.sort_keys.append((key, self.sort_dir))
|
||||||
|
|
||||||
for current_sort_key, current_sort_dir in self.sort_keys:
|
for current_sort_key, current_sort_dir in self.sort_keys:
|
||||||
|
# Translate sort_key from API standard to data model's name
|
||||||
|
current_sort_key = (
|
||||||
|
model.__v2_wsme__.translate_key_to_data_model(
|
||||||
|
current_sort_key))
|
||||||
sort_dir_func = {
|
sort_dir_func = {
|
||||||
constants.ASC: sqlalchemy.asc,
|
constants.ASC: sqlalchemy.asc,
|
||||||
constants.DESC: sqlalchemy.desc,
|
constants.DESC: sqlalchemy.desc,
|
||||||
}[current_sort_dir]
|
}[current_sort_dir]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sort_key_attr = getattr(model, current_sort_key)
|
# The translated object may be a nested parameter
|
||||||
|
# such as vip.ip_address, so handle that case by
|
||||||
|
# joining with the nested table.
|
||||||
|
if '.' in current_sort_key:
|
||||||
|
parent, child = current_sort_key.split('.')
|
||||||
|
parent_obj = getattr(model, parent)
|
||||||
|
query = query.join(parent_obj)
|
||||||
|
sort_key_attr = child
|
||||||
|
else:
|
||||||
|
sort_key_attr = getattr(model, current_sort_key)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise exceptions.InvalidSortKey(key=current_sort_key)
|
raise exceptions.InvalidSortKey(key=current_sort_key)
|
||||||
query = query.order_by(sort_dir_func(sort_key_attr))
|
query = query.order_by(sort_dir_func(sort_key_attr))
|
||||||
|
|
|
@ -155,6 +155,14 @@ class BaseType(wtypes.Base):
|
||||||
res[k] = v
|
res[k] = v
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def translate_key_to_data_model(cls, key):
|
||||||
|
"""Translate the keys from wsme class type, to data_model."""
|
||||||
|
if not hasattr(cls, '_type_to_model_map') or (
|
||||||
|
key not in cls._type_to_model_map):
|
||||||
|
return key
|
||||||
|
return cls._type_to_model_map[key]
|
||||||
|
|
||||||
def to_dict(self, render_unsets=False):
|
def to_dict(self, render_unsets=False):
|
||||||
"""Converts Octavia WSME type to dictionary.
|
"""Converts Octavia WSME type to dictionary.
|
||||||
|
|
||||||
|
|
|
@ -136,7 +136,7 @@ class PoolsController(base.BaseController):
|
||||||
def _is_only_specified_in_request(self, request, **kwargs):
|
def _is_only_specified_in_request(self, request, **kwargs):
|
||||||
request_attrs = []
|
request_attrs = []
|
||||||
check_attrs = kwargs['check_exist_attrs']
|
check_attrs = kwargs['check_exist_attrs']
|
||||||
escaped_attrs = ['from_data_model',
|
escaped_attrs = ['from_data_model', 'translate_key_to_data_model',
|
||||||
'translate_dict_keys_to_data_model', 'to_dict']
|
'translate_dict_keys_to_data_model', 'to_dict']
|
||||||
|
|
||||||
for attr in dir(request):
|
for attr in dir(request):
|
||||||
|
|
|
@ -318,6 +318,7 @@ AMP_DATA = 'amp_data'
|
||||||
AMPS_DATA = 'amps_data'
|
AMPS_DATA = 'amps_data'
|
||||||
NICS = 'nics'
|
NICS = 'nics'
|
||||||
VIP = 'vip'
|
VIP = 'vip'
|
||||||
|
VIP_ADDRESS = 'vip_address'
|
||||||
POOL = 'pool'
|
POOL = 'pool'
|
||||||
POOL_CHILD_COUNT = 'pool_child_count'
|
POOL_CHILD_COUNT = 'pool_child_count'
|
||||||
POOL_ID = 'pool_id'
|
POOL_ID = 'pool_id'
|
||||||
|
|
|
@ -455,6 +455,64 @@ class TestHealthMonitor(base.BaseAPITest):
|
||||||
hm_id_names_asc = [(hm.get('id'), hm.get('name')) for hm in hms_asc]
|
hm_id_names_asc = [(hm.get('id'), hm.get('name')) for hm in hms_asc]
|
||||||
self.assertEqual(hm_id_names_asc, list(reversed(hm_id_names_desc)))
|
self.assertEqual(hm_id_names_asc, list(reversed(hm_id_names_desc)))
|
||||||
|
|
||||||
|
def test_get_all_sorted_by_max_retries(self):
|
||||||
|
pool1 = self.create_pool(
|
||||||
|
self.lb_id,
|
||||||
|
constants.PROTOCOL_HTTP,
|
||||||
|
constants.LB_ALGORITHM_ROUND_ROBIN,
|
||||||
|
name='pool1').get('pool')
|
||||||
|
self.set_lb_status(self.lb_id)
|
||||||
|
pool2 = self.create_pool(
|
||||||
|
self.lb_id,
|
||||||
|
constants.PROTOCOL_HTTP,
|
||||||
|
constants.LB_ALGORITHM_ROUND_ROBIN,
|
||||||
|
name='pool2').get('pool')
|
||||||
|
self.set_lb_status(self.lb_id)
|
||||||
|
pool3 = self.create_pool(
|
||||||
|
self.lb_id,
|
||||||
|
constants.PROTOCOL_HTTP,
|
||||||
|
constants.LB_ALGORITHM_ROUND_ROBIN,
|
||||||
|
name='pool3').get('pool')
|
||||||
|
self.set_lb_status(self.lb_id)
|
||||||
|
hm1 = self.create_health_monitor(
|
||||||
|
pool1.get('id'), constants.HEALTH_MONITOR_HTTP,
|
||||||
|
1, 1, 1, 2, name='hm1').get(self.root_tag)
|
||||||
|
self.set_lb_status(self.lb_id)
|
||||||
|
hm2 = self.create_health_monitor(
|
||||||
|
pool2.get('id'), constants.HEALTH_MONITOR_PING,
|
||||||
|
1, 1, 1, 1, name='hm2').get(self.root_tag)
|
||||||
|
self.set_lb_status(self.lb_id)
|
||||||
|
hm3 = self.create_health_monitor(
|
||||||
|
pool3.get('id'), constants.HEALTH_MONITOR_TCP,
|
||||||
|
1, 1, 1, 3, name='hm3').get(self.root_tag)
|
||||||
|
self.set_lb_status(self.lb_id)
|
||||||
|
|
||||||
|
response = self.get(self.HMS_PATH, params={'sort': 'max_retries:desc'})
|
||||||
|
hms_desc = response.json.get(self.root_tag_list)
|
||||||
|
response = self.get(self.HMS_PATH, params={'sort': 'max_retries:asc'})
|
||||||
|
hms_asc = response.json.get(self.root_tag_list)
|
||||||
|
|
||||||
|
self.assertEqual(3, len(hms_desc))
|
||||||
|
self.assertEqual(3, len(hms_asc))
|
||||||
|
|
||||||
|
hm_id_names_desc = [(hm.get('id'), hm.get('name')) for hm in hms_desc]
|
||||||
|
hm_id_names_asc = [(hm.get('id'), hm.get('name')) for hm in hms_asc]
|
||||||
|
self.assertEqual(hm_id_names_asc, list(reversed(hm_id_names_desc)))
|
||||||
|
|
||||||
|
self.assertEqual(hm2[constants.MAX_RETRIES],
|
||||||
|
hms_asc[0][constants.MAX_RETRIES])
|
||||||
|
self.assertEqual(hm1[constants.MAX_RETRIES],
|
||||||
|
hms_asc[1][constants.MAX_RETRIES])
|
||||||
|
self.assertEqual(hm3[constants.MAX_RETRIES],
|
||||||
|
hms_asc[2][constants.MAX_RETRIES])
|
||||||
|
|
||||||
|
self.assertEqual(hm3[constants.MAX_RETRIES],
|
||||||
|
hms_desc[0][constants.MAX_RETRIES])
|
||||||
|
self.assertEqual(hm1[constants.MAX_RETRIES],
|
||||||
|
hms_desc[1][constants.MAX_RETRIES])
|
||||||
|
self.assertEqual(hm2[constants.MAX_RETRIES],
|
||||||
|
hms_desc[2][constants.MAX_RETRIES])
|
||||||
|
|
||||||
def test_get_all_limited(self):
|
def test_get_all_limited(self):
|
||||||
pool1 = self.create_pool(
|
pool1 = self.create_pool(
|
||||||
self.lb_id,
|
self.lb_id,
|
||||||
|
|
|
@ -1250,6 +1250,41 @@ class TestLoadBalancer(base.BaseAPITest):
|
||||||
lb_id_names_asc = [(lb.get('id'), lb.get('name')) for lb in lbs_asc]
|
lb_id_names_asc = [(lb.get('id'), lb.get('name')) for lb in lbs_asc]
|
||||||
self.assertEqual(lb_id_names_asc, list(reversed(lb_id_names_desc)))
|
self.assertEqual(lb_id_names_asc, list(reversed(lb_id_names_desc)))
|
||||||
|
|
||||||
|
def test_get_all_sorted_by_vip_ip_address(self):
|
||||||
|
self.create_load_balancer(uuidutils.generate_uuid(),
|
||||||
|
name='lb1',
|
||||||
|
project_id=self.project_id,
|
||||||
|
vip_address='198.51.100.2')
|
||||||
|
self.create_load_balancer(uuidutils.generate_uuid(),
|
||||||
|
name='lb2',
|
||||||
|
project_id=self.project_id,
|
||||||
|
vip_address='198.51.100.1')
|
||||||
|
self.create_load_balancer(uuidutils.generate_uuid(),
|
||||||
|
name='lb3',
|
||||||
|
project_id=self.project_id,
|
||||||
|
vip_address='198.51.100.3')
|
||||||
|
response = self.get(self.LBS_PATH,
|
||||||
|
params={'sort': 'vip_address:desc'})
|
||||||
|
lbs_desc = response.json.get(self.root_tag_list)
|
||||||
|
response = self.get(self.LBS_PATH,
|
||||||
|
params={'sort': 'vip_address:asc'})
|
||||||
|
lbs_asc = response.json.get(self.root_tag_list)
|
||||||
|
|
||||||
|
self.assertEqual(3, len(lbs_desc))
|
||||||
|
self.assertEqual(3, len(lbs_asc))
|
||||||
|
|
||||||
|
lb_id_names_desc = [(lb.get('id'), lb.get('name')) for lb in lbs_desc]
|
||||||
|
lb_id_names_asc = [(lb.get('id'), lb.get('name')) for lb in lbs_asc]
|
||||||
|
self.assertEqual(lb_id_names_asc, list(reversed(lb_id_names_desc)))
|
||||||
|
|
||||||
|
self.assertEqual('198.51.100.1', lbs_asc[0][constants.VIP_ADDRESS])
|
||||||
|
self.assertEqual('198.51.100.2', lbs_asc[1][constants.VIP_ADDRESS])
|
||||||
|
self.assertEqual('198.51.100.3', lbs_asc[2][constants.VIP_ADDRESS])
|
||||||
|
|
||||||
|
self.assertEqual('198.51.100.3', lbs_desc[0][constants.VIP_ADDRESS])
|
||||||
|
self.assertEqual('198.51.100.2', lbs_desc[1][constants.VIP_ADDRESS])
|
||||||
|
self.assertEqual('198.51.100.1', lbs_desc[2][constants.VIP_ADDRESS])
|
||||||
|
|
||||||
def test_get_all_limited(self):
|
def test_get_all_limited(self):
|
||||||
self.create_load_balancer(uuidutils.generate_uuid(),
|
self.create_load_balancer(uuidutils.generate_uuid(),
|
||||||
name='lb1',
|
name='lb1',
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Fixed an issue where some columns could not be used for sort keys in
|
||||||
|
API list calls.
|
Loading…
Reference in New Issue