Added optional arguments to host-list command and unit tests.
Implemented handling of argument values as well as defined acceptable field values for hosts. Change-Id: I2fc2267d402a87e09c059dfdc8b10d86e8eeb69c
This commit is contained in:
@@ -75,6 +75,12 @@ class HTTPError(ClientException):
|
||||
self.status_code = code
|
||||
|
||||
|
||||
class CommandError(ClientException):
|
||||
"""Client command was invalid or failed."""
|
||||
|
||||
message = "The command used was invalid or caused an error."""
|
||||
|
||||
|
||||
class ConnectionFailed(HTTPError):
|
||||
"""Connecting to the server failed."""
|
||||
|
||||
|
||||
@@ -13,11 +13,73 @@
|
||||
# under the License.
|
||||
"""Hosts resource and resource shell wrapper."""
|
||||
from cratonclient.common import cliutils
|
||||
from cratonclient import exceptions as exc
|
||||
from cratonclient.v1.hosts import HOST_FIELDS as h_fields
|
||||
|
||||
|
||||
@cliutils.arg('-c', '--cell',
|
||||
metavar='<cell>',
|
||||
type=int,
|
||||
help='Integer ID of the cell that contains '
|
||||
'the desired list of hosts.')
|
||||
@cliutils.arg('--detail',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Show detailed information about the hosts.')
|
||||
@cliutils.arg('--limit',
|
||||
metavar='<limit>',
|
||||
type=int,
|
||||
help='Maximum number of hosts to return.')
|
||||
@cliutils.arg('--sort-key',
|
||||
metavar='<field>',
|
||||
help='Host field that will be used for sorting.')
|
||||
@cliutils.arg('--sort-dir',
|
||||
metavar='<direction>',
|
||||
default='asc',
|
||||
help='Sort direction: "asc" (default) or "desc".')
|
||||
@cliutils.arg('--fields',
|
||||
nargs='+',
|
||||
metavar='<fields>',
|
||||
default=[],
|
||||
help='Comma-separated list of fields to display. '
|
||||
'Only these fields will be fetched from the server. '
|
||||
'Can not be used when "--detail" is specified')
|
||||
def do_host_list(cc, args):
|
||||
"""Print list of hosts which are registered with the Craton service."""
|
||||
params = {}
|
||||
columns = ['id', 'name']
|
||||
default_fields = ['id', 'name', 'type', 'active', 'cell_id']
|
||||
if args.cell is not None:
|
||||
params['cell'] = args.cell
|
||||
if args.limit is not None:
|
||||
if args.limit < 0:
|
||||
raise exc.CommandError('Invalid limit specified. Expected '
|
||||
'non-negative limit, got {0}'
|
||||
.format(args.limit))
|
||||
params['limit'] = args.limit
|
||||
if args.detail:
|
||||
fields = h_fields
|
||||
params['detail'] = args.detail
|
||||
elif args.fields:
|
||||
fields = {x: h_fields[x] for x in args.fields}
|
||||
else:
|
||||
fields = {x: h_fields[x] for x in default_fields}
|
||||
if args.sort_key is not None:
|
||||
fields_map = dict(zip(fields.keys(), fields.keys()))
|
||||
# TODO(cmspence): Do we want to allow sorting by field heading value?
|
||||
try:
|
||||
sort_key = fields_map[args.sort_key]
|
||||
except KeyError:
|
||||
raise exc.CommandError(
|
||||
'{0} is an invalid key for sorting, valid values for '
|
||||
'--sort-key are: {1}'.format(args.sort_key, h_fields.keys())
|
||||
)
|
||||
params['sort_key'] = sort_key
|
||||
if args.sort_dir is not None:
|
||||
if args.sort_dir not in ('asc', 'desc'):
|
||||
raise exc.CommandError('Invalid sort direction specified. The '
|
||||
'expected valid values for --sort-dir '
|
||||
'are: "asc", "desc".')
|
||||
params['sort_dir'] = args.sort_dir
|
||||
|
||||
hosts = cc.hosts.list(args.craton_project_id, **params)
|
||||
cliutils.print_list(hosts, columns)
|
||||
cliutils.print_list(hosts, list(fields))
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
import mock
|
||||
|
||||
from cratonclient import exceptions as exc
|
||||
from cratonclient.tests import base
|
||||
|
||||
|
||||
@@ -25,3 +26,105 @@ class TestHostsShell(base.ShellTestCase):
|
||||
"""Verify that no arguments prints out all project hosts."""
|
||||
self.shell('host-list')
|
||||
self.assertTrue(mock_list.called)
|
||||
|
||||
@mock.patch('cratonclient.v1.hosts.HostManager.list')
|
||||
def test_host_list_parse_param_success(self, mock_list):
|
||||
"""Verify that success of parsing a subcommand argument."""
|
||||
self.shell('host-list --limit 0')
|
||||
self.assertTrue(mock_list.called)
|
||||
|
||||
@mock.patch('cratonclient.v1.hosts.HostManager.list')
|
||||
def test_host_list_limit_0_succcess(self, mock_list):
|
||||
"""Verify that --limit 0 prints out all project hosts."""
|
||||
self.shell('host-list --limit 0')
|
||||
mock_list.assert_called_once_with(mock.ANY, limit=0)
|
||||
|
||||
@mock.patch('cratonclient.v1.hosts.HostManager.list')
|
||||
def test_host_list_limit_positive_num_success(self, mock_list):
|
||||
"""Verify --limit X, where X is a positive integer, succeeds.
|
||||
|
||||
The command will print out X number of project hosts.
|
||||
"""
|
||||
self.shell('host-list --limit 1')
|
||||
mock_list.assert_called_once_with(mock.ANY, limit=1)
|
||||
|
||||
def test_host_list_limit_negative_num_failure(self):
|
||||
"""Verify --limit X, where X is a negative integer, fails.
|
||||
|
||||
The command will cause a Command Error message response.
|
||||
"""
|
||||
self.assertRaises(exc.CommandError,
|
||||
self.shell,
|
||||
'host-list --limit -1')
|
||||
|
||||
@mock.patch('cratonclient.v1.hosts.HostManager.list')
|
||||
def test_host_list_cell_success(self, mock_list):
|
||||
"""Verify --cell arguments successfully pass cell to Client."""
|
||||
for cell_arg in ['-c', '--cell']:
|
||||
self.shell('host-list {0} 1'.format(cell_arg))
|
||||
mock_list.assert_called_once_with(mock.ANY, cell=1)
|
||||
mock_list.reset_mock()
|
||||
|
||||
@mock.patch('cratonclient.v1.hosts.HostManager.list')
|
||||
def test_host_list_detail_success(self, mock_list):
|
||||
"""Verify --detail argument successfully pass detail to Client."""
|
||||
self.shell('host-list --detail')
|
||||
mock_list.assert_called_once_with(mock.ANY, detail=True)
|
||||
|
||||
@mock.patch('cratonclient.v1.hosts.HostManager.list')
|
||||
@mock.patch('cratonclient.common.cliutils.print_list')
|
||||
def test_host_list_fields_success(self, mock_printlist, mock_list):
|
||||
"""Verify --fields argument successfully passed to Client."""
|
||||
self.shell('host-list --fields id name')
|
||||
mock_list.assert_called_once_with(mock.ANY)
|
||||
mock_printlist.assert_called_once_with(mock.ANY,
|
||||
list({'id': 'ID',
|
||||
'name': 'Name'}))
|
||||
|
||||
@mock.patch('cratonclient.v1.hosts.HostManager.list')
|
||||
def test_host_list_detail_and_fields_specified(self, mock_list):
|
||||
"""Verify --fields ignored when --detail argument passed in."""
|
||||
self.shell('host-list --fields id name --detail')
|
||||
mock_list.assert_called_once_with(mock.ANY, detail=True)
|
||||
|
||||
@mock.patch('cratonclient.v1.hosts.HostManager.list')
|
||||
def test_host_list_sort_key_field_key_success(self, mock_list):
|
||||
"""Verify --sort-key arguments successfully passed to Client."""
|
||||
self.shell('host-list --sort-key cell_id')
|
||||
mock_list.assert_called_once_with(mock.ANY,
|
||||
sort_key='cell_id',
|
||||
sort_dir='asc')
|
||||
|
||||
def test_host_list_sort_key_invalid(self):
|
||||
"""Verify --sort-key with invalid args, fails with Command Error."""
|
||||
self.assertRaises(exc.CommandError,
|
||||
self.shell,
|
||||
'host-list --sort-key invalid')
|
||||
|
||||
@mock.patch('cratonclient.v1.hosts.HostManager.list')
|
||||
def test_host_list_sort_dir_not_passed_without_sort_key(self, mock_list):
|
||||
"""Verify --sort-dir arg ignored without --sort-key."""
|
||||
self.shell('host-list --sort-dir desc')
|
||||
mock_list.assert_called_once_with(mock.ANY)
|
||||
|
||||
@mock.patch('cratonclient.v1.hosts.HostManager.list')
|
||||
def test_host_list_sort_dir_asc_success(self, mock_list):
|
||||
"""Verify --sort-dir asc successfully passed to Client."""
|
||||
self.shell('host-list --sort-key name --sort-dir asc')
|
||||
mock_list.assert_called_once_with(mock.ANY,
|
||||
sort_key='name',
|
||||
sort_dir='asc')
|
||||
|
||||
@mock.patch('cratonclient.v1.hosts.HostManager.list')
|
||||
def test_host_list_sort_dir_desc_success(self, mock_list):
|
||||
"""Verify --sort-dir desc successfully passed to Client."""
|
||||
self.shell('host-list --sort-key name --sort-dir desc')
|
||||
mock_list.assert_called_once_with(mock.ANY,
|
||||
sort_key='name',
|
||||
sort_dir='desc')
|
||||
|
||||
def test_host_list_sort_dir_invalid_value(self):
|
||||
"""Verify --sort-dir with invalid args, fails with Command Error."""
|
||||
self.assertRaises(exc.CommandError,
|
||||
self.shell,
|
||||
'host-list --sort-key name --sort-dir invalid')
|
||||
|
||||
@@ -32,3 +32,18 @@ class HostManager(crud.CRUDClient):
|
||||
"""Retrieve the hosts in a specific region."""
|
||||
kwargs['project'] = str(project_id)
|
||||
super(HostManager, self).list(**kwargs)
|
||||
|
||||
HOST_FIELDS = {
|
||||
'id': 'ID',
|
||||
'name': 'Name',
|
||||
'type': 'Type',
|
||||
'project_id': 'Project ID',
|
||||
'region_id': 'Region ID',
|
||||
'cell_id': 'Cell ID',
|
||||
'ip_address': 'IP Address',
|
||||
'active': 'Active',
|
||||
'note': 'Note',
|
||||
'access_secret_id': "Access Secret ID",
|
||||
'created_at': 'Created At',
|
||||
'update_at': 'Updated At'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user