novaclient sort parameters support
Adds sorting support to the 'nova list' command. --sort <key>[:<direction>] The --sort parameter is comma-separated and is used to specify one or more sort keys and directions. The direction defaults to 'desc' for each sort key and the user can supply 'asc' to override. Partially implements: blueprint nova-pagination Change-Id: I635e017c7f9ab61812333983bfecccd6fce8d394
This commit is contained in:
parent
5f2ad683ce
commit
4b530bf9d6
novaclient
@ -49,6 +49,25 @@ class ServersTest(utils.FixturedTestCase):
|
||||
for s in sl:
|
||||
self.assertIsInstance(s, servers.Server)
|
||||
|
||||
def test_list_servers_sort_single(self):
|
||||
sl = self.cs.servers.list(sort_keys=['display_name'],
|
||||
sort_dirs=['asc'])
|
||||
self.assert_called(
|
||||
'GET',
|
||||
'/servers/detail?sort_dir=asc&sort_key=display_name')
|
||||
for s in sl:
|
||||
self.assertIsInstance(s, servers.Server)
|
||||
|
||||
def test_list_servers_sort_multiple(self):
|
||||
sl = self.cs.servers.list(sort_keys=['display_name', 'id'],
|
||||
sort_dirs=['asc', 'desc'])
|
||||
self.assert_called(
|
||||
'GET',
|
||||
('/servers/detail?sort_dir=asc&sort_dir=desc&'
|
||||
'sort_key=display_name&sort_key=id'))
|
||||
for s in sl:
|
||||
self.assertIsInstance(s, servers.Server)
|
||||
|
||||
def test_get_server_details(self):
|
||||
s = self.cs.servers.get(1234)
|
||||
self.assert_called('GET', '/servers/1234')
|
||||
|
@ -851,6 +851,60 @@ class ShellTest(utils.TestCase):
|
||||
'GET',
|
||||
'/servers/detail?all_tenants=1&user_id=fake_user')
|
||||
|
||||
def test_list_with_single_sort_key_no_dir(self):
|
||||
self.run_command('list --sort 1')
|
||||
self.assert_called(
|
||||
'GET', ('/servers/detail?sort_dir=desc&sort_key=1'))
|
||||
|
||||
def test_list_with_single_sort_key_and_dir(self):
|
||||
self.run_command('list --sort 1:asc')
|
||||
self.assert_called(
|
||||
'GET', ('/servers/detail?sort_dir=asc&sort_key=1'))
|
||||
|
||||
def test_list_with_sort_keys_no_dir(self):
|
||||
self.run_command('list --sort 1,2')
|
||||
self.assert_called(
|
||||
'GET', ('/servers/detail?sort_dir=desc&sort_dir=desc&'
|
||||
'sort_key=1&sort_key=2'))
|
||||
|
||||
def test_list_with_sort_keys_and_dirs(self):
|
||||
self.run_command('list --sort 1:asc,2:desc')
|
||||
self.assert_called(
|
||||
'GET', ('/servers/detail?sort_dir=asc&sort_dir=desc&'
|
||||
'sort_key=1&sort_key=2'))
|
||||
|
||||
def test_list_with_sort_keys_and_some_dirs(self):
|
||||
self.run_command('list --sort 1,2:asc')
|
||||
self.assert_called(
|
||||
'GET', ('/servers/detail?sort_dir=desc&sort_dir=asc&'
|
||||
'sort_key=1&sort_key=2'))
|
||||
|
||||
def test_list_with_invalid_sort_dir_one(self):
|
||||
cmd = 'list --sort 1:foo'
|
||||
self.assertRaises(exceptions.CommandError, self.run_command, cmd)
|
||||
|
||||
def test_list_with_invalid_sort_dir_two(self):
|
||||
cmd = 'list --sort 1:asc,2:foo'
|
||||
self.assertRaises(exceptions.CommandError, self.run_command, cmd)
|
||||
|
||||
def test_list_sortby_index_with_sort(self):
|
||||
# sortby_index is None if there is sort information
|
||||
for cmd in ['list --sort key',
|
||||
'list --sort key:desc',
|
||||
'list --sort key1,key2:asc']:
|
||||
with mock.patch('novaclient.utils.print_list') as mock_print_list:
|
||||
self.run_command(cmd)
|
||||
mock_print_list.assert_called_once_with(
|
||||
mock.ANY, mock.ANY, mock.ANY, sortby_index=None)
|
||||
|
||||
def test_list_sortby_index_without_sort(self):
|
||||
# sortby_index is 1 without sort information
|
||||
for cmd in ['list', 'list --minimal', 'list --deleted']:
|
||||
with mock.patch('novaclient.utils.print_list') as mock_print_list:
|
||||
self.run_command(cmd)
|
||||
mock_print_list.assert_called_once_with(
|
||||
mock.ANY, mock.ANY, mock.ANY, sortby_index=1)
|
||||
|
||||
def test_list_fields(self):
|
||||
output = self.run_command(
|
||||
'list --fields '
|
||||
|
@ -566,7 +566,8 @@ class ServerManager(base.BootingManagerWithFind):
|
||||
"""
|
||||
return self._get("/servers/%s" % base.getid(server), "server")
|
||||
|
||||
def list(self, detailed=True, search_opts=None, marker=None, limit=None):
|
||||
def list(self, detailed=True, search_opts=None, marker=None, limit=None,
|
||||
sort_keys=None, sort_dirs=None):
|
||||
"""
|
||||
Get a list of servers.
|
||||
|
||||
@ -575,6 +576,8 @@ class ServerManager(base.BootingManagerWithFind):
|
||||
:param marker: Begin returning servers that appear later in the server
|
||||
list than that represented by this server id (optional).
|
||||
:param limit: Maximum number of servers to return (optional).
|
||||
:param sort_keys: List of sort keys
|
||||
:param sort_dirs: List of sort directions
|
||||
|
||||
:rtype: list of :class:`Server`
|
||||
"""
|
||||
@ -595,8 +598,16 @@ class ServerManager(base.BootingManagerWithFind):
|
||||
|
||||
# Transform the dict to a sequence of two-element tuples in fixed
|
||||
# order, then the encoded string will be consistent in Python 2&3.
|
||||
if qparams:
|
||||
new_qparams = sorted(qparams.items(), key=lambda x: x[0])
|
||||
if qparams or sort_keys or sort_dirs:
|
||||
# sort keys and directions are unique since the same parameter
|
||||
# key is repeated for each associated value
|
||||
# (ie, &sort_key=key1&sort_key=key2&sort_key=key3)
|
||||
items = list(qparams.items())
|
||||
if sort_keys:
|
||||
items.extend(('sort_key', sort_key) for sort_key in sort_keys)
|
||||
if sort_dirs:
|
||||
items.extend(('sort_dir', sort_dir) for sort_dir in sort_dirs)
|
||||
new_qparams = sorted(items, key=lambda x: x[0])
|
||||
query_string = "?%s" % parse.urlencode(new_qparams)
|
||||
else:
|
||||
query_string = ""
|
||||
|
@ -1308,6 +1308,13 @@ def do_image_delete(cs, args):
|
||||
action="store_true",
|
||||
default=False,
|
||||
help=_('Get only uuid and name.'))
|
||||
@cliutils.arg(
|
||||
'--sort',
|
||||
dest='sort',
|
||||
metavar='<key>[:<direction>]',
|
||||
help=('Comma-separated list of sort keys and directions in the form'
|
||||
' of <key>[:<asc|desc>]. The direction defaults to descending if'
|
||||
' not specified.'))
|
||||
def do_list(cs, args):
|
||||
"""List active servers."""
|
||||
imageid = None
|
||||
@ -1350,8 +1357,23 @@ def do_list(cs, args):
|
||||
|
||||
detailed = not args.minimal
|
||||
|
||||
sort_keys = []
|
||||
sort_dirs = []
|
||||
if args.sort:
|
||||
for sort in args.sort.split(','):
|
||||
sort_key, _sep, sort_dir = sort.partition(':')
|
||||
if not sort_dir:
|
||||
sort_dir = 'desc'
|
||||
elif sort_dir not in ('asc', 'desc'):
|
||||
raise exceptions.CommandError(_(
|
||||
'Unknown sort direction: %s') % sort_dir)
|
||||
sort_keys.append(sort_key)
|
||||
sort_dirs.append(sort_dir)
|
||||
|
||||
servers = cs.servers.list(detailed=detailed,
|
||||
search_opts=search_opts)
|
||||
search_opts=search_opts,
|
||||
sort_keys=sort_keys,
|
||||
sort_dirs=sort_dirs)
|
||||
convert = [('OS-EXT-SRV-ATTR:host', 'host'),
|
||||
('OS-EXT-STS:task_state', 'task_state'),
|
||||
('OS-EXT-SRV-ATTR:instance_name', 'instance_name'),
|
||||
@ -1375,8 +1397,11 @@ def do_list(cs, args):
|
||||
'Networks'
|
||||
]
|
||||
formatters['Networks'] = utils._format_servers_list_networks
|
||||
sortby_index = 1
|
||||
if args.sort:
|
||||
sortby_index = None
|
||||
utils.print_list(servers, columns,
|
||||
formatters, sortby_index=1)
|
||||
formatters, sortby_index=sortby_index)
|
||||
|
||||
|
||||
@cliutils.arg(
|
||||
|
Loading…
x
Reference in New Issue
Block a user