Merge "Use the compute SDK in server list"

This commit is contained in:
Zuul
2022-12-02 14:21:38 +00:00
committed by Gerrit Code Review
4 changed files with 205 additions and 189 deletions

View File

@@ -66,6 +66,28 @@ class PowerStateColumn(cliff_columns.FormattableColumn):
return 'N/A' return 'N/A'
class AddressesColumn(cliff_columns.FormattableColumn):
"""Generate a formatted string of a server's addresses."""
def human_readable(self):
try:
return utils.format_dict_of_list({
k: [i['addr'] for i in v if 'addr' in i]
for k, v in self._value.items()})
except Exception:
return 'N/A'
class HostColumn(cliff_columns.FormattableColumn):
"""Generate a formatted string of a hostname."""
def human_readable(self):
if self._value is None:
return ''
return self._value
def _get_ip_address(addresses, address_type, ip_address_family): def _get_ip_address(addresses, address_type, ip_address_family):
# Old style addresses # Old style addresses
if address_type in addresses: if address_type in addresses:
@@ -2288,7 +2310,7 @@ class ListServer(command.Lister):
return parser return parser
def take_action(self, parsed_args): def take_action(self, parsed_args):
compute_client = self.app.client_manager.compute compute_client = self.app.client_manager.sdk_connection.compute
identity_client = self.app.client_manager.identity identity_client = self.app.client_manager.identity
image_client = self.app.client_manager.image image_client = self.app.client_manager.image
@@ -2313,10 +2335,11 @@ class ListServer(command.Lister):
# flavor name is given, map it to ID. # flavor name is given, map it to ID.
flavor_id = None flavor_id = None
if parsed_args.flavor: if parsed_args.flavor:
flavor_id = utils.find_resource( flavor = compute_client.find_flavor(parsed_args.flavor)
compute_client.flavors, if flavor is None:
parsed_args.flavor, msg = _('Unable to find flavor: %s') % parsed_args.flavor
).id raise exceptions.CommandError(msg)
flavor_id = flavor.id
# Nova only supports list servers searching by image ID. So if a # Nova only supports list servers searching by image ID. So if a
# image name is given, map it to ID. # image name is given, map it to ID.
@@ -2332,19 +2355,21 @@ class ListServer(command.Lister):
'ip': parsed_args.ip, 'ip': parsed_args.ip,
'ip6': parsed_args.ip6, 'ip6': parsed_args.ip6,
'name': parsed_args.name, 'name': parsed_args.name,
'instance_name': parsed_args.instance_name,
'status': parsed_args.status, 'status': parsed_args.status,
'flavor': flavor_id, 'flavor': flavor_id,
'image': image_id, 'image': image_id,
'host': parsed_args.host, 'host': parsed_args.host,
'tenant_id': project_id, 'project_id': project_id,
'all_tenants': parsed_args.all_projects, 'all_projects': parsed_args.all_projects,
'user_id': user_id, 'user_id': user_id,
'deleted': parsed_args.deleted, 'deleted': parsed_args.deleted,
'changes-before': parsed_args.changes_before, 'changes-before': parsed_args.changes_before,
'changes-since': parsed_args.changes_since, 'changes-since': parsed_args.changes_since,
} }
if parsed_args.instance_name is not None:
search_opts['instance_name'] = parsed_args.instance_name
if parsed_args.availability_zone: if parsed_args.availability_zone:
search_opts['availability_zone'] = parsed_args.availability_zone search_opts['availability_zone'] = parsed_args.availability_zone
@@ -2376,7 +2401,7 @@ class ListServer(command.Lister):
search_opts['power_state'] = power_state search_opts['power_state'] = power_state
if parsed_args.tags: if parsed_args.tags:
if compute_client.api_version < api_versions.APIVersion('2.26'): if not sdk_utils.supports_microversion(compute_client, '2.26'):
msg = _( msg = _(
'--os-compute-api-version 2.26 or greater is required to ' '--os-compute-api-version 2.26 or greater is required to '
'support the --tag option' 'support the --tag option'
@@ -2386,7 +2411,7 @@ class ListServer(command.Lister):
search_opts['tags'] = ','.join(parsed_args.tags) search_opts['tags'] = ','.join(parsed_args.tags)
if parsed_args.not_tags: if parsed_args.not_tags:
if compute_client.api_version < api_versions.APIVersion('2.26'): if not sdk_utils.supports_microversion(compute_client, '2.26'):
msg = _( msg = _(
'--os-compute-api-version 2.26 or greater is required to ' '--os-compute-api-version 2.26 or greater is required to '
'support the --not-tag option' 'support the --not-tag option'
@@ -2396,7 +2421,7 @@ class ListServer(command.Lister):
search_opts['not-tags'] = ','.join(parsed_args.not_tags) search_opts['not-tags'] = ','.join(parsed_args.not_tags)
if parsed_args.locked: if parsed_args.locked:
if compute_client.api_version < api_versions.APIVersion('2.73'): if not sdk_utils.supports_microversion(compute_client, '2.73'):
msg = _( msg = _(
'--os-compute-api-version 2.73 or greater is required to ' '--os-compute-api-version 2.73 or greater is required to '
'support the --locked option' 'support the --locked option'
@@ -2405,7 +2430,7 @@ class ListServer(command.Lister):
search_opts['locked'] = True search_opts['locked'] = True
elif parsed_args.unlocked: elif parsed_args.unlocked:
if compute_client.api_version < api_versions.APIVersion('2.73'): if not sdk_utils.supports_microversion(compute_client, '2.73'):
msg = _( msg = _(
'--os-compute-api-version 2.73 or greater is required to ' '--os-compute-api-version 2.73 or greater is required to '
'support the --unlocked option' 'support the --unlocked option'
@@ -2414,10 +2439,14 @@ class ListServer(command.Lister):
search_opts['locked'] = False search_opts['locked'] = False
if parsed_args.limit is not None:
search_opts['limit'] = parsed_args.limit
search_opts['paginated'] = False
LOG.debug('search options: %s', search_opts) LOG.debug('search options: %s', search_opts)
if search_opts['changes-before']: if search_opts['changes-before']:
if compute_client.api_version < api_versions.APIVersion('2.66'): if not sdk_utils.supports_microversion(compute_client, '2.66'):
msg = _('--os-compute-api-version 2.66 or later is required') msg = _('--os-compute-api-version 2.66 or later is required')
raise exceptions.CommandError(msg) raise exceptions.CommandError(msg)
@@ -2451,15 +2480,15 @@ class ListServer(command.Lister):
if parsed_args.long: if parsed_args.long:
columns += ( columns += (
'OS-EXT-STS:task_state', 'task_state',
'OS-EXT-STS:power_state', 'power_state',
) )
column_headers += ( column_headers += (
'Task State', 'Task State',
'Power State', 'Power State',
) )
columns += ('networks',) columns += ('addresses',)
column_headers += ('Networks',) column_headers += ('Networks',)
if parsed_args.long: if parsed_args.long:
@@ -2481,7 +2510,7 @@ class ListServer(command.Lister):
# microversion 2.47 puts the embedded flavor into the server response # microversion 2.47 puts the embedded flavor into the server response
# body but omits the id, so if not present we just expose the original # body but omits the id, so if not present we just expose the original
# flavor name in the output # flavor name in the output
if compute_client.api_version >= api_versions.APIVersion('2.47'): if sdk_utils.supports_microversion(compute_client, '2.47'):
columns += ('flavor_name',) columns += ('flavor_name',)
column_headers += ('Flavor',) column_headers += ('Flavor',)
else: else:
@@ -2503,8 +2532,8 @@ class ListServer(command.Lister):
if parsed_args.long: if parsed_args.long:
columns += ( columns += (
'OS-EXT-AZ:availability_zone', 'availability_zone',
'OS-EXT-SRV-ATTR:host', 'hypervisor_hostname',
'metadata', 'metadata',
) )
column_headers += ( column_headers += (
@@ -2513,40 +2542,38 @@ class ListServer(command.Lister):
'Properties', 'Properties',
) )
marker_id = None
# support for additional columns # support for additional columns
if parsed_args.columns: if parsed_args.columns:
for c in parsed_args.columns: for c in parsed_args.columns:
if c in ('Project ID', 'project_id'): if c in ('Project ID', 'project_id'):
columns += ('tenant_id',) columns += ('project_id',)
column_headers += ('Project ID',) column_headers += ('Project ID',)
if c in ('User ID', 'user_id'): if c in ('User ID', 'user_id'):
columns += ('user_id',) columns += ('user_id',)
column_headers += ('User ID',) column_headers += ('User ID',)
if c in ('Created At', 'created_at'): if c in ('Created At', 'created_at'):
columns += ('created',) columns += ('created_at',)
column_headers += ('Created At',) column_headers += ('Created At',)
if c in ('Security Groups', 'security_groups'): if c in ('Security Groups', 'security_groups'):
columns += ('security_groups_name',) columns += ('security_groups_name',)
column_headers += ('Security Groups',) column_headers += ('Security Groups',)
if c in ("Task State", "task_state"): if c in ("Task State", "task_state"):
columns += ('OS-EXT-STS:task_state',) columns += ('task_state',)
column_headers += ('Task State',) column_headers += ('Task State',)
if c in ("Power State", "power_state"): if c in ("Power State", "power_state"):
columns += ('OS-EXT-STS:power_state',) columns += ('power_state',)
column_headers += ('Power State',) column_headers += ('Power State',)
if c in ("Image ID", "image_id"): if c in ("Image ID", "image_id"):
columns += ('Image ID',) columns += ('Image ID',)
column_headers += ('Image ID',) column_headers += ('Image ID',)
if c in ("Flavor ID", "flavor_id"): if c in ("Flavor ID", "flavor_id"):
columns += ('Flavor ID',) columns += ('flavor_id',)
column_headers += ('Flavor ID',) column_headers += ('Flavor ID',)
if c in ('Availability Zone', "availability_zone"): if c in ('Availability Zone', "availability_zone"):
columns += ('OS-EXT-AZ:availability_zone',) columns += ('availability_zone',)
column_headers += ('Availability Zone',) column_headers += ('Availability Zone',)
if c in ('Host', "host"): if c in ('Host', "host"):
columns += ('OS-EXT-SRV-ATTR:host',) columns += ('hypervisor_hostname',)
column_headers += ('Host',) column_headers += ('Host',)
if c in ('Properties', "properties"): if c in ('Properties', "properties"):
columns += ('Metadata',) columns += ('Metadata',)
@@ -2556,7 +2583,7 @@ class ListServer(command.Lister):
column_headers = tuple(column_headers) column_headers = tuple(column_headers)
columns = tuple(columns) columns = tuple(columns)
if parsed_args.marker: if parsed_args.marker is not None:
# Check if both "--marker" and "--deleted" are used. # Check if both "--marker" and "--deleted" are used.
# In that scenario a lookup is not needed as the marker # In that scenario a lookup is not needed as the marker
# needs to be an ID, because find_resource does not # needs to be an ID, because find_resource does not
@@ -2564,16 +2591,10 @@ class ListServer(command.Lister):
if parsed_args.deleted: if parsed_args.deleted:
marker_id = parsed_args.marker marker_id = parsed_args.marker
else: else:
marker_id = utils.find_resource( marker_id = compute_client.find_server(parsed_args.marker).id
compute_client.servers, search_opts['marker'] = marker_id
parsed_args.marker,
).id
data = compute_client.servers.list( data = list(compute_client.servers(**search_opts))
search_opts=search_opts,
marker=marker_id,
limit=parsed_args.limit,
)
images = {} images = {}
flavors = {} flavors = {}
@@ -2628,12 +2649,12 @@ class ListServer(command.Lister):
# "Flavor Name" is not crucial, so we swallow any # "Flavor Name" is not crucial, so we swallow any
# exceptions # exceptions
try: try:
flavors[f_id] = compute_client.flavors.get(f_id) flavors[f_id] = compute_client.find_flavor(f_id)
except Exception: except Exception:
pass pass
else: else:
try: try:
flavors_list = compute_client.flavors.list(is_public=None) flavors_list = compute_client.flavors(is_public=None)
for i in flavors_list: for i in flavors_list:
flavors[i.id] = i flavors[i.id] = i
except Exception: except Exception:
@@ -2642,7 +2663,7 @@ class ListServer(command.Lister):
# Populate image_name, image_id, flavor_name and flavor_id attributes # Populate image_name, image_id, flavor_name and flavor_id attributes
# of server objects so that we can display those columns. # of server objects so that we can display those columns.
for s in data: for s in data:
if compute_client.api_version >= api_versions.APIVersion('2.69'): if sdk_utils.supports_microversion(compute_client, '2.69'):
# NOTE(tssurya): From 2.69, we will have the keys 'flavor' # NOTE(tssurya): From 2.69, we will have the keys 'flavor'
# and 'image' missing in the server response during # and 'image' missing in the server response during
# infrastructure failure situations. # infrastructure failure situations.
@@ -2651,7 +2672,7 @@ class ListServer(command.Lister):
if not hasattr(s, 'image') or not hasattr(s, 'flavor'): if not hasattr(s, 'image') or not hasattr(s, 'flavor'):
continue continue
if 'id' in s.image: if 'id' in s.image and s.image.id is not None:
image = images.get(s.image['id']) image = images.get(s.image['id'])
if image: if image:
s.image_name = image.name s.image_name = image.name
@@ -2664,7 +2685,7 @@ class ListServer(command.Lister):
s.image_name = IMAGE_STRING_FOR_BFV s.image_name = IMAGE_STRING_FOR_BFV
s.image_id = IMAGE_STRING_FOR_BFV s.image_id = IMAGE_STRING_FOR_BFV
if compute_client.api_version < api_versions.APIVersion('2.47'): if not sdk_utils.supports_microversion(compute_client, '2.47'):
flavor = flavors.get(s.flavor['id']) flavor = flavors.get(s.flavor['id'])
if flavor: if flavor:
s.flavor_name = flavor.name s.flavor_name = flavor.name
@@ -2674,7 +2695,7 @@ class ListServer(command.Lister):
# Add a list with security group name as attribute # Add a list with security group name as attribute
for s in data: for s in data:
if hasattr(s, 'security_groups'): if hasattr(s, 'security_groups') and s.security_groups is not None:
s.security_groups_name = [x["name"] for x in s.security_groups] s.security_groups_name = [x["name"] for x in s.security_groups]
else: else:
s.security_groups_name = [] s.security_groups_name = []
@@ -2687,10 +2708,10 @@ class ListServer(command.Lister):
# it's on, providing useful information to a user in this # it's on, providing useful information to a user in this
# situation. # situation.
if ( if (
compute_client.api_version >= api_versions.APIVersion('2.16') and sdk_utils.supports_microversion(compute_client, '2.16') and
parsed_args.long parsed_args.long
): ):
if any([hasattr(s, 'host_status') for s in data]): if any([s.host_status is not None for s in data]):
columns += ('Host Status',) columns += ('Host Status',)
column_headers += ('Host Status',) column_headers += ('Host Status',)
@@ -2700,16 +2721,17 @@ class ListServer(command.Lister):
utils.get_item_properties( utils.get_item_properties(
s, columns, s, columns,
mixed_case_fields=( mixed_case_fields=(
'OS-EXT-STS:task_state', 'task_state',
'OS-EXT-STS:power_state', 'power_state',
'OS-EXT-AZ:availability_zone', 'availability_zone',
'OS-EXT-SRV-ATTR:host', 'host',
), ),
formatters={ formatters={
'OS-EXT-STS:power_state': PowerStateColumn, 'power_state': PowerStateColumn,
'networks': format_columns.DictListColumn, 'addresses': AddressesColumn,
'metadata': format_columns.DictColumn, 'metadata': format_columns.DictColumn,
'security_groups_name': format_columns.ListColumn, 'security_groups_name': format_columns.ListColumn,
'hypervisor_hostname': HostColumn,
}, },
) for s in data ) for s in data
), ),

View File

@@ -105,7 +105,7 @@ class ServerTests(common.ComputeTestCase):
'server list -f json --deleted --marker ' + name2 'server list -f json --deleted --marker ' + name2
)) ))
except exceptions.CommandFailed as e: except exceptions.CommandFailed as e:
self.assertIn('marker [%s] not found (HTTP 400)' % (name2), self.assertIn('marker [%s] not found' % (name2),
e.stderr.decode('utf-8')) e.stderr.decode('utf-8'))
def test_server_list_with_changes_before(self): def test_server_list_with_changes_before(self):

View File

@@ -117,6 +117,21 @@ class TestServer(compute_fakes.TestComputev2):
# Set object methods to be tested. Could be overwritten in subclass. # Set object methods to be tested. Could be overwritten in subclass.
self.methods = {} self.methods = {}
patcher = mock.patch.object(
sdk_utils, 'supports_microversion', return_value=True)
self.addCleanup(patcher.stop)
self.supports_microversion_mock = patcher.start()
self._set_mock_microversion(
self.app.client_manager.compute.api_version.get_string())
def _set_mock_microversion(self, mock_v):
"""Set a specific microversion for the mock supports_microversion()."""
self.supports_microversion_mock.reset_mock(return_value=True)
self.supports_microversion_mock.side_effect = (
lambda _, v:
api_versions.APIVersion(v) <= api_versions.APIVersion(mock_v))
def setup_servers_mock(self, count): def setup_servers_mock(self, count):
# If we are creating more than one server, make one of them # If we are creating more than one server, make one of them
# boot-from-volume # boot-from-volume
@@ -4448,32 +4463,25 @@ class _TestServerList(TestServer):
def setUp(self): def setUp(self):
super(_TestServerList, self).setUp() super(_TestServerList, self).setUp()
self.search_opts = { # Default params of the core function of the command in the case of no
# commandline option specified.
self.kwargs = {
'reservation_id': None, 'reservation_id': None,
'ip': None, 'ip': None,
'ip6': None, 'ip6': None,
'name': None, 'name': None,
'instance_name': None,
'status': None, 'status': None,
'flavor': None, 'flavor': None,
'image': None, 'image': None,
'host': None, 'host': None,
'tenant_id': None, 'project_id': None,
'all_tenants': False, 'all_projects': False,
'user_id': None, 'user_id': None,
'deleted': False, 'deleted': False,
'changes-since': None, 'changes-since': None,
'changes-before': None, 'changes-before': None,
} }
# Default params of the core function of the command in the case of no
# commandline option specified.
self.kwargs = {
'search_opts': self.search_opts,
'marker': None,
'limit': None,
}
# The fake servers' attributes. Use the original attributes names in # The fake servers' attributes. Use the original attributes names in
# nova, not the ones printed by "server list" command. # nova, not the ones printed by "server list" command.
self.attrs = { self.attrs = {
@@ -4488,10 +4496,6 @@ class _TestServerList(TestServer):
'Metadata': format_columns.DictColumn({}), 'Metadata': format_columns.DictColumn({}),
} }
# The servers to be listed.
self.servers = self.setup_servers_mock(3)
self.servers_mock.list.return_value = self.servers
self.image = image_fakes.create_one_image() self.image = image_fakes.create_one_image()
# self.images_mock.return_value = [self.image] # self.images_mock.return_value = [self.image]
@@ -4499,7 +4503,12 @@ class _TestServerList(TestServer):
self.get_image_mock.return_value = self.image self.get_image_mock.return_value = self.image
self.flavor = compute_fakes.FakeFlavor.create_one_flavor() self.flavor = compute_fakes.FakeFlavor.create_one_flavor()
self.flavors_mock.get.return_value = self.flavor self.sdk_client.find_flavor.return_value = self.flavor
self.attrs['flavor'] = {'original_name': self.flavor.name}
# The servers to be listed.
self.servers = self.setup_sdk_servers_mock(3)
self.sdk_client.servers.return_value = self.servers
# Get the command object to test # Get the command object to test
self.cmd = server.ListServer(self.app, None) self.cmd = server.ListServer(self.app, None)
@@ -4518,7 +4527,7 @@ class TestServerList(_TestServerList):
] ]
Flavor = collections.namedtuple('Flavor', 'id name') Flavor = collections.namedtuple('Flavor', 'id name')
self.flavors_mock.list.return_value = [ self.sdk_client.flavors.return_value = [
Flavor(id=s.flavor['id'], name=self.flavor.name) Flavor(id=s.flavor['id'], name=self.flavor.name)
for s in self.servers for s in self.servers
] ]
@@ -4528,7 +4537,7 @@ class TestServerList(_TestServerList):
s.id, s.id,
s.name, s.name,
s.status, s.status,
format_columns.DictListColumn(s.networks), server.AddressesColumn(s.addresses),
# Image will be an empty string if boot-from-volume # Image will be an empty string if boot-from-volume
self.image.name if s.image else server.IMAGE_STRING_FOR_BFV, self.image.name if s.image else server.IMAGE_STRING_FOR_BFV,
self.flavor.name, self.flavor.name,
@@ -4547,9 +4556,9 @@ class TestServerList(_TestServerList):
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.images_mock.assert_called() self.images_mock.assert_called()
self.flavors_mock.list.assert_called() self.sdk_client.flavors.assert_called()
# we did not pass image or flavor, so gets on those must be absent # we did not pass image or flavor, so gets on those must be absent
self.assertFalse(self.flavors_mock.get.call_count) self.assertFalse(self.flavors_mock.get.call_count)
self.assertFalse(self.get_image_mock.call_count) self.assertFalse(self.get_image_mock.call_count)
@@ -4564,14 +4573,14 @@ class TestServerList(_TestServerList):
('deleted', False), ('deleted', False),
] ]
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.servers_mock.list.return_value = [] self.sdk_client.servers.return_value = []
self.data = () self.data = ()
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.images_mock.assert_not_called() self.images_mock.assert_not_called()
self.flavors_mock.list.assert_not_called() self.sdk_client.flavors.assert_not_called()
self.assertEqual(self.columns, columns) self.assertEqual(self.columns, columns)
self.assertEqual(self.data, tuple(data)) self.assertEqual(self.data, tuple(data))
@@ -4581,19 +4590,19 @@ class TestServerList(_TestServerList):
s.id, s.id,
s.name, s.name,
s.status, s.status,
getattr(s, 'OS-EXT-STS:task_state'), getattr(s, 'task_state'),
server.PowerStateColumn( server.PowerStateColumn(
getattr(s, 'OS-EXT-STS:power_state') getattr(s, 'power_state')
), ),
format_columns.DictListColumn(s.networks), server.AddressesColumn(s.addresses),
# Image will be an empty string if boot-from-volume # Image will be an empty string if boot-from-volume
self.image.name if s.image else server.IMAGE_STRING_FOR_BFV, self.image.name if s.image else server.IMAGE_STRING_FOR_BFV,
s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV, s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV,
self.flavor.name, self.flavor.name,
s.flavor['id'], s.flavor['id'],
getattr(s, 'OS-EXT-AZ:availability_zone'), getattr(s, 'availability_zone'),
getattr(s, 'OS-EXT-SRV-ATTR:host'), server.HostColumn(getattr(s, 'hypervisor_hostname')),
s.Metadata, format_columns.DictColumn(s.metadata),
) for s in self.servers ) for s in self.servers
) )
arglist = [ arglist = [
@@ -4606,12 +4615,12 @@ class TestServerList(_TestServerList):
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
image_ids = {s.image['id'] for s in self.servers if s.image} image_ids = {s.image['id'] for s in self.servers if s.image}
self.images_mock.assert_called_once_with( self.images_mock.assert_called_once_with(
id=f'in:{",".join(image_ids)}', id=f'in:{",".join(image_ids)}',
) )
self.flavors_mock.list.assert_called_once_with(is_public=None) self.sdk_client.flavors.assert_called_once_with(is_public=None)
self.assertEqual(self.columns_long, columns) self.assertEqual(self.columns_long, columns)
self.assertEqual(self.data, tuple(data)) self.assertEqual(self.data, tuple(data))
@@ -4637,7 +4646,7 @@ class TestServerList(_TestServerList):
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.assertIn('Project ID', columns) self.assertIn('Project ID', columns)
self.assertIn('User ID', columns) self.assertIn('User ID', columns)
self.assertIn('Created At', columns) self.assertIn('Created At', columns)
@@ -4656,7 +4665,7 @@ class TestServerList(_TestServerList):
s.id, s.id,
s.name, s.name,
s.status, s.status,
format_columns.DictListColumn(s.networks), server.AddressesColumn(s.addresses),
# Image will be an empty string if boot-from-volume # Image will be an empty string if boot-from-volume
s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV, s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV,
s.flavor['id'] s.flavor['id']
@@ -4674,9 +4683,9 @@ class TestServerList(_TestServerList):
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.images_mock.assert_not_called() self.images_mock.assert_not_called()
self.flavors_mock.list.assert_not_called() self.sdk_client.flavors.assert_not_called()
self.assertEqual(self.columns, columns) self.assertEqual(self.columns, columns)
self.assertEqual(self.data, tuple(data)) self.assertEqual(self.data, tuple(data))
@@ -4686,7 +4695,7 @@ class TestServerList(_TestServerList):
s.id, s.id,
s.name, s.name,
s.status, s.status,
format_columns.DictListColumn(s.networks), server.AddressesColumn(s.addresses),
# Image will be an empty string if boot-from-volume # Image will be an empty string if boot-from-volume
s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV, s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV,
s.flavor['id'] s.flavor['id']
@@ -4704,9 +4713,9 @@ class TestServerList(_TestServerList):
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.images_mock.assert_not_called() self.images_mock.assert_not_called()
self.flavors_mock.list.assert_not_called() self.sdk_client.flavors.assert_not_called()
self.assertEqual(self.columns, columns) self.assertEqual(self.columns, columns)
self.assertEqual(self.data, tuple(data)) self.assertEqual(self.data, tuple(data))
@@ -4723,11 +4732,11 @@ class TestServerList(_TestServerList):
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.images_mock.assert_not_called() self.images_mock.assert_not_called()
self.flavors_mock.list.assert_not_called() self.sdk_client.flavors.assert_not_called()
self.get_image_mock.assert_called() self.get_image_mock.assert_called()
self.flavors_mock.get.assert_called() self.sdk_client.find_flavor.assert_called()
self.assertEqual(self.columns, columns) self.assertEqual(self.columns, columns)
self.assertEqual(self.data, tuple(data)) self.assertEqual(self.data, tuple(data))
@@ -4747,10 +4756,10 @@ class TestServerList(_TestServerList):
self.find_image_mock.assert_called_with(self.image.id, self.find_image_mock.assert_called_with(self.image.id,
ignore_missing=False) ignore_missing=False)
self.search_opts['image'] = self.image.id self.kwargs['image'] = self.image.id
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.images_mock.assert_not_called() self.images_mock.assert_not_called()
self.flavors_mock.list.assert_called_once() self.sdk_client.flavors.assert_called_once()
self.assertEqual(self.columns, columns) self.assertEqual(self.columns, columns)
self.assertEqual(self.data, tuple(data)) self.assertEqual(self.data, tuple(data))
@@ -4767,12 +4776,13 @@ class TestServerList(_TestServerList):
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.flavors_mock.get.assert_has_calls([mock.call(self.flavor.id)]) self.sdk_client.find_flavor.assert_has_calls(
[mock.call(self.flavor.id)])
self.search_opts['flavor'] = self.flavor.id self.kwargs['flavor'] = self.flavor.id
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.images_mock.assert_called_once() self.images_mock.assert_called_once()
self.flavors_mock.list.assert_not_called() self.sdk_client.flavors.assert_not_called()
self.assertEqual(self.columns, columns) self.assertEqual(self.columns, columns)
self.assertEqual(self.data, tuple(data)) self.assertEqual(self.data, tuple(data))
@@ -4791,9 +4801,9 @@ class TestServerList(_TestServerList):
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.search_opts['changes-since'] = '2016-03-04T06:27:59Z' self.kwargs['changes-since'] = '2016-03-04T06:27:59Z'
self.search_opts['deleted'] = True self.kwargs['deleted'] = True
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.assertEqual(self.columns, columns) self.assertEqual(self.columns, columns)
self.assertEqual(self.data, tuple(data)) self.assertEqual(self.data, tuple(data))
@@ -4820,8 +4830,7 @@ class TestServerList(_TestServerList):
) )
def test_server_list_with_tag(self): def test_server_list_with_tag(self):
self.app.client_manager.compute.api_version = api_versions.APIVersion( self._set_mock_microversion('2.26')
'2.26')
arglist = [ arglist = [
'--tag', 'tag1', '--tag', 'tag1',
@@ -4834,16 +4843,15 @@ class TestServerList(_TestServerList):
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.search_opts['tags'] = 'tag1,tag2' self.kwargs['tags'] = 'tag1,tag2'
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.assertEqual(self.columns, columns) self.assertEqual(self.columns, columns)
self.assertEqual(self.data, tuple(data)) self.assertEqual(self.data, tuple(data))
def test_server_list_with_tag_pre_v225(self): def test_server_list_with_tag_pre_v225(self):
self.app.client_manager.compute.api_version = api_versions.APIVersion( self._set_mock_microversion('2.25')
'2.25')
arglist = [ arglist = [
'--tag', 'tag1', '--tag', 'tag1',
@@ -4863,9 +4871,7 @@ class TestServerList(_TestServerList):
str(ex)) str(ex))
def test_server_list_with_not_tag(self): def test_server_list_with_not_tag(self):
self.app.client_manager.compute.api_version = api_versions.APIVersion( self._set_mock_microversion('2.26')
'2.26')
arglist = [ arglist = [
'--not-tag', 'tag1', '--not-tag', 'tag1',
'--not-tag', 'tag2', '--not-tag', 'tag2',
@@ -4877,16 +4883,15 @@ class TestServerList(_TestServerList):
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.search_opts['not-tags'] = 'tag1,tag2' self.kwargs['not-tags'] = 'tag1,tag2'
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.assertEqual(self.columns, columns) self.assertEqual(self.columns, columns)
self.assertEqual(self.data, tuple(data)) self.assertEqual(self.data, tuple(data))
def test_server_list_with_not_tag_pre_v226(self): def test_server_list_with_not_tag_pre_v226(self):
self.app.client_manager.compute.api_version = api_versions.APIVersion( self._set_mock_microversion('2.25')
'2.25')
arglist = [ arglist = [
'--not-tag', 'tag1', '--not-tag', 'tag1',
@@ -4916,8 +4921,8 @@ class TestServerList(_TestServerList):
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.search_opts['availability_zone'] = 'test-az' self.kwargs['availability_zone'] = 'test-az'
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.assertEqual(self.columns, columns) self.assertEqual(self.columns, columns)
self.assertEqual(tuple(self.data), tuple(data)) self.assertEqual(tuple(self.data), tuple(data))
@@ -4932,8 +4937,8 @@ class TestServerList(_TestServerList):
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.search_opts['key_name'] = 'test-key' self.kwargs['key_name'] = 'test-key'
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.assertEqual(self.columns, columns) self.assertEqual(self.columns, columns)
self.assertEqual(tuple(self.data), tuple(data)) self.assertEqual(tuple(self.data), tuple(data))
@@ -4948,8 +4953,8 @@ class TestServerList(_TestServerList):
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.search_opts['config_drive'] = True self.kwargs['config_drive'] = True
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.assertEqual(self.columns, columns) self.assertEqual(self.columns, columns)
self.assertEqual(tuple(self.data), tuple(data)) self.assertEqual(tuple(self.data), tuple(data))
@@ -4964,8 +4969,8 @@ class TestServerList(_TestServerList):
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.search_opts['config_drive'] = False self.kwargs['config_drive'] = False
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.assertEqual(self.columns, columns) self.assertEqual(self.columns, columns)
self.assertEqual(tuple(self.data), tuple(data)) self.assertEqual(tuple(self.data), tuple(data))
@@ -4980,8 +4985,8 @@ class TestServerList(_TestServerList):
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.search_opts['progress'] = '100' self.kwargs['progress'] = '100'
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.assertEqual(self.columns, columns) self.assertEqual(self.columns, columns)
self.assertEqual(tuple(self.data), tuple(data)) self.assertEqual(tuple(self.data), tuple(data))
@@ -5005,8 +5010,8 @@ class TestServerList(_TestServerList):
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.search_opts['vm_state'] = 'active' self.kwargs['vm_state'] = 'active'
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.assertEqual(self.columns, columns) self.assertEqual(self.columns, columns)
self.assertEqual(tuple(self.data), tuple(data)) self.assertEqual(tuple(self.data), tuple(data))
@@ -5021,8 +5026,8 @@ class TestServerList(_TestServerList):
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.search_opts['task_state'] = 'deleting' self.kwargs['task_state'] = 'deleting'
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.assertEqual(self.columns, columns) self.assertEqual(self.columns, columns)
self.assertEqual(tuple(self.data), tuple(data)) self.assertEqual(tuple(self.data), tuple(data))
@@ -5037,33 +5042,31 @@ class TestServerList(_TestServerList):
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.search_opts['power_state'] = 1 self.kwargs['power_state'] = 1
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.assertEqual(self.columns, columns) self.assertEqual(self.columns, columns)
self.assertEqual(tuple(self.data), tuple(data)) self.assertEqual(tuple(self.data), tuple(data))
def test_server_list_long_with_host_status_v216(self): def test_server_list_long_with_host_status_v216(self):
self.app.client_manager.compute.api_version = \ self._set_mock_microversion('2.16')
api_versions.APIVersion('2.16')
self.data1 = tuple( self.data1 = tuple(
( (
s.id, s.id,
s.name, s.name,
s.status, s.status,
getattr(s, 'OS-EXT-STS:task_state'), getattr(s, 'task_state'),
server.PowerStateColumn( server.PowerStateColumn(
getattr(s, 'OS-EXT-STS:power_state') getattr(s, 'power_state')
), ),
format_columns.DictListColumn(s.networks), server.AddressesColumn(s.addresses),
# Image will be an empty string if boot-from-volume # Image will be an empty string if boot-from-volume
self.image.name if s.image else server.IMAGE_STRING_FOR_BFV, self.image.name if s.image else server.IMAGE_STRING_FOR_BFV,
s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV, s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV,
self.flavor.name, self.flavor.name,
s.flavor['id'], s.flavor['id'],
getattr(s, 'OS-EXT-AZ:availability_zone'), getattr(s, 'availability_zone'),
getattr(s, 'OS-EXT-SRV-ATTR:host'), server.HostColumn(getattr(s, 'hypervisor_hostname')),
s.Metadata, format_columns.DictColumn(s.metadata),
) for s in self.servers) ) for s in self.servers)
arglist = [ arglist = [
@@ -5078,18 +5081,18 @@ class TestServerList(_TestServerList):
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.assertEqual(self.columns_long, columns) self.assertEqual(self.columns_long, columns)
self.assertEqual(tuple(self.data1), tuple(data)) self.assertEqual(tuple(self.data1), tuple(data))
# Next test with host_status in the data -- the column should be # Next test with host_status in the data -- the column should be
# present in this case. # present in this case.
self.servers_mock.reset_mock() self.sdk_client.servers.reset_mock()
self.attrs['host_status'] = 'UP' self.attrs['host_status'] = 'UP'
servers = self.setup_servers_mock(3) servers = self.setup_sdk_servers_mock(3)
self.servers_mock.list.return_value = servers self.sdk_client.servers.return_value = servers
# Make sure the returned image and flavor IDs match the servers. # Make sure the returned image and flavor IDs match the servers.
Image = collections.namedtuple('Image', 'id name') Image = collections.namedtuple('Image', 'id name')
@@ -5099,12 +5102,6 @@ class TestServerList(_TestServerList):
for s in servers if s.image for s in servers if s.image
] ]
Flavor = collections.namedtuple('Flavor', 'id name')
self.flavors_mock.list.return_value = [
Flavor(id=s.flavor['id'], name=self.flavor.name)
for s in servers
]
# Add the expected host_status column and data. # Add the expected host_status column and data.
columns_long = self.columns_long + ('Host Status',) columns_long = self.columns_long + ('Host Status',)
self.data2 = tuple( self.data2 = tuple(
@@ -5112,25 +5109,25 @@ class TestServerList(_TestServerList):
s.id, s.id,
s.name, s.name,
s.status, s.status,
getattr(s, 'OS-EXT-STS:task_state'), getattr(s, 'task_state'),
server.PowerStateColumn( server.PowerStateColumn(
getattr(s, 'OS-EXT-STS:power_state') getattr(s, 'power_state')
), ),
format_columns.DictListColumn(s.networks), server.AddressesColumn(s.addresses),
# Image will be an empty string if boot-from-volume # Image will be an empty string if boot-from-volume
self.image.name if s.image else server.IMAGE_STRING_FOR_BFV, self.image.name if s.image else server.IMAGE_STRING_FOR_BFV,
s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV, s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV,
self.flavor.name, self.flavor.name,
s.flavor['id'], s.flavor['id'],
getattr(s, 'OS-EXT-AZ:availability_zone'), getattr(s, 'availability_zone'),
getattr(s, 'OS-EXT-SRV-ATTR:host'), server.HostColumn(getattr(s, 'hypervisor_hostname')),
s.Metadata, format_columns.DictColumn(s.metadata),
s.host_status, s.host_status,
) for s in servers) ) for s in servers)
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.assertEqual(columns_long, columns) self.assertEqual(columns_long, columns)
self.assertEqual(tuple(self.data2), tuple(data)) self.assertEqual(tuple(self.data2), tuple(data))
@@ -5178,8 +5175,8 @@ class TestServerListV273(_TestServerList):
} }
# The servers to be listed. # The servers to be listed.
self.servers = self.setup_servers_mock(3) self.servers = self.setup_sdk_servers_mock(3)
self.servers_mock.list.return_value = self.servers self.sdk_client.servers.return_value = self.servers
Image = collections.namedtuple('Image', 'id name') Image = collections.namedtuple('Image', 'id name')
self.images_mock.return_value = [ self.images_mock.return_value = [
@@ -5190,14 +5187,14 @@ class TestServerListV273(_TestServerList):
# The flavor information is embedded, so now reason for this to be # The flavor information is embedded, so now reason for this to be
# called # called
self.flavors_mock.list = mock.NonCallableMock() self.sdk_client.flavors = mock.NonCallableMock()
self.data = tuple( self.data = tuple(
( (
s.id, s.id,
s.name, s.name,
s.status, s.status,
format_columns.DictListColumn(s.networks), server.AddressesColumn(s.addresses),
# Image will be an empty string if boot-from-volume # Image will be an empty string if boot-from-volume
self.image.name if s.image else server.IMAGE_STRING_FOR_BFV, self.image.name if s.image else server.IMAGE_STRING_FOR_BFV,
self.flavor.name, self.flavor.name,
@@ -5221,8 +5218,7 @@ class TestServerListV273(_TestServerList):
def test_server_list_with_locked(self): def test_server_list_with_locked(self):
self.app.client_manager.compute.api_version = \ self._set_mock_microversion('2.73')
api_versions.APIVersion('2.73')
arglist = [ arglist = [
'--locked' '--locked'
] ]
@@ -5233,16 +5229,15 @@ class TestServerListV273(_TestServerList):
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.search_opts['locked'] = True self.kwargs['locked'] = True
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.columns, columns)
self.assertCountEqual(self.data, tuple(data)) self.assertCountEqual(self.data, tuple(data))
def test_server_list_with_unlocked_v273(self): def test_server_list_with_unlocked_v273(self):
self._set_mock_microversion('2.73')
self.app.client_manager.compute.api_version = \
api_versions.APIVersion('2.73')
arglist = [ arglist = [
'--unlocked' '--unlocked'
] ]
@@ -5253,16 +5248,15 @@ class TestServerListV273(_TestServerList):
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.search_opts['locked'] = False self.kwargs['locked'] = False
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.columns, columns)
self.assertCountEqual(self.data, tuple(data)) self.assertCountEqual(self.data, tuple(data))
def test_server_list_with_locked_and_unlocked(self): def test_server_list_with_locked_and_unlocked(self):
self.app.client_manager.compute.api_version = \ self._set_mock_microversion('2.73')
api_versions.APIVersion('2.73')
arglist = [ arglist = [
'--locked', '--locked',
'--unlocked' '--unlocked'
@@ -5278,8 +5272,7 @@ class TestServerListV273(_TestServerList):
self.assertIn('Argument parse failed', str(ex)) self.assertIn('Argument parse failed', str(ex))
def test_server_list_with_changes_before(self): def test_server_list_with_changes_before(self):
self.app.client_manager.compute.api_version = ( self._set_mock_microversion('2.66')
api_versions.APIVersion('2.66'))
arglist = [ arglist = [
'--changes-before', '2016-03-05T06:27:59Z', '--changes-before', '2016-03-05T06:27:59Z',
'--deleted' '--deleted'
@@ -5292,10 +5285,10 @@ class TestServerListV273(_TestServerList):
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.search_opts['changes-before'] = '2016-03-05T06:27:59Z' self.kwargs['changes-before'] = '2016-03-05T06:27:59Z'
self.search_opts['deleted'] = True self.kwargs['deleted'] = True
self.servers_mock.list.assert_called_with(**self.kwargs) self.sdk_client.servers.assert_called_with(**self.kwargs)
self.assertCountEqual(self.columns, columns) self.assertCountEqual(self.columns, columns)
self.assertCountEqual(self.data, tuple(data)) self.assertCountEqual(self.data, tuple(data))
@@ -5303,9 +5296,7 @@ class TestServerListV273(_TestServerList):
@mock.patch.object(iso8601, 'parse_date', side_effect=iso8601.ParseError) @mock.patch.object(iso8601, 'parse_date', side_effect=iso8601.ParseError)
def test_server_list_with_invalid_changes_before( def test_server_list_with_invalid_changes_before(
self, mock_parse_isotime): self, mock_parse_isotime):
self.app.client_manager.compute.api_version = ( self._set_mock_microversion('2.66')
api_versions.APIVersion('2.66'))
arglist = [ arglist = [
'--changes-before', 'Invalid time value', '--changes-before', 'Invalid time value',
] ]
@@ -5325,8 +5316,7 @@ class TestServerListV273(_TestServerList):
) )
def test_server_with_changes_before_pre_v266(self): def test_server_with_changes_before_pre_v266(self):
self.app.client_manager.compute.api_version = ( self._set_mock_microversion('2.65')
api_versions.APIVersion('2.65'))
arglist = [ arglist = [
'--changes-before', '2016-03-05T06:27:59Z', '--changes-before', '2016-03-05T06:27:59Z',
@@ -5344,8 +5334,7 @@ class TestServerListV273(_TestServerList):
parsed_args) parsed_args)
def test_server_list_v269_with_partial_constructs(self): def test_server_list_v269_with_partial_constructs(self):
self.app.client_manager.compute.api_version = \ self._set_mock_microversion('2.69')
api_versions.APIVersion('2.69')
arglist = [] arglist = []
verifylist = [] verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -5371,10 +5360,10 @@ class TestServerListV273(_TestServerList):
# it will fail at formatting the networks info later on. # it will fail at formatting the networks info later on.
"networks": {} "networks": {}
} }
server = compute_fakes.fakes.FakeResource( fake_server = compute_fakes.fakes.FakeResource(
info=server_dict, info=server_dict,
) )
self.servers.append(server) self.servers.append(fake_server)
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
# get the first three servers out since our interest is in the partial # get the first three servers out since our interest is in the partial
# server. # server.
@@ -5384,7 +5373,7 @@ class TestServerListV273(_TestServerList):
partial_server = next(data) partial_server = next(data)
expected_row = ( expected_row = (
'server-id-95a56bfc4xxxxxx28d7e418bfd97813a', '', 'server-id-95a56bfc4xxxxxx28d7e418bfd97813a', '',
'UNKNOWN', format_columns.DictListColumn({}), '', '') 'UNKNOWN', server.AddressesColumn(''), '', '')
self.assertEqual(expected_row, partial_server) self.assertEqual(expected_row, partial_server)

View File

@@ -0,0 +1,5 @@
---
features:
- |
The ``server list`` command now uses the OpenStack SDK instead of the
Python nova bindings.