diff options
Diffstat (limited to 'openstackclient')
195 files changed, 2308 insertions, 610 deletions
diff --git a/openstackclient/api/api.py b/openstackclient/api/api.py index 7e2fe38f..d4772f94 100644 --- a/openstackclient/api/api.py +++ b/openstackclient/api/api.py @@ -13,11 +13,10 @@ """Base API Library""" -import simplejson as json - from keystoneauth1 import exceptions as ks_exceptions from keystoneauth1 import session as ks_session from osc_lib import exceptions +import simplejson as json from openstackclient.i18n import _ diff --git a/openstackclient/api/object_store_v1.py b/openstackclient/api/object_store_v1.py index d1e5dfaf..c8514a57 100644 --- a/openstackclient/api/object_store_v1.py +++ b/openstackclient/api/object_store_v1.py @@ -19,12 +19,16 @@ import os import sys from osc_lib import utils -import six from six.moves import urllib from openstackclient.api import api +GLOBAL_READ_ACL = ".r:*" +LIST_CONTENTS_ACL = ".rlistings" +PUBLIC_CONTAINER_ACLS = [GLOBAL_READ_ACL, LIST_CONTENTS_ACL] + + class APIv1(api.BaseAPI): """Object Store v1 API""" @@ -34,15 +38,32 @@ class APIv1(api.BaseAPI): def container_create( self, container=None, + public=False, + storage_policy=None ): """Create a container :param string container: name of container to create + :param bool public: + Boolean value indicating if the container should be publicly + readable. Defaults to False. + :param string storage_policy: + Name of the a specific storage policy to use. If not specified + swift will use its default storage policy. :returns: dict of returned headers """ - response = self.create(urllib.parse.quote(container), method='PUT') + + headers = {} + if public: + headers['x-container-read'] = ",".join(PUBLIC_CONTAINER_ACLS) + if storage_policy is not None: + headers['x-storage-policy'] = storage_policy + + response = self.create( + urllib.parse.quote(container), method='PUT', headers=headers) + data = { 'account': self._find_account_id(), 'container': container, @@ -174,7 +195,8 @@ class APIv1(api.BaseAPI): 'object_count': response.headers.get( 'x-container-object-count' ), - 'bytes_used': response.headers.get('x-container-bytes-used') + 'bytes_used': response.headers.get('x-container-bytes-used'), + 'storage_policy': response.headers.get('x-storage-policy'), } if 'x-container-read' in response.headers: @@ -559,7 +581,7 @@ class APIv1(api.BaseAPI): log = logging.getLogger(__name__ + '._set_properties') headers = {} - for k, v in six.iteritems(properties): + for k, v in properties.items(): if not utils.is_ascii(k) or not utils.is_ascii(v): log.error('Cannot set property %s to non-ascii value', k) continue @@ -572,7 +594,7 @@ class APIv1(api.BaseAPI): # Add in properties as a top level key, this is consistent with other # OSC commands properties = {} - for k, v in six.iteritems(headers): + for k, v in headers.items(): if k.lower().startswith(header_tag): properties[k[len(header_tag):]] = v return properties diff --git a/openstackclient/common/availability_zone.py b/openstackclient/common/availability_zone.py index b2385ef7..3b2fa848 100644 --- a/openstackclient/common/availability_zone.py +++ b/openstackclient/common/availability_zone.py @@ -19,7 +19,6 @@ import logging from novaclient import exceptions as nova_exceptions from osc_lib.command import command from osc_lib import utils -import six from openstackclient.i18n import _ @@ -47,11 +46,11 @@ def _xform_compute_availability_zone(az, include_extra): return result if hasattr(az, 'hosts') and az.hosts: - for host, services in six.iteritems(az.hosts): + for host, services in az.hosts.items(): host_info = copy.deepcopy(zone_info) host_info['host_name'] = host - for svc, state in six.iteritems(services): + for svc, state in services.items(): info = copy.deepcopy(host_info) info['service_name'] = svc info['service_status'] = '%s %s %s' % ( diff --git a/openstackclient/common/configuration.py b/openstackclient/common/configuration.py index 53b30d5f..49ef0e05 100644 --- a/openstackclient/common/configuration.py +++ b/openstackclient/common/configuration.py @@ -15,7 +15,6 @@ from keystoneauth1.loading import base from osc_lib.command import command -import six from openstackclient.i18n import _ @@ -59,9 +58,9 @@ class ShowConfiguration(command.ShowOne): if o.secret ] - for key, value in six.iteritems(info.pop('auth', {})): + for key, value in info.pop('auth', {}).items(): if parsed_args.mask and key.lower() in secret_opts: value = REDACTED info['auth.' + key] = value - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) diff --git a/openstackclient/common/module.py b/openstackclient/common/module.py index 20497f21..f55fdce0 100644 --- a/openstackclient/common/module.py +++ b/openstackclient/common/module.py @@ -19,7 +19,6 @@ import sys from osc_lib.command import command from osc_lib import utils -import six from openstackclient.i18n import _ @@ -113,4 +112,4 @@ class ListModule(command.ShowOne): # Catch all exceptions, just skip it pass - return zip(*sorted(six.iteritems(data))) + return zip(*sorted(data.items())) diff --git a/openstackclient/common/quota.py b/openstackclient/common/quota.py index 80c8749a..37437344 100644 --- a/openstackclient/common/quota.py +++ b/openstackclient/common/quota.py @@ -21,7 +21,6 @@ import sys from osc_lib.command import command from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.network import common @@ -650,7 +649,7 @@ class ShowQuota(command.ShowOne, BaseQuota): for k, v in itertools.chain( COMPUTE_QUOTAS.items(), NOVA_NETWORK_QUOTAS.items(), VOLUME_QUOTAS.items(), NETWORK_QUOTAS.items()): - if not k == v and info.get(k): + if not k == v and info.get(k) is not None: info[v] = info[k] info.pop(k) @@ -663,4 +662,4 @@ class ShowQuota(command.ShowOne, BaseQuota): project_name = project_info['name'] info['project_name'] = project_name - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) diff --git a/openstackclient/compute/v2/agent.py b/openstackclient/compute/v2/agent.py index 151dcc1e..3feb99ec 100644 --- a/openstackclient/compute/v2/agent.py +++ b/openstackclient/compute/v2/agent.py @@ -20,7 +20,6 @@ import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -77,7 +76,7 @@ class CreateAgent(command.ShowOne): parsed_args.hypervisor ) agent = compute_client.agents.create(*args)._info.copy() - return zip(*sorted(six.iteritems(agent))) + return zip(*sorted(agent.items())) class DeleteAgent(command.Command): diff --git a/openstackclient/compute/v2/aggregate.py b/openstackclient/compute/v2/aggregate.py index 3834de1f..599659a3 100644 --- a/openstackclient/compute/v2/aggregate.py +++ b/openstackclient/compute/v2/aggregate.py @@ -23,7 +23,6 @@ from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -68,7 +67,7 @@ class AddAggregateHost(command.ShowOne): 'properties': format_columns.DictColumn(info.pop('metadata')), }, ) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) class CreateAggregate(command.ShowOne): @@ -125,7 +124,7 @@ class CreateAggregate(command.ShowOne): 'properties': properties, }, ) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) class DeleteAggregate(command.Command): @@ -255,7 +254,7 @@ class RemoveAggregateHost(command.ShowOne): 'properties': format_columns.DictColumn(info.pop('metadata')), }, ) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) class SetAggregate(command.Command): @@ -372,7 +371,7 @@ class ShowAggregate(command.ShowOne): info = {} info.update(data._info) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) class UnsetAggregate(command.Command): diff --git a/openstackclient/compute/v2/console.py b/openstackclient/compute/v2/console.py index b2f7288f..110b21b8 100644 --- a/openstackclient/compute/v2/console.py +++ b/openstackclient/compute/v2/console.py @@ -18,7 +18,6 @@ from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import utils -import six from openstackclient.i18n import _ @@ -138,4 +137,4 @@ class ShowConsoleURL(command.ShowOne): # handle for different microversion API. console_data = data.get('remote_console', data.get('console')) info.update(console_data) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) diff --git a/openstackclient/compute/v2/flavor.py b/openstackclient/compute/v2/flavor.py index 4f1e48af..42649db5 100644 --- a/openstackclient/compute/v2/flavor.py +++ b/openstackclient/compute/v2/flavor.py @@ -22,7 +22,6 @@ from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common as identity_common @@ -195,7 +194,7 @@ class CreateFlavor(command.ShowOne): flavor_info.pop("links") flavor_info['properties'] = utils.format_dict(flavor.get_keys()) - return zip(*sorted(six.iteritems(flavor_info))) + return zip(*sorted(flavor_info.items())) class DeleteFlavor(command.Command): @@ -447,7 +446,7 @@ class ShowFlavor(command.ShowOne): flavor['properties'] = utils.format_dict(resource_flavor.get_keys()) - return zip(*sorted(six.iteritems(flavor))) + return zip(*sorted(flavor.items())) class UnsetFlavor(command.Command): diff --git a/openstackclient/compute/v2/hypervisor.py b/openstackclient/compute/v2/hypervisor.py index 0d367fee..7f110028 100644 --- a/openstackclient/compute/v2/hypervisor.py +++ b/openstackclient/compute/v2/hypervisor.py @@ -20,7 +20,6 @@ import re from novaclient import exceptions as nova_exceptions from osc_lib.command import command from osc_lib import utils -import six from openstackclient.i18n import _ @@ -126,4 +125,4 @@ class ShowHypervisor(command.ShowOne): hypervisor["service_host"] = hypervisor["service"]["host"] del hypervisor["service"] - return zip(*sorted(six.iteritems(hypervisor))) + return zip(*sorted(hypervisor.items())) diff --git a/openstackclient/compute/v2/hypervisor_stats.py b/openstackclient/compute/v2/hypervisor_stats.py index b0413005..4493e080 100644 --- a/openstackclient/compute/v2/hypervisor_stats.py +++ b/openstackclient/compute/v2/hypervisor_stats.py @@ -15,7 +15,6 @@ """Hypervisor Stats action implementations""" from osc_lib.command import command -import six from openstackclient.i18n import _ @@ -27,4 +26,4 @@ class ShowHypervisorStats(command.ShowOne): compute_client = self.app.client_manager.compute hypervisor_stats = compute_client.hypervisors.statistics().to_dict() - return zip(*sorted(six.iteritems(hypervisor_stats))) + return zip(*sorted(hypervisor_stats.items())) diff --git a/openstackclient/compute/v2/keypair.py b/openstackclient/compute/v2/keypair.py index 851cced0..2b365ceb 100644 --- a/openstackclient/compute/v2/keypair.py +++ b/openstackclient/compute/v2/keypair.py @@ -23,7 +23,6 @@ import sys from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -101,7 +100,7 @@ class CreateKeypair(command.ShowOne): del info['public_key'] if 'private_key' in info: del info['private_key'] - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) else: sys.stdout.write(keypair.private_key) return ({}, {}) @@ -184,7 +183,7 @@ class ShowKeypair(command.ShowOne): info.update(keypair._info) if not parsed_args.public_key: del info['public_key'] - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) else: # NOTE(dtroyer): a way to get the public key in a similar form # as the private key in the create command diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py index 414abb62..5cc73284 100644 --- a/openstackclient/compute/v2/server.py +++ b/openstackclient/compute/v2/server.py @@ -689,8 +689,8 @@ class CreateServer(command.ShowOne): parser.add_argument( '--hint', metavar='<key=value>', - action='append', - default=[], + action=parseractions.KeyValueAppendAction, + default={}, help=_('Hints for the scheduler (optional extension)'), ) parser.add_argument( @@ -986,16 +986,12 @@ class CreateServer(command.ShowOne): security_group_names.append(sg['name']) hints = {} - for hint in parsed_args.hint: - key, _sep, value = hint.partition('=') - # NOTE(vish): multiple copies of the same hint will - # result in a list of values - if key in hints: - if isinstance(hints[key], six.string_types): - hints[key] = [hints[key]] - hints[key] += [value] + for key, values in parsed_args.hint.items(): + # only items with multiple values will result in a list + if len(values) == 1: + hints[key] = values[0] else: - hints[key] = value + hints[key] = values # What does a non-boolean value for config-drive do? # --config-drive argument is either a volume id or @@ -1069,7 +1065,7 @@ class CreateServer(command.ShowOne): raise SystemExit details = _prep_server_detail(compute_client, image_client, server) - return zip(*sorted(six.iteritems(details))) + return zip(*sorted(details.items())) class CreateServerDump(command.Command): @@ -1242,7 +1238,8 @@ class ListServer(command.Lister): default=None, help=_('The last server of the previous page. Display ' 'list of servers after marker. Display all servers if not ' - 'specified. (name or ID)') + 'specified. When used with ``--deleted``, the marker must ' + 'be an ID, otherwise a name or ID can be used.'), ) parser.add_argument( '--limit', @@ -1450,9 +1447,17 @@ class ListServer(command.Lister): mixed_case_fields = [] marker_id = None + if parsed_args.marker: - marker_id = utils.find_resource(compute_client.servers, - parsed_args.marker).id + # Check if both "--marker" and "--deleted" are used. + # In that scenario a lookup is not needed as the marker + # needs to be an ID, because find_resource does not + # handle deleted resources + if parsed_args.deleted: + marker_id = parsed_args.marker + else: + marker_id = utils.find_resource(compute_client.servers, + parsed_args.marker).id data = compute_client.servers.list(search_opts=search_opts, marker=marker_id, @@ -1958,7 +1963,7 @@ class RebuildServer(command.ShowOne): details = _prep_server_detail(compute_client, image_client, server, refresh=False) - return zip(*sorted(six.iteritems(details))) + return zip(*sorted(details.items())) class RemoveFixedIP(command.Command): @@ -2528,7 +2533,7 @@ class ShowServer(command.ShowOne): self.app.client_manager.image, server, refresh=False) - return zip(*sorted(six.iteritems(data))) + return zip(*sorted(data.items())) class SshServer(command.Command): diff --git a/openstackclient/compute/v2/server_backup.py b/openstackclient/compute/v2/server_backup.py index a79f5f70..1d560dc0 100644 --- a/openstackclient/compute/v2/server_backup.py +++ b/openstackclient/compute/v2/server_backup.py @@ -19,7 +19,6 @@ from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from oslo_utils import importutils -import six from openstackclient.i18n import _ @@ -129,4 +128,4 @@ class CreateServerBackup(command.ShowOne): ] ) info = image_module._format_image(image) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) diff --git a/openstackclient/compute/v2/server_event.py b/openstackclient/compute/v2/server_event.py index 6d33d02d..4fcc9136 100644 --- a/openstackclient/compute/v2/server_event.py +++ b/openstackclient/compute/v2/server_event.py @@ -19,7 +19,6 @@ import logging from osc_lib.command import command from osc_lib import utils -import six from openstackclient.i18n import _ @@ -122,4 +121,4 @@ class ShowServerEvent(command.ShowOne): action_detail = compute_client.instance_action.get( server_id, parsed_args.request_id) - return zip(*sorted(six.iteritems(action_detail.to_dict()))) + return zip(*sorted(action_detail.to_dict().items())) diff --git a/openstackclient/compute/v2/server_image.py b/openstackclient/compute/v2/server_image.py index 3bc5d94a..b93cd4d8 100644 --- a/openstackclient/compute/v2/server_image.py +++ b/openstackclient/compute/v2/server_image.py @@ -21,7 +21,6 @@ from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils from oslo_utils import importutils -import six from openstackclient.i18n import _ @@ -109,4 +108,4 @@ class CreateServerImage(command.ShowOne): ] ) info = image_module._format_image(image) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) diff --git a/openstackclient/compute/v2/usage.py b/openstackclient/compute/v2/usage.py index f84cd61d..307c238a 100644 --- a/openstackclient/compute/v2/usage.py +++ b/openstackclient/compute/v2/usage.py @@ -21,7 +21,6 @@ import datetime from novaclient import api_versions from osc_lib.command import command from osc_lib import utils -import six from openstackclient.i18n import _ @@ -236,4 +235,4 @@ class ShowUsage(command.ShowOne): info['Disk GB-Hours'] = ( float("%.2f" % usage.total_local_gb_usage) if hasattr(usage, "total_local_gb_usage") else None) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) diff --git a/openstackclient/identity/v2_0/catalog.py b/openstackclient/identity/v2_0/catalog.py index 5d1e3062..ccedbf33 100644 --- a/openstackclient/identity/v2_0/catalog.py +++ b/openstackclient/identity/v2_0/catalog.py @@ -19,7 +19,6 @@ from cliff import columns as cliff_columns from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -102,4 +101,4 @@ class ShowCatalog(command.ShowOne): LOG.error(_('service %s not found\n'), parsed_args.service) return ((), ()) - return zip(*sorted(six.iteritems(data))) + return zip(*sorted(data.items())) diff --git a/openstackclient/identity/v2_0/ec2creds.py b/openstackclient/identity/v2_0/ec2creds.py index 0bc48322..f712bf45 100644 --- a/openstackclient/identity/v2_0/ec2creds.py +++ b/openstackclient/identity/v2_0/ec2creds.py @@ -21,7 +21,6 @@ import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -82,7 +81,7 @@ class CreateEC2Creds(command.ShowOne): {'project_id': info.pop('tenant_id')} ) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) class DeleteEC2Creds(command.Command): @@ -206,4 +205,4 @@ class ShowEC2Creds(command.ShowOne): {'project_id': info.pop('tenant_id')} ) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) diff --git a/openstackclient/identity/v2_0/endpoint.py b/openstackclient/identity/v2_0/endpoint.py index 1628e488..57906ddf 100644 --- a/openstackclient/identity/v2_0/endpoint.py +++ b/openstackclient/identity/v2_0/endpoint.py @@ -20,7 +20,6 @@ import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common @@ -76,7 +75,7 @@ class CreateEndpoint(command.ShowOne): info.update(endpoint._info) info['service_name'] = service.name info['service_type'] = service.type - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) class DeleteEndpoint(command.Command): @@ -178,4 +177,4 @@ class ShowEndpoint(command.ShowOne): info.update(match._info) info['service_name'] = service.name info['service_type'] = service.type - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) diff --git a/openstackclient/identity/v2_0/project.py b/openstackclient/identity/v2_0/project.py index e0018860..f431c021 100644 --- a/openstackclient/identity/v2_0/project.py +++ b/openstackclient/identity/v2_0/project.py @@ -23,7 +23,6 @@ from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -100,7 +99,7 @@ class CreateProject(command.ShowOne): # TODO(stevemar): Remove the line below when we support multitenancy project._info.pop('parent_id', None) - return zip(*sorted(six.iteritems(project._info))) + return zip(*sorted(project._info.items())) class DeleteProject(command.Command): @@ -299,7 +298,7 @@ class ShowProject(command.ShowOne): properties[k] = v info['properties'] = format_columns.DictColumn(properties) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) class UnsetProject(command.Command): diff --git a/openstackclient/identity/v2_0/role.py b/openstackclient/identity/v2_0/role.py index e9fe50fa..5c53fbcd 100644 --- a/openstackclient/identity/v2_0/role.py +++ b/openstackclient/identity/v2_0/role.py @@ -21,7 +21,6 @@ from keystoneauth1 import exceptions as ks_exc from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -69,7 +68,7 @@ class AddRole(command.ShowOne): info = {} info.update(role._info) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) class CreateRole(command.ShowOne): @@ -105,7 +104,7 @@ class CreateRole(command.ShowOne): info = {} info.update(role._info) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) class DeleteRole(command.Command): @@ -217,4 +216,4 @@ class ShowRole(command.ShowOne): info = {} info.update(role._info) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) diff --git a/openstackclient/identity/v2_0/service.py b/openstackclient/identity/v2_0/service.py index 653de8eb..afc0b3d7 100644 --- a/openstackclient/identity/v2_0/service.py +++ b/openstackclient/identity/v2_0/service.py @@ -20,7 +20,6 @@ import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common @@ -65,7 +64,7 @@ class CreateService(command.ShowOne): info = {} info.update(service._info) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) class DeleteService(command.Command): @@ -153,11 +152,11 @@ class ShowService(command.ShowOne): if parsed_args.catalog: endpoints = auth_ref.service_catalog.get_endpoints( service_type=parsed_args.service) - for (service, service_endpoints) in six.iteritems(endpoints): + for (service, service_endpoints) in endpoints.items(): if service_endpoints: info = {"type": service} info.update(service_endpoints[0]) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) msg = _("No service catalog with a type, name or ID of '%s' " "exists.") % (parsed_args.service) @@ -166,4 +165,4 @@ class ShowService(command.ShowOne): service = common.find_service(identity_client, parsed_args.service) info = {} info.update(service._info) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) diff --git a/openstackclient/identity/v2_0/token.py b/openstackclient/identity/v2_0/token.py index 3b08b475..205e15d3 100644 --- a/openstackclient/identity/v2_0/token.py +++ b/openstackclient/identity/v2_0/token.py @@ -17,7 +17,6 @@ from osc_lib.command import command from osc_lib import exceptions -import six from openstackclient.i18n import _ @@ -49,7 +48,7 @@ class IssueToken(command.ShowOne): data['project_id'] = auth_ref.project_id if auth_ref.user_id: data['user_id'] = auth_ref.user_id - return zip(*sorted(six.iteritems(data))) + return zip(*sorted(data.items())) class RevokeToken(command.Command): diff --git a/openstackclient/identity/v2_0/user.py b/openstackclient/identity/v2_0/user.py index 0675877b..8dac093e 100644 --- a/openstackclient/identity/v2_0/user.py +++ b/openstackclient/identity/v2_0/user.py @@ -23,7 +23,6 @@ from keystoneauth1 import exceptions as ks_exc from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -154,7 +153,7 @@ class CreateUser(command.ShowOne): info = {} info.update(user._info) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) class DeleteUser(command.Command): @@ -418,4 +417,4 @@ class ShowUser(command.ShowOne): {'project_id': info.pop('tenant_id')} ) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) diff --git a/openstackclient/identity/v3/access_rule.py b/openstackclient/identity/v3/access_rule.py new file mode 100644 index 00000000..65e78be1 --- /dev/null +++ b/openstackclient/identity/v3/access_rule.py @@ -0,0 +1,118 @@ +# Copyright 2019 SUSE LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +"""Identity v3 Access Rule action implementations""" + +import logging + +from osc_lib.command import command +from osc_lib import exceptions +from osc_lib import utils +import six + +from openstackclient.i18n import _ +from openstackclient.identity import common + + +LOG = logging.getLogger(__name__) + + +class DeleteAccessRule(command.Command): + _description = _("Delete access rule(s)") + + def get_parser(self, prog_name): + parser = super(DeleteAccessRule, self).get_parser(prog_name) + parser.add_argument( + 'access_rule', + metavar='<access-rule>', + nargs="+", + help=_('Access rule(s) to delete (name or ID)'), + ) + return parser + + def take_action(self, parsed_args): + identity_client = self.app.client_manager.identity + + errors = 0 + for ac in parsed_args.access_rule: + try: + access_rule = utils.find_resource( + identity_client.access_rules, ac) + identity_client.access_rules.delete(access_rule.id) + except Exception as e: + errors += 1 + LOG.error(_("Failed to delete access rule with " + "ID '%(ac)s': %(e)s"), + {'ac': ac, 'e': e}) + + if errors > 0: + total = len(parsed_args.access_rule) + msg = (_("%(errors)s of %(total)s access rules failed " + "to delete.") % {'errors': errors, 'total': total}) + raise exceptions.CommandError(msg) + + +class ListAccessRule(command.Lister): + _description = _("List access rules") + + def get_parser(self, prog_name): + parser = super(ListAccessRule, self).get_parser(prog_name) + parser.add_argument( + '--user', + metavar='<user>', + help=_('User whose access rules to list (name or ID)'), + ) + common.add_user_domain_option_to_parser(parser) + return parser + + def take_action(self, parsed_args): + identity_client = self.app.client_manager.identity + if parsed_args.user: + user_id = common.find_user(identity_client, + parsed_args.user, + parsed_args.user_domain).id + else: + user_id = None + + columns = ('ID', 'Service', 'Method', 'Path') + data = identity_client.access_rules.list( + user=user_id) + return (columns, + (utils.get_item_properties( + s, columns, + formatters={}, + ) for s in data)) + + +class ShowAccessRule(command.ShowOne): + _description = _("Display access rule details") + + def get_parser(self, prog_name): + parser = super(ShowAccessRule, self).get_parser(prog_name) + parser.add_argument( + 'access_rule', + metavar='<access-rule>', + help=_('Access rule to display (name or ID)'), + ) + return parser + + def take_action(self, parsed_args): + identity_client = self.app.client_manager.identity + access_rule = utils.find_resource(identity_client.access_rules, + parsed_args.access_rule) + + access_rule._info.pop('links', None) + + return zip(*sorted(six.iteritems(access_rule._info))) diff --git a/openstackclient/identity/v3/application_credential.py b/openstackclient/identity/v3/application_credential.py index 747fa20e..a2089856 100644 --- a/openstackclient/identity/v3/application_credential.py +++ b/openstackclient/identity/v3/application_credential.py @@ -16,12 +16,12 @@ """Identity v3 Application Credential action implementations""" import datetime +import json import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common @@ -80,6 +80,17 @@ class CreateApplicationCredential(command.ShowOne): ' other application credentials and trusts (this is the' ' default behavior)'), ) + parser.add_argument( + '--access-rules', + metavar='<access-rules>', + help=_('Either a string or file path containing a JSON-formatted ' + 'list of access rules, each containing a request method, ' + 'path, and service, for example ' + '\'[{"method": "GET", ' + '"path": "/v2.1/servers", ' + '"service": "compute"}]\''), + + ) return parser def take_action(self, parsed_args): @@ -106,6 +117,20 @@ class CreateApplicationCredential(command.ShowOne): else: unrestricted = parsed_args.unrestricted + if parsed_args.access_rules: + try: + access_rules = json.loads(parsed_args.access_rules) + except ValueError: + try: + with open(parsed_args.access_rules) as f: + access_rules = json.load(f) + except IOError: + raise exceptions.CommandError( + _("Access rules is not valid JSON string or file does" + " not exist.")) + else: + access_rules = None + app_cred_manager = identity_client.application_credentials application_credential = app_cred_manager.create( parsed_args.name, @@ -114,6 +139,7 @@ class CreateApplicationCredential(command.ShowOne): description=parsed_args.description, secret=parsed_args.secret, unrestricted=unrestricted, + access_rules=access_rules, ) application_credential._info.pop('links', None) @@ -123,7 +149,7 @@ class CreateApplicationCredential(command.ShowOne): msg = ' '.join(r['name'] for r in roles) application_credential._info['roles'] = msg - return zip(*sorted(six.iteritems(application_credential._info))) + return zip(*sorted(application_credential._info.items())) class DeleteApplicationCredential(command.Command): @@ -217,4 +243,4 @@ class ShowApplicationCredential(command.ShowOne): msg = ' '.join(r['name'] for r in roles) app_cred._info['roles'] = msg - return zip(*sorted(six.iteritems(app_cred._info))) + return zip(*sorted(app_cred._info.items())) diff --git a/openstackclient/identity/v3/catalog.py b/openstackclient/identity/v3/catalog.py index 59430c4c..d1f7d319 100644 --- a/openstackclient/identity/v3/catalog.py +++ b/openstackclient/identity/v3/catalog.py @@ -19,7 +19,6 @@ from cliff import columns as cliff_columns from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -97,4 +96,4 @@ class ShowCatalog(command.ShowOne): LOG.error(_('service %s not found\n'), parsed_args.service) return ((), ()) - return zip(*sorted(six.iteritems(data))) + return zip(*sorted(data.items())) diff --git a/openstackclient/identity/v3/consumer.py b/openstackclient/identity/v3/consumer.py index 6dd24dcc..2f925aba 100644 --- a/openstackclient/identity/v3/consumer.py +++ b/openstackclient/identity/v3/consumer.py @@ -20,7 +20,6 @@ import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -46,7 +45,7 @@ class CreateConsumer(command.ShowOne): parsed_args.description ) consumer._info.pop('links', None) - return zip(*sorted(six.iteritems(consumer._info))) + return zip(*sorted(consumer._info.items())) class DeleteConsumer(command.Command): @@ -142,4 +141,4 @@ class ShowConsumer(command.ShowOne): identity_client.oauth1.consumers, parsed_args.consumer) consumer._info.pop('links', None) - return zip(*sorted(six.iteritems(consumer._info))) + return zip(*sorted(consumer._info.items())) diff --git a/openstackclient/identity/v3/credential.py b/openstackclient/identity/v3/credential.py index 981f940a..bf48df83 100644 --- a/openstackclient/identity/v3/credential.py +++ b/openstackclient/identity/v3/credential.py @@ -20,7 +20,6 @@ import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common @@ -74,7 +73,7 @@ class CreateCredential(command.ShowOne): project=project) credential._info.pop('links') - return zip(*sorted(six.iteritems(credential._info))) + return zip(*sorted(credential._info.items())) class DeleteCredential(command.Command): @@ -225,4 +224,4 @@ class ShowCredential(command.ShowOne): parsed_args.credential) credential._info.pop('links') - return zip(*sorted(six.iteritems(credential._info))) + return zip(*sorted(credential._info.items())) diff --git a/openstackclient/identity/v3/domain.py b/openstackclient/identity/v3/domain.py index 064624ab..dbcc97f6 100644 --- a/openstackclient/identity/v3/domain.py +++ b/openstackclient/identity/v3/domain.py @@ -21,7 +21,6 @@ from keystoneauth1 import exceptions as ks_exc from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common @@ -85,7 +84,7 @@ class CreateDomain(command.ShowOne): raise domain._info.pop('links') - return zip(*sorted(six.iteritems(domain._info))) + return zip(*sorted(domain._info.items())) class DeleteDomain(command.Command): @@ -206,4 +205,4 @@ class ShowDomain(command.ShowOne): domain_str) domain._info.pop('links') - return zip(*sorted(six.iteritems(domain._info))) + return zip(*sorted(domain._info.items())) diff --git a/openstackclient/identity/v3/ec2creds.py b/openstackclient/identity/v3/ec2creds.py index 44e9a2c7..921b9168 100644 --- a/openstackclient/identity/v3/ec2creds.py +++ b/openstackclient/identity/v3/ec2creds.py @@ -17,7 +17,6 @@ import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common @@ -108,7 +107,7 @@ class CreateEC2Creds(command.ShowOne): {'project_id': info.pop('tenant_id')} ) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) class DeleteEC2Creds(command.Command): @@ -209,4 +208,4 @@ class ShowEC2Creds(command.ShowOne): {'project_id': info.pop('tenant_id')} ) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) diff --git a/openstackclient/identity/v3/endpoint.py b/openstackclient/identity/v3/endpoint.py index 858b5036..a3bd2683 100644 --- a/openstackclient/identity/v3/endpoint.py +++ b/openstackclient/identity/v3/endpoint.py @@ -20,7 +20,6 @@ import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common @@ -131,7 +130,7 @@ class CreateEndpoint(command.ShowOne): info.update(endpoint._info) info['service_name'] = get_service_name(service) info['service_type'] = service.type - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) class DeleteEndpoint(command.Command): @@ -389,4 +388,4 @@ class ShowEndpoint(command.ShowOne): info.update(endpoint._info) info['service_name'] = get_service_name(service) info['service_type'] = service.type - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) diff --git a/openstackclient/identity/v3/endpoint_group.py b/openstackclient/identity/v3/endpoint_group.py index 66bd164d..cbe27edb 100644 --- a/openstackclient/identity/v3/endpoint_group.py +++ b/openstackclient/identity/v3/endpoint_group.py @@ -19,7 +19,6 @@ import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common @@ -129,7 +128,7 @@ class CreateEndpointGroup(command.ShowOne, _FiltersReader): info = {} endpoint_group._info.pop('links') info.update(endpoint_group._info) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) class DeleteEndpointGroup(command.Command): @@ -321,4 +320,4 @@ class ShowEndpointGroup(command.ShowOne): info = {} endpoint_group._info.pop('links') info.update(endpoint_group._info) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) diff --git a/openstackclient/identity/v3/federation_protocol.py b/openstackclient/identity/v3/federation_protocol.py index 6429d934..0929469e 100644 --- a/openstackclient/identity/v3/federation_protocol.py +++ b/openstackclient/identity/v3/federation_protocol.py @@ -19,7 +19,6 @@ import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -68,7 +67,7 @@ class CreateProtocol(command.ShowOne): info['identity_provider'] = parsed_args.identity_provider info['mapping'] = info.pop('mapping_id') info.pop('links', None) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) class DeleteProtocol(command.Command): @@ -175,7 +174,7 @@ class SetProtocol(command.Command): # user. info['identity_provider'] = parsed_args.identity_provider info['mapping'] = info.pop('mapping_id') - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) class ShowProtocol(command.ShowOne): @@ -205,4 +204,4 @@ class ShowProtocol(command.ShowOne): info = dict(protocol._info) info['mapping'] = info.pop('mapping_id') info.pop('links', None) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) diff --git a/openstackclient/identity/v3/group.py b/openstackclient/identity/v3/group.py index 02eeadd6..46c3142c 100644 --- a/openstackclient/identity/v3/group.py +++ b/openstackclient/identity/v3/group.py @@ -21,7 +21,6 @@ from keystoneauth1 import exceptions as ks_exc from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common @@ -182,7 +181,7 @@ class CreateGroup(command.ShowOne): raise group._info.pop('links') - return zip(*sorted(six.iteritems(group._info))) + return zip(*sorted(group._info.items())) class DeleteGroup(command.Command): @@ -405,4 +404,4 @@ class ShowGroup(command.ShowOne): domain_name_or_id=parsed_args.domain) group._info.pop('links') - return zip(*sorted(six.iteritems(group._info))) + return zip(*sorted(group._info.items())) diff --git a/openstackclient/identity/v3/identity_provider.py b/openstackclient/identity/v3/identity_provider.py index b3315182..2b2d9d11 100644 --- a/openstackclient/identity/v3/identity_provider.py +++ b/openstackclient/identity/v3/identity_provider.py @@ -19,7 +19,6 @@ from osc_lib.cli import format_columns from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common @@ -106,7 +105,7 @@ class CreateIdentityProvider(command.ShowOne): idp._info.pop('links', None) remote_ids = format_columns.ListColumn(idp._info.pop('remote_ids', [])) idp._info['remote_ids'] = remote_ids - return zip(*sorted(six.iteritems(idp._info))) + return zip(*sorted(idp._info.items())) class DeleteIdentityProvider(command.Command): @@ -248,4 +247,4 @@ class ShowIdentityProvider(command.ShowOne): idp._info.pop('links', None) remote_ids = format_columns.ListColumn(idp._info.pop('remote_ids', [])) idp._info['remote_ids'] = remote_ids - return zip(*sorted(six.iteritems(idp._info))) + return zip(*sorted(idp._info.items())) diff --git a/openstackclient/identity/v3/implied_role.py b/openstackclient/identity/v3/implied_role.py index 4e3df88a..054f3028 100644 --- a/openstackclient/identity/v3/implied_role.py +++ b/openstackclient/identity/v3/implied_role.py @@ -18,7 +18,6 @@ import logging from osc_lib.command import command -import six from openstackclient.i18n import _ @@ -75,7 +74,7 @@ class CreateImpliedRole(command.ShowOne): prior_role_id, implied_role_id) response._info.pop('links', None) return zip(*sorted([(k, v['id']) - for k, v in six.iteritems(response._info)])) + for k, v in response._info.items()])) class DeleteImpliedRole(command.Command): diff --git a/openstackclient/identity/v3/limit.py b/openstackclient/identity/v3/limit.py index f2af81e9..b155cbd8 100644 --- a/openstackclient/identity/v3/limit.py +++ b/openstackclient/identity/v3/limit.py @@ -18,7 +18,6 @@ import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common as common_utils @@ -102,7 +101,7 @@ class CreateLimit(command.ShowOne): ) limit._info.pop('links', None) - return zip(*sorted(six.iteritems(limit._info))) + return zip(*sorted(limit._info.items())) class ListLimit(command.Lister): @@ -198,7 +197,7 @@ class ShowLimit(command.ShowOne): identity_client = self.app.client_manager.identity limit = identity_client.limits.get(parsed_args.limit_id) limit._info.pop('links', None) - return zip(*sorted(six.iteritems(limit._info))) + return zip(*sorted(limit._info.items())) class SetLimit(command.ShowOne): @@ -236,7 +235,7 @@ class SetLimit(command.ShowOne): limit._info.pop('links', None) - return zip(*sorted(six.iteritems(limit._info))) + return zip(*sorted(limit._info.items())) class DeleteLimit(command.Command): diff --git a/openstackclient/identity/v3/mapping.py b/openstackclient/identity/v3/mapping.py index e729c410..7d40a2b7 100644 --- a/openstackclient/identity/v3/mapping.py +++ b/openstackclient/identity/v3/mapping.py @@ -21,7 +21,6 @@ import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -107,7 +106,7 @@ class CreateMapping(command.ShowOne, _RulesReader): rules=rules) mapping._info.pop('links', None) - return zip(*sorted(six.iteritems(mapping._info))) + return zip(*sorted(mapping._info.items())) class DeleteMapping(command.Command): @@ -202,4 +201,4 @@ class ShowMapping(command.ShowOne): mapping = identity_client.federation.mappings.get(parsed_args.mapping) mapping._info.pop('links', None) - return zip(*sorted(six.iteritems(mapping._info))) + return zip(*sorted(mapping._info.items())) diff --git a/openstackclient/identity/v3/policy.py b/openstackclient/identity/v3/policy.py index 3b644195..45674210 100644 --- a/openstackclient/identity/v3/policy.py +++ b/openstackclient/identity/v3/policy.py @@ -20,7 +20,6 @@ import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -57,7 +56,7 @@ class CreatePolicy(command.ShowOne): policy._info.pop('links') policy._info.update({'rules': policy._info.pop('blob')}) - return zip(*sorted(six.iteritems(policy._info))) + return zip(*sorted(policy._info.items())) class DeletePolicy(command.Command): @@ -176,4 +175,4 @@ class ShowPolicy(command.ShowOne): policy._info.pop('links') policy._info.update({'rules': policy._info.pop('blob')}) - return zip(*sorted(six.iteritems(policy._info))) + return zip(*sorted(policy._info.items())) diff --git a/openstackclient/identity/v3/project.py b/openstackclient/identity/v3/project.py index 073fb6df..9ecc70ef 100644 --- a/openstackclient/identity/v3/project.py +++ b/openstackclient/identity/v3/project.py @@ -22,7 +22,6 @@ from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common @@ -124,7 +123,7 @@ class CreateProject(command.ShowOne): raise project._info.pop('links') - return zip(*sorted(six.iteritems(project._info))) + return zip(*sorted(project._info.items())) class DeleteProject(command.Command): @@ -401,4 +400,4 @@ class ShowProject(command.ShowOne): subtree_as_ids=parsed_args.children) project._info.pop('links') - return zip(*sorted(six.iteritems(project._info))) + return zip(*sorted(project._info.items())) diff --git a/openstackclient/identity/v3/region.py b/openstackclient/identity/v3/region.py index 69c8b506..20ee073c 100644 --- a/openstackclient/identity/v3/region.py +++ b/openstackclient/identity/v3/region.py @@ -18,7 +18,6 @@ import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -62,7 +61,7 @@ class CreateRegion(command.ShowOne): region._info['region'] = region._info.pop('id') region._info['parent_region'] = region._info.pop('parent_region_id') region._info.pop('links', None) - return zip(*sorted(six.iteritems(region._info))) + return zip(*sorted(region._info.items())) class DeleteRegion(command.Command): @@ -181,4 +180,4 @@ class ShowRegion(command.ShowOne): region._info['region'] = region._info.pop('id') region._info['parent_region'] = region._info.pop('parent_region_id') region._info.pop('links', None) - return zip(*sorted(six.iteritems(region._info))) + return zip(*sorted(region._info.items())) diff --git a/openstackclient/identity/v3/registered_limit.py b/openstackclient/identity/v3/registered_limit.py index 9366ec1e..53117c71 100644 --- a/openstackclient/identity/v3/registered_limit.py +++ b/openstackclient/identity/v3/registered_limit.py @@ -18,7 +18,6 @@ import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common as common_utils @@ -92,7 +91,7 @@ class CreateRegisteredLimit(command.ShowOne): ) registered_limit._info.pop('links', None) - return zip(*sorted(six.iteritems(registered_limit._info))) + return zip(*sorted(registered_limit._info.items())) class DeleteRegisteredLimit(command.Command): @@ -275,7 +274,7 @@ class SetRegisteredLimit(command.ShowOne): ) registered_limit._info.pop('links', None) - return zip(*sorted(six.iteritems(registered_limit._info))) + return zip(*sorted(registered_limit._info.items())) class ShowRegisteredLimit(command.ShowOne): @@ -296,4 +295,4 @@ class ShowRegisteredLimit(command.ShowOne): parsed_args.registered_limit_id ) registered_limit._info.pop('links', None) - return zip(*sorted(six.iteritems(registered_limit._info))) + return zip(*sorted(registered_limit._info.items())) diff --git a/openstackclient/identity/v3/role.py b/openstackclient/identity/v3/role.py index 0eeddd37..36f3f938 100644 --- a/openstackclient/identity/v3/role.py +++ b/openstackclient/identity/v3/role.py @@ -21,7 +21,6 @@ from keystoneauth1 import exceptions as ks_exc from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common @@ -178,6 +177,11 @@ class CreateRole(command.ShowOne): help=_('New role name'), ) parser.add_argument( + '--description', + metavar='<description>', + help=_('Add description about the role'), + ) + parser.add_argument( '--domain', metavar='<domain>', help=_('Domain the role belongs to (name or ID)'), @@ -199,7 +203,8 @@ class CreateRole(command.ShowOne): try: role = identity_client.roles.create( - name=parsed_args.name, domain=domain_id) + name=parsed_args.name, domain=domain_id, + description=parsed_args.description) except ks_exc.Conflict: if parsed_args.or_show: @@ -211,7 +216,7 @@ class CreateRole(command.ShowOne): raise role._info.pop('links') - return zip(*sorted(six.iteritems(role._info))) + return zip(*sorted(role._info.items())) class DeleteRole(command.Command): @@ -347,6 +352,11 @@ class SetRole(command.Command): help=_('Role to modify (name or ID)'), ) parser.add_argument( + '--description', + metavar='<description>', + help=_('Add description about the role'), + ) + parser.add_argument( '--domain', metavar='<domain>', help=_('Domain the role belongs to (name or ID)'), @@ -370,7 +380,8 @@ class SetRole(command.Command): parsed_args.role, domain_id=domain_id) - identity_client.roles.update(role.id, name=parsed_args.name) + identity_client.roles.update(role.id, name=parsed_args.name, + description=parsed_args.description) class ShowRole(command.ShowOne): @@ -403,4 +414,4 @@ class ShowRole(command.ShowOne): domain_id=domain_id) role._info.pop('links') - return zip(*sorted(six.iteritems(role._info))) + return zip(*sorted(role._info.items())) diff --git a/openstackclient/identity/v3/service.py b/openstackclient/identity/v3/service.py index ac8d8d9e..9dc66962 100644 --- a/openstackclient/identity/v3/service.py +++ b/openstackclient/identity/v3/service.py @@ -20,7 +20,6 @@ import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common @@ -77,7 +76,7 @@ class CreateService(command.ShowOne): ) service._info.pop('links') - return zip(*sorted(six.iteritems(service._info))) + return zip(*sorted(service._info.items())) class DeleteService(command.Command): @@ -218,4 +217,4 @@ class ShowService(command.ShowOne): service = common.find_service(identity_client, parsed_args.service) service._info.pop('links') - return zip(*sorted(six.iteritems(service._info))) + return zip(*sorted(service._info.items())) diff --git a/openstackclient/identity/v3/service_provider.py b/openstackclient/identity/v3/service_provider.py index bb2d9917..e106c787 100644 --- a/openstackclient/identity/v3/service_provider.py +++ b/openstackclient/identity/v3/service_provider.py @@ -18,7 +18,6 @@ import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -83,7 +82,7 @@ class CreateServiceProvider(command.ShowOne): sp_url=parsed_args.service_provider_url) sp._info.pop('links', None) - return zip(*sorted(six.iteritems(sp._info))) + return zip(*sorted(sp._info.items())) class DeleteServiceProvider(command.Command): @@ -211,4 +210,4 @@ class ShowServiceProvider(command.ShowOne): id=parsed_args.service_provider) service_provider._info.pop('links', None) - return zip(*sorted(six.iteritems(service_provider._info))) + return zip(*sorted(service_provider._info.items())) diff --git a/openstackclient/identity/v3/token.py b/openstackclient/identity/v3/token.py index 1933ecad..f14dd8bc 100644 --- a/openstackclient/identity/v3/token.py +++ b/openstackclient/identity/v3/token.py @@ -18,7 +18,6 @@ from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common @@ -62,7 +61,7 @@ class AuthorizeRequestToken(command.ShowOne): parsed_args.request_key, roles) - return zip(*sorted(six.iteritems(verifier_pin._info))) + return zip(*sorted(verifier_pin._info.items())) class CreateAccessToken(command.ShowOne): @@ -108,7 +107,7 @@ class CreateAccessToken(command.ShowOne): parsed_args.consumer_key, parsed_args.consumer_secret, parsed_args.request_key, parsed_args.request_secret, parsed_args.verifier) - return zip(*sorted(six.iteritems(access_token._info))) + return zip(*sorted(access_token._info.items())) class CreateRequestToken(command.ShowOne): @@ -160,7 +159,7 @@ class CreateRequestToken(command.ShowOne): parsed_args.consumer_key, parsed_args.consumer_secret, project.id) - return zip(*sorted(six.iteritems(request_token._info))) + return zip(*sorted(request_token._info.items())) class IssueToken(command.ShowOne): @@ -198,7 +197,7 @@ class IssueToken(command.ShowOne): # deployment system. When that happens, this will have to relay # scope information and IDs like we do for projects and domains. data['system'] = 'all' - return zip(*sorted(six.iteritems(data))) + return zip(*sorted(data.items())) class RevokeToken(command.Command): diff --git a/openstackclient/identity/v3/trust.py b/openstackclient/identity/v3/trust.py index 155063bb..cd3a65d0 100644 --- a/openstackclient/identity/v3/trust.py +++ b/openstackclient/identity/v3/trust.py @@ -20,7 +20,6 @@ from keystoneclient import exceptions as identity_exc from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common @@ -136,7 +135,7 @@ class CreateTrust(command.ShowOne): msg = ' '.join(r['name'] for r in roles) trust._info['roles'] = msg - return zip(*sorted(six.iteritems(trust._info))) + return zip(*sorted(trust._info.items())) class DeleteTrust(command.Command): @@ -213,4 +212,4 @@ class ShowTrust(command.ShowOne): msg = ' '.join(r['name'] for r in roles) trust._info['roles'] = msg - return zip(*sorted(six.iteritems(trust._info))) + return zip(*sorted(trust._info.items())) diff --git a/openstackclient/identity/v3/user.py b/openstackclient/identity/v3/user.py index 5f4fb544..ca85c5d8 100644 --- a/openstackclient/identity/v3/user.py +++ b/openstackclient/identity/v3/user.py @@ -22,7 +22,6 @@ from keystoneauth1 import exceptions as ks_exc from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common @@ -135,7 +134,7 @@ class CreateUser(command.ShowOne): raise user._info.pop('links') - return zip(*sorted(six.iteritems(user._info))) + return zip(*sorted(user._info.items())) class DeleteUser(command.Command): @@ -486,4 +485,4 @@ class ShowUser(command.ShowOne): user_str) user._info.pop('links') - return zip(*sorted(six.iteritems(user._info))) + return zip(*sorted(user._info.items())) diff --git a/openstackclient/image/v1/image.py b/openstackclient/image/v1/image.py index c2dab3ee..a711a128 100644 --- a/openstackclient/image/v1/image.py +++ b/openstackclient/image/v1/image.py @@ -28,7 +28,6 @@ from osc_lib.cli import format_columns from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import utils -import six from openstackclient.i18n import _ @@ -271,7 +270,7 @@ class CreateImage(command.ShowOne): info.update(image._info) info['properties'] = format_columns.DictColumn( info.get('properties', {})) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) class DeleteImage(command.Command): @@ -718,4 +717,4 @@ class ShowImage(command.ShowOne): info['size'] = utils.format_size(info['size']) info['properties'] = format_columns.DictColumn( info.get('properties', {})) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) diff --git a/openstackclient/image/v2/image.py b/openstackclient/image/v2/image.py index 2b10c3ad..feeb2567 100644 --- a/openstackclient/image/v2/image.py +++ b/openstackclient/image/v2/image.py @@ -110,7 +110,7 @@ class AddProjectToImage(command.ShowOne): project_id, ) - return zip(*sorted(six.iteritems(image_member))) + return zip(*sorted(image_member.items())) class CreateImage(command.ShowOne): @@ -292,7 +292,7 @@ class CreateImage(command.ShowOne): # properties should get flattened into the general kwargs if getattr(parsed_args, 'properties', None): - for k, v in six.iteritems(parsed_args.properties): + for k, v in parsed_args.properties.items(): kwargs[k] = str(v) # Handle exclusive booleans with care @@ -417,7 +417,7 @@ class CreateImage(command.ShowOne): if not info: info = _format_image(image) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) class DeleteImage(command.Command): @@ -969,7 +969,7 @@ class SetImage(command.Command): # Properties should get flattened into the general kwargs if getattr(parsed_args, 'properties', None): - for k, v in six.iteritems(parsed_args.properties): + for k, v in parsed_args.properties.items(): kwargs[k] = str(v) # Handle exclusive booleans with care @@ -1066,7 +1066,7 @@ class ShowImage(command.ShowOne): image['size'] = utils.format_size(image['size']) info = _format_image(image) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(info.items())) class UnsetImage(command.Command): diff --git a/openstackclient/network/sdk_utils.py b/openstackclient/network/sdk_utils.py index 9f085617..af9c74f9 100644 --- a/openstackclient/network/sdk_utils.py +++ b/openstackclient/network/sdk_utils.py @@ -10,8 +10,6 @@ # License for the specific language governing permissions and limitations # under the License. -import six - def get_osc_show_columns_for_sdk_resource( sdk_resource, @@ -44,7 +42,7 @@ def get_osc_show_columns_for_sdk_resource( for col_name in invisible_columns: if col_name in display_columns: display_columns.remove(col_name) - for sdk_attr, osc_attr in six.iteritems(osc_column_map): + for sdk_attr, osc_attr in osc_column_map.items(): if sdk_attr in display_columns: attr_map[osc_attr] = sdk_attr display_columns.remove(sdk_attr) diff --git a/openstackclient/network/v2/_tag.py b/openstackclient/network/v2/_tag.py deleted file mode 100644 index e1cba22e..00000000 --- a/openstackclient/network/v2/_tag.py +++ /dev/null @@ -1,144 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -# - -import argparse - -from openstackclient.i18n import _ - - -class _CommaListAction(argparse.Action): - - def __call__(self, parser, namespace, values, option_string=None): - setattr(namespace, self.dest, values.split(',')) - - -def add_tag_filtering_option_to_parser(parser, collection_name, - enhance_help=lambda _h: _h): - parser.add_argument( - '--tags', - metavar='<tag>[,<tag>,...]', - action=_CommaListAction, - help=enhance_help( - _('List %s which have all given tag(s) (Comma-separated list of ' - 'tags)') % collection_name) - ) - parser.add_argument( - '--any-tags', - metavar='<tag>[,<tag>,...]', - action=_CommaListAction, - help=enhance_help( - _('List %s which have any given tag(s) (Comma-separated list of ' - 'tags)') % collection_name) - ) - parser.add_argument( - '--not-tags', - metavar='<tag>[,<tag>,...]', - action=_CommaListAction, - help=enhance_help( - _('Exclude %s which have all given tag(s) (Comma-separated list ' - 'of tags)') % collection_name) - ) - parser.add_argument( - '--not-any-tags', - metavar='<tag>[,<tag>,...]', - action=_CommaListAction, - help=enhance_help( - _('Exclude %s which have any given tag(s) (Comma-separated list ' - 'of tags)') % collection_name) - ) - - -def get_tag_filtering_args(parsed_args, args): - if parsed_args.tags: - args['tags'] = ','.join(parsed_args.tags) - if parsed_args.any_tags: - args['any_tags'] = ','.join(parsed_args.any_tags) - if parsed_args.not_tags: - args['not_tags'] = ','.join(parsed_args.not_tags) - if parsed_args.not_any_tags: - args['not_any_tags'] = ','.join(parsed_args.not_any_tags) - - -def add_tag_option_to_parser_for_create(parser, resource_name, - enhance_help=lambda _h: _h): - tag_group = parser.add_mutually_exclusive_group() - tag_group.add_argument( - '--tag', - action='append', - dest='tags', - metavar='<tag>', - help=enhance_help( - _("Tag to be added to the %s " - "(repeat option to set multiple tags)") % resource_name) - ) - tag_group.add_argument( - '--no-tag', - action='store_true', - help=enhance_help(_("No tags associated with the %s") % resource_name) - ) - - -def add_tag_option_to_parser_for_set(parser, resource_name, - enhance_help=lambda _h: _h): - parser.add_argument( - '--tag', - action='append', - dest='tags', - metavar='<tag>', - help=enhance_help( - _("Tag to be added to the %s (repeat option to set multiple " - "tags)") % resource_name) - ) - parser.add_argument( - '--no-tag', - action='store_true', - help=enhance_help( - _("Clear tags associated with the %s. Specify both --tag and " - "--no-tag to overwrite current tags") % resource_name) - ) - - -def update_tags_for_set(client, obj, parsed_args): - if parsed_args.no_tag: - tags = set() - else: - tags = set(obj.tags or []) - if parsed_args.tags: - tags |= set(parsed_args.tags) - if set(obj.tags or []) != tags: - client.set_tags(obj, list(tags)) - - -def add_tag_option_to_parser_for_unset(parser, resource_name): - tag_group = parser.add_mutually_exclusive_group() - tag_group.add_argument( - '--tag', - action='append', - dest='tags', - metavar='<tag>', - help=_("Tag to be removed from the %s " - "(repeat option to remove multiple tags)") % resource_name) - tag_group.add_argument( - '--all-tag', - action='store_true', - help=_("Clear all tags associated with the %s") % resource_name) - - -def update_tags_for_unset(client, obj, parsed_args): - tags = set(obj.tags) - if parsed_args.all_tag: - tags = set() - if parsed_args.tags: - tags -= set(parsed_args.tags) - if set(obj.tags) != tags: - client.set_tags(obj, list(tags)) diff --git a/openstackclient/network/v2/floating_ip.py b/openstackclient/network/v2/floating_ip.py index bd43379a..f3e3e5c4 100644 --- a/openstackclient/network/v2/floating_ip.py +++ b/openstackclient/network/v2/floating_ip.py @@ -16,12 +16,12 @@ from osc_lib.cli import format_columns from osc_lib.command import command from osc_lib import utils +from osc_lib.utils import tags as _tag from openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import common from openstackclient.network import sdk_utils -from openstackclient.network.v2 import _tag _formatters = { @@ -412,6 +412,11 @@ class SetFloatingIP(command.Command): help=_("Fixed IP of the port " "(required only if port has multiple IPs)") ) + parser.add_argument( + '--description', + metavar='<description>', + help=_('Set floating IP description') + ) qos_policy_group = parser.add_mutually_exclusive_group() qos_policy_group.add_argument( '--qos-policy', @@ -443,6 +448,9 @@ class SetFloatingIP(command.Command): if parsed_args.fixed_ip_address: attrs['fixed_ip_address'] = parsed_args.fixed_ip_address + if parsed_args.description: + attrs['description'] = parsed_args.description + if parsed_args.qos_policy: attrs['qos_policy_id'] = client.find_qos_policy( parsed_args.qos_policy, ignore_missing=False).id diff --git a/openstackclient/network/v2/network.py b/openstackclient/network/v2/network.py index e7031266..3f579b6d 100644 --- a/openstackclient/network/v2/network.py +++ b/openstackclient/network/v2/network.py @@ -16,13 +16,14 @@ from cliff import columns as cliff_columns from osc_lib.cli import format_columns from osc_lib.command import command +from osc_lib import exceptions from osc_lib import utils +from osc_lib.utils import tags as _tag from openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import common from openstackclient.network import sdk_utils -from openstackclient.network.v2 import _tag class AdminStateColumn(cliff_columns.FormattableColumn): @@ -125,6 +126,9 @@ def _get_attrs_network(client_manager, parsed_args): attrs['is_default'] = False if parsed_args.default: attrs['is_default'] = True + if attrs.get('is_default') and not attrs.get('router:external'): + msg = _("Cannot set default for internal network") + raise exceptions.CommandError(msg) # Update Provider network options if parsed_args.provider_network_type: attrs['provider:network_type'] = parsed_args.provider_network_type @@ -702,7 +706,8 @@ class SetNetwork(command.Command): default_router_grp.add_argument( '--default', action='store_true', - help=_("Set the network as the default external network") + help=_("Set the network as the default external network " + "(cannot be used with internal network).") ) default_router_grp.add_argument( '--no-default', diff --git a/openstackclient/network/v2/network_segment_range.py b/openstackclient/network/v2/network_segment_range.py index f03bcc1c..b38c72c2 100644 --- a/openstackclient/network/v2/network_segment_range.py +++ b/openstackclient/network/v2/network_segment_range.py @@ -23,7 +23,6 @@ from osc_lib.cli import format_columns from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common as identity_common @@ -42,7 +41,7 @@ def _get_columns(item): def _get_ranges(item): - item = [int(i) if isinstance(i, six.string_types) else i for i in item] + item = sorted([int(i) for i in item]) for a, b in itertools.groupby(enumerate(item), lambda xy: xy[1] - xy[0]): b = list(b) yield "%s-%s" % (b[0][1], b[-1][1]) if b[0][1] != b[-1][1] else \ @@ -61,7 +60,7 @@ def _is_prop_empty(columns, props, prop_name): def _exchange_dict_keys_with_values(orig_dict): updated_dict = dict() - for k, v in six.iteritems(orig_dict): + for k, v in orig_dict.items(): k = [k] if not updated_dict.get(v): updated_dict[v] = k @@ -80,7 +79,7 @@ def _update_available_from_props(columns, props): def _update_used_from_props(columns, props): index_used = columns.index('used') updated_used = _exchange_dict_keys_with_values(props[index_used]) - for k, v in six.iteritems(updated_used): + for k, v in updated_used.items(): updated_used[k] = list(_get_ranges(v)) props = _hack_tuple_value_update_by_index( props, index_used, updated_used) diff --git a/openstackclient/network/v2/port.py b/openstackclient/network/v2/port.py index 4d7e5189..a22bcafb 100644 --- a/openstackclient/network/v2/port.py +++ b/openstackclient/network/v2/port.py @@ -24,12 +24,12 @@ from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils +from osc_lib.utils import tags as _tag from openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import common from openstackclient.network import sdk_utils -from openstackclient.network.v2 import _tag LOG = logging.getLogger(__name__) diff --git a/openstackclient/network/v2/router.py b/openstackclient/network/v2/router.py index 02da50c3..464dbbec 100644 --- a/openstackclient/network/v2/router.py +++ b/openstackclient/network/v2/router.py @@ -23,11 +23,11 @@ from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils +from osc_lib.utils import tags as _tag from openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import sdk_utils -from openstackclient.network.v2 import _tag LOG = logging.getLogger(__name__) @@ -49,7 +49,7 @@ class RouterInfoColumn(cliff_columns.FormattableColumn): class RoutesColumn(cliff_columns.FormattableColumn): def human_readable(self): # Map the route keys to match --route option. - for route in self._value: + for route in self._value or []: if 'nexthop' in route: route['gateway'] = route.pop('nexthop') return utils.format_list_of_dicts(self._value) diff --git a/openstackclient/network/v2/security_group.py b/openstackclient/network/v2/security_group.py index 9f0ca0a1..2033af14 100644 --- a/openstackclient/network/v2/security_group.py +++ b/openstackclient/network/v2/security_group.py @@ -19,14 +19,13 @@ from cliff import columns as cliff_columns from osc_lib.cli import format_columns from osc_lib.command import command from osc_lib import utils -import six +from osc_lib.utils import tags as _tag from openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import common from openstackclient.network import sdk_utils from openstackclient.network import utils as network_utils -from openstackclient.network.v2 import _tag def _format_network_security_group_rules(sg_rules): @@ -34,7 +33,7 @@ def _format_network_security_group_rules(sg_rules): # rules, trim keys with caller known (e.g. security group and tenant ID) # or empty values. for sg_rule in sg_rules: - empty_keys = [k for k, v in six.iteritems(sg_rule) if not v] + empty_keys = [k for k, v in sg_rule.items() if not v] for key in empty_keys: sg_rule.pop(key) sg_rule.pop('security_group_id', None) @@ -203,6 +202,7 @@ class DeleteSecurityGroup(common.NetworkAndComputeDelete): # the OSC minimum requirements include SDK 1.0. class ListSecurityGroup(common.NetworkAndComputeLister): _description = _("List security groups") + FIELDS_TO_RETRIEVE = ['id', 'name', 'description', 'project_id', 'tags'] def update_parser_network(self, parser): if not self.is_docs_build: @@ -252,7 +252,8 @@ class ListSecurityGroup(common.NetworkAndComputeLister): filters['project_id'] = project_id _tag.get_tag_filtering_args(parsed_args, filters) - data = client.security_groups(**filters) + data = client.security_groups(fields=self.FIELDS_TO_RETRIEVE, + **filters) columns = ( "ID", diff --git a/openstackclient/network/v2/security_group_rule.py b/openstackclient/network/v2/security_group_rule.py index a38587fa..f48478ea 100644 --- a/openstackclient/network/v2/security_group_rule.py +++ b/openstackclient/network/v2/security_group_rule.py @@ -20,7 +20,6 @@ from osc_lib.cli import format_columns from osc_lib.cli import parseractions from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common as identity_common @@ -39,7 +38,7 @@ _formatters = { def _format_security_group_rule_show(obj): data = network_utils.transform_compute_security_group_rule(obj) - return zip(*sorted(six.iteritems(data))) + return zip(*sorted(data.items())) def _format_network_port_range(rule): diff --git a/openstackclient/network/v2/subnet.py b/openstackclient/network/v2/subnet.py index c5368861..f6844065 100644 --- a/openstackclient/network/v2/subnet.py +++ b/openstackclient/network/v2/subnet.py @@ -22,11 +22,11 @@ from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils +from osc_lib.utils import tags as _tag from openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import sdk_utils -from openstackclient.network.v2 import _tag LOG = logging.getLogger(__name__) @@ -230,6 +230,10 @@ def _get_attrs(client_manager, parsed_args, is_create=True): attrs['enable_dhcp'] = True if parsed_args.no_dhcp: attrs['enable_dhcp'] = False + if parsed_args.dns_publish_fixed_ip: + attrs['dns_publish_fixed_ip'] = True + if parsed_args.no_dns_publish_fixed_ip: + attrs['dns_publish_fixed_ip'] = False if ('dns_nameservers' in parsed_args and parsed_args.dns_nameservers is not None): attrs['dns_nameservers'] = parsed_args.dns_nameservers @@ -303,6 +307,17 @@ class CreateSubnet(command.ShowOne): action='store_true', help=_("Disable DHCP") ) + dns_publish_fixed_ip_group = parser.add_mutually_exclusive_group() + dns_publish_fixed_ip_group.add_argument( + '--dns-publish-fixed-ip', + action='store_true', + help=_("Enable publishing fixed IPs in DNS") + ) + dns_publish_fixed_ip_group.add_argument( + '--no-dns-publish-fixed-ip', + action='store_true', + help=_("Disable publishing fixed IPs in DNS (default)") + ) parser.add_argument( '--gateway', metavar='<gateway>', @@ -558,6 +573,17 @@ class SetSubnet(command.Command): action='store_true', help=_("Disable DHCP") ) + dns_publish_fixed_ip_group = parser.add_mutually_exclusive_group() + dns_publish_fixed_ip_group.add_argument( + '--dns-publish-fixed-ip', + action='store_true', + help=_("Enable publishing fixed IPs in DNS") + ) + dns_publish_fixed_ip_group.add_argument( + '--no-dns-publish-fixed-ip', + action='store_true', + help=_("Disable publishing fixed IPs in DNS") + ) parser.add_argument( '--gateway', metavar='<gateway>', diff --git a/openstackclient/network/v2/subnet_pool.py b/openstackclient/network/v2/subnet_pool.py index d5a15475..2750574a 100644 --- a/openstackclient/network/v2/subnet_pool.py +++ b/openstackclient/network/v2/subnet_pool.py @@ -20,11 +20,11 @@ from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils +from osc_lib.utils import tags as _tag from openstackclient.i18n import _ from openstackclient.identity import common as identity_common from openstackclient.network import sdk_utils -from openstackclient.network.v2 import _tag LOG = logging.getLogger(__name__) diff --git a/openstackclient/object/v1/account.py b/openstackclient/object/v1/account.py index 95be8132..d6bc9fd7 100644 --- a/openstackclient/object/v1/account.py +++ b/openstackclient/object/v1/account.py @@ -16,7 +16,6 @@ from osc_lib.cli import format_columns from osc_lib.cli import parseractions from osc_lib.command import command -import six from openstackclient.i18n import _ @@ -50,7 +49,7 @@ class ShowAccount(command.ShowOne): if 'properties' in data: data['properties'] = format_columns.DictColumn( data.pop('properties')) - return zip(*sorted(six.iteritems(data))) + return zip(*sorted(data.items())) class UnsetAccount(command.Command): diff --git a/openstackclient/object/v1/container.py b/openstackclient/object/v1/container.py index 02e8d277..917e41c0 100644 --- a/openstackclient/object/v1/container.py +++ b/openstackclient/object/v1/container.py @@ -21,7 +21,6 @@ from osc_lib.cli import format_columns from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import utils -import six from openstackclient.i18n import _ @@ -35,6 +34,16 @@ class CreateContainer(command.Lister): def get_parser(self, prog_name): parser = super(CreateContainer, self).get_parser(prog_name) parser.add_argument( + '--public', + action='store_true', + default=False, + help="Make the container publicly accessible" + ) + parser.add_argument( + '--storage-policy', + help="Specify a particular storage policy to use." + ) + parser.add_argument( 'containers', metavar='<container-name>', nargs="+", @@ -52,6 +61,8 @@ class CreateContainer(command.Lister): ' is 256'), len(container)) data = self.app.client_manager.object_store.container_create( container=container, + public=parsed_args.public, + storage_policy=parsed_args.storage_policy ) results.append(data) @@ -233,7 +244,7 @@ class ShowContainer(command.ShowOne): if 'properties' in data: data['properties'] = format_columns.DictColumn(data['properties']) - return zip(*sorted(six.iteritems(data))) + return zip(*sorted(data.items())) class UnsetContainer(command.Command): diff --git a/openstackclient/object/v1/object.py b/openstackclient/object/v1/object.py index 3747e19e..01e537ee 100644 --- a/openstackclient/object/v1/object.py +++ b/openstackclient/object/v1/object.py @@ -22,7 +22,6 @@ from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -287,7 +286,7 @@ class ShowObject(command.ShowOne): if 'properties' in data: data['properties'] = format_columns.DictColumn(data['properties']) - return zip(*sorted(six.iteritems(data))) + return zip(*sorted(data.items())) class UnsetObject(command.Command): diff --git a/openstackclient/shell.py b/openstackclient/shell.py index 7fbda1ae..755af24d 100644 --- a/openstackclient/shell.py +++ b/openstackclient/shell.py @@ -139,32 +139,6 @@ class OpenStackShell(shell.OpenStackShell): pw_func=shell.prompt_for_password, ) - def prepare_to_run_command(self, cmd): - """Set up auth and API versions""" - - # TODO(dtroyer): Move this to osc-lib, remove entire method when 1.4.0 - # release is minimum version is in global-requirements - # NOTE(dtroyer): If auth is not required for a command, skip - # get_one_Cloud()'s validation to avoid loading plugins - validate = cmd.auth_required - - # Force skipping auth for commands that do not need it - # NOTE(dtroyer): This is here because ClientManager does not have - # visibility into the Command object to get - # auth_required. It needs to move into osc-lib - self.client_manager._auth_required = cmd.auth_required - - # Validate auth options - self.cloud = self.cloud_config.get_one_cloud( - cloud=self.options.cloud, - argparse=self.options, - validate=validate, - ) - # Push the updated args into ClientManager - self.client_manager._cli_options = self.cloud - - return super(OpenStackShell, self).prepare_to_run_command(cmd) - def main(argv=None): if argv is None: diff --git a/openstackclient/tests/functional/compute/v2/test_server.py b/openstackclient/tests/functional/compute/v2/test_server.py index 2bca70d0..6e080e9b 100644 --- a/openstackclient/tests/functional/compute/v2/test_server.py +++ b/openstackclient/tests/functional/compute/v2/test_server.py @@ -63,6 +63,49 @@ class ServerTests(common.ComputeTestCase): self.assertNotIn(name1, col_name) self.assertIn(name2, col_name) + def test_server_list_with_marker_and_deleted(self): + """Test server list with deleted and marker""" + cmd_output = self.server_create(cleanup=False) + name1 = cmd_output['name'] + cmd_output = self.server_create(cleanup=False) + name2 = cmd_output['name'] + id2 = cmd_output['id'] + self.wait_for_status(name1, "ACTIVE") + self.wait_for_status(name2, "ACTIVE") + + # Test list --marker with ID + cmd_output = json.loads(self.openstack( + 'server list -f json --marker ' + id2 + )) + col_name = [x["Name"] for x in cmd_output] + self.assertIn(name1, col_name) + + # Test list --marker with Name + cmd_output = json.loads(self.openstack( + 'server list -f json --marker ' + name2 + )) + col_name = [x["Name"] for x in cmd_output] + self.assertIn(name1, col_name) + + self.openstack('server delete --wait ' + name1) + self.openstack('server delete --wait ' + name2) + + # Test list --deleted --marker with ID + cmd_output = json.loads(self.openstack( + 'server list -f json --deleted --marker ' + id2 + )) + col_name = [x["Name"] for x in cmd_output] + self.assertIn(name1, col_name) + + # Test list --deleted --marker with Name + try: + cmd_output = json.loads(self.openstack( + 'server list -f json --deleted --marker ' + name2 + )) + except exceptions.CommandFailed as e: + self.assertIn('marker [%s] not found (HTTP 400)' % (name2), + e.stderr.decode('utf-8')) + def test_server_list_with_changes_before(self): """Test server list. diff --git a/openstackclient/tests/functional/identity/v3/common.py b/openstackclient/tests/functional/identity/v3/common.py index 86f090bc..a5edd9a5 100644 --- a/openstackclient/tests/functional/identity/v3/common.py +++ b/openstackclient/tests/functional/identity/v3/common.py @@ -33,7 +33,7 @@ class IdentityTests(base.TestCase): 'password_expires_at'] PROJECT_FIELDS = ['description', 'id', 'domain_id', 'is_domain', 'enabled', 'name', 'parent_id'] - ROLE_FIELDS = ['id', 'name', 'domain_id'] + ROLE_FIELDS = ['id', 'name', 'domain_id', 'description'] SERVICE_FIELDS = ['id', 'enabled', 'name', 'type', 'description'] REGION_FIELDS = ['description', 'enabled', 'parent_region', 'region'] ENDPOINT_FIELDS = ['id', 'region', 'region_id', 'service_id', diff --git a/openstackclient/tests/functional/identity/v3/test_role.py b/openstackclient/tests/functional/identity/v3/test_role.py index 38bfff71..3954c4e3 100644 --- a/openstackclient/tests/functional/identity/v3/test_role.py +++ b/openstackclient/tests/functional/identity/v3/test_role.py @@ -20,6 +20,21 @@ class RoleTests(common.IdentityTests): def test_role_create(self): self._create_dummy_role() + def test_role_create_with_description(self): + role_name = data_utils.rand_name('TestRole') + description = data_utils.rand_name('description') + raw_output = self.openstack( + 'role create ' + '--description %(description)s ' + '%(name)s' % {'description': description, + 'name': role_name}) + role = self.parse_show_as_object(raw_output) + self.addCleanup(self.openstack, 'role delete %s' % role['id']) + items = self.parse_show(raw_output) + self.assert_show_fields(items, self.ROLE_FIELDS) + self.assertEqual(description, role['description']) + return role_name + def test_role_delete(self): role_name = self._create_dummy_role(add_clean_up=False) raw_output = self.openstack('role delete %s' % role_name) @@ -47,6 +62,16 @@ class RoleTests(common.IdentityTests): role = self.parse_show_as_object(raw_output) self.assertEqual(new_role_name, role['name']) + def test_role_set_description(self): + role_name = self._create_dummy_role() + description = data_utils.rand_name("NewDescription") + raw_output = self.openstack('role set --description %s %s' + % (description, role_name)) + self.assertEqual(0, len(raw_output)) + raw_output = self.openstack('role show %s' % role_name) + role = self.parse_show_as_object(raw_output) + self.assertEqual(description, role['description']) + def test_role_add(self): role_name = self._create_dummy_role() username = self._create_dummy_user() diff --git a/openstackclient/tests/functional/volume/v3/test_qos.py b/openstackclient/tests/functional/volume/v3/test_qos.py index a6290fc5..fdfa6827 100644 --- a/openstackclient/tests/functional/volume/v3/test_qos.py +++ b/openstackclient/tests/functional/volume/v3/test_qos.py @@ -10,9 +10,209 @@ # License for the specific language governing permissions and limitations # under the License. -from openstackclient.tests.functional.volume.v2 import test_qos as v2 +import json +import uuid + from openstackclient.tests.functional.volume.v3 import common -class QosTests(common.BaseVolumeTests, v2.QosTests): +class QosTests(common.BaseVolumeTests): """Functional tests for volume qos. """ + + def test_volume_qos_create_delete_list(self): + """Test create, list, delete multiple""" + name1 = uuid.uuid4().hex + cmd_output = json.loads(self.openstack( + 'volume qos create -f json ' + + name1 + )) + self.assertEqual( + name1, + cmd_output['name'] + ) + + name2 = uuid.uuid4().hex + cmd_output = json.loads(self.openstack( + 'volume qos create -f json ' + + name2 + )) + self.assertEqual( + name2, + cmd_output['name'] + ) + + # Test list + cmd_output = json.loads(self.openstack( + 'volume qos list -f json' + )) + names = [x["Name"] for x in cmd_output] + self.assertIn(name1, names) + self.assertIn(name2, names) + + # Test delete multiple + del_output = self.openstack('volume qos delete ' + name1 + ' ' + name2) + self.assertOutput('', del_output) + + def test_volume_qos_set_show_unset(self): + """Tests create volume qos, set, unset, show, delete""" + + name = uuid.uuid4().hex + cmd_output = json.loads(self.openstack( + 'volume qos create -f json ' + + '--consumer front-end ' + '--property Alpha=a ' + + name + )) + self.addCleanup(self.openstack, 'volume qos delete ' + name) + self.assertEqual( + name, + cmd_output['name'] + ) + + self.assertEqual( + "front-end", + cmd_output['consumer'] + ) + self.assertEqual( + {'Alpha': 'a'}, + cmd_output['properties'] + ) + + # Test volume qos set + raw_output = self.openstack( + 'volume qos set ' + + '--property Alpha=c ' + + '--property Beta=b ' + + name, + ) + self.assertOutput('', raw_output) + + # Test volume qos show + cmd_output = json.loads(self.openstack( + 'volume qos show -f json ' + + name + )) + self.assertEqual( + name, + cmd_output['name'] + ) + self.assertEqual( + {'Alpha': 'c', 'Beta': 'b'}, + cmd_output['properties'] + ) + + # Test volume qos unset + raw_output = self.openstack( + 'volume qos unset ' + + '--property Alpha ' + + name, + ) + self.assertOutput('', raw_output) + + cmd_output = json.loads(self.openstack( + 'volume qos show -f json ' + + name + )) + self.assertEqual( + name, + cmd_output['name'] + ) + self.assertEqual( + {'Beta': 'b'}, + cmd_output['properties'] + ) + + def test_volume_qos_asso_disasso(self): + """Tests associate and disassociate qos with volume type""" + vol_type1 = uuid.uuid4().hex + cmd_output = json.loads(self.openstack( + 'volume type create -f json ' + + vol_type1 + )) + self.assertEqual( + vol_type1, + cmd_output['name'] + ) + self.addCleanup(self.openstack, 'volume type delete ' + vol_type1) + + vol_type2 = uuid.uuid4().hex + cmd_output = json.loads(self.openstack( + 'volume type create -f json ' + + vol_type2 + )) + self.assertEqual( + vol_type2, + cmd_output['name'] + ) + self.addCleanup(self.openstack, 'volume type delete ' + vol_type2) + + name = uuid.uuid4().hex + cmd_output = json.loads(self.openstack( + 'volume qos create -f json ' + + name + )) + self.assertEqual( + name, + cmd_output['name'] + ) + self.addCleanup(self.openstack, 'volume qos delete ' + name) + + # Test associate + raw_output = self.openstack( + 'volume qos associate ' + + name + ' ' + vol_type1 + ) + self.assertOutput('', raw_output) + raw_output = self.openstack( + 'volume qos associate ' + + name + ' ' + vol_type2 + ) + self.assertOutput('', raw_output) + + cmd_output = json.loads(self.openstack( + 'volume qos show -f json ' + + name + )) + types = cmd_output["associations"] + self.assertIn(vol_type1, types) + self.assertIn(vol_type2, types) + + # Test disassociate + raw_output = self.openstack( + 'volume qos disassociate ' + + '--volume-type ' + vol_type1 + + ' ' + name + ) + self.assertOutput('', raw_output) + cmd_output = json.loads(self.openstack( + 'volume qos show -f json ' + + name + )) + types = cmd_output["associations"] + self.assertNotIn(vol_type1, types) + self.assertIn(vol_type2, types) + + # Test disassociate --all + raw_output = self.openstack( + 'volume qos associate ' + + name + ' ' + vol_type1 + ) + self.assertOutput('', raw_output) + cmd_output = json.loads(self.openstack( + 'volume qos show -f json ' + + name + )) + types = cmd_output["associations"] + self.assertIn(vol_type1, types) + self.assertIn(vol_type2, types) + + raw_output = self.openstack( + 'volume qos disassociate ' + + '--all ' + name + ) + self.assertOutput('', raw_output) + cmd_output = json.loads(self.openstack( + 'volume qos show -f json ' + + name + )) + self.assertNotIn("associations", cmd_output.keys()) diff --git a/openstackclient/tests/functional/volume/v3/test_transfer_request.py b/openstackclient/tests/functional/volume/v3/test_transfer_request.py index f16dfafa..1bbfedc9 100644 --- a/openstackclient/tests/functional/volume/v3/test_transfer_request.py +++ b/openstackclient/tests/functional/volume/v3/test_transfer_request.py @@ -10,12 +10,112 @@ # License for the specific language governing permissions and limitations # under the License. -from openstackclient.tests.functional.volume.v2 import test_transfer_request \ - as v2 +import json +import uuid + from openstackclient.tests.functional.volume.v3 import common -class TransferRequestTests(common.BaseVolumeTests, v2.TransferRequestTests): +class TransferRequestTests(common.BaseVolumeTests): """Functional tests for transfer request. """ API_VERSION = '3' + + def test_volume_transfer_request_accept(self): + volume_name = uuid.uuid4().hex + xfer_name = uuid.uuid4().hex + + # create a volume + cmd_output = json.loads(self.openstack( + 'volume create -f json ' + + '--size 1 ' + + volume_name + )) + self.assertEqual(volume_name, cmd_output['name']) + self.addCleanup( + self.openstack, + '--os-volume-api-version ' + self.API_VERSION + ' ' + + 'volume delete ' + + volume_name + ) + self.wait_for_status("volume", volume_name, "available") + + # create volume transfer request for the volume + # and get the auth_key of the new transfer request + cmd_output = json.loads(self.openstack( + '--os-volume-api-version ' + self.API_VERSION + ' ' + + 'volume transfer request create -f json ' + + ' --name ' + xfer_name + ' ' + + volume_name + )) + self.assertEqual(xfer_name, cmd_output['name']) + xfer_id = cmd_output['id'] + auth_key = cmd_output['auth_key'] + self.assertTrue(auth_key) + self.wait_for_status("volume", volume_name, "awaiting-transfer") + + # accept the volume transfer request + cmd_output = json.loads(self.openstack( + '--os-volume-api-version ' + self.API_VERSION + ' ' + + 'volume transfer request accept -f json ' + + '--auth-key ' + auth_key + ' ' + + xfer_id + )) + self.assertEqual(xfer_name, cmd_output['name']) + self.wait_for_status("volume", volume_name, "available") + + def test_volume_transfer_request_list_show(self): + volume_name = uuid.uuid4().hex + xfer_name = uuid.uuid4().hex + + # create a volume + cmd_output = json.loads(self.openstack( + 'volume create -f json ' + + '--size 1 ' + + volume_name + )) + self.assertEqual(volume_name, cmd_output['name']) + self.addCleanup( + self.openstack, + '--os-volume-api-version ' + self.API_VERSION + ' ' + + 'volume delete ' + + volume_name + ) + self.wait_for_status("volume", volume_name, "available") + + cmd_output = json.loads(self.openstack( + '--os-volume-api-version ' + self.API_VERSION + ' ' + + 'volume transfer request create -f json ' + + ' --name ' + xfer_name + ' ' + + volume_name + )) + self.assertEqual(xfer_name, cmd_output['name']) + xfer_id = cmd_output['id'] + auth_key = cmd_output['auth_key'] + self.assertTrue(auth_key) + self.wait_for_status("volume", volume_name, "awaiting-transfer") + + cmd_output = json.loads(self.openstack( + '--os-volume-api-version ' + self.API_VERSION + ' ' + + 'volume transfer request list -f json' + )) + self.assertIn(xfer_name, [req['Name'] for req in cmd_output]) + + cmd_output = json.loads(self.openstack( + '--os-volume-api-version ' + self.API_VERSION + ' ' + + 'volume transfer request show -f json ' + + xfer_id + )) + self.assertEqual(xfer_name, cmd_output['name']) + + # NOTE(dtroyer): We need to delete the transfer request to allow the + # volume to be deleted. The addCleanup() route does + # not have a mechanism to wait for the volume status + # to become 'available' before attempting to delete + # the volume. + cmd_output = self.openstack( + '--os-volume-api-version ' + self.API_VERSION + ' ' + + 'volume transfer request delete ' + + xfer_id + ) + self.wait_for_status("volume", volume_name, "available") diff --git a/openstackclient/tests/functional/volume/v3/test_volume.py b/openstackclient/tests/functional/volume/v3/test_volume.py index 283b830f..6635167d 100644 --- a/openstackclient/tests/functional/volume/v3/test_volume.py +++ b/openstackclient/tests/functional/volume/v3/test_volume.py @@ -10,9 +10,273 @@ # License for the specific language governing permissions and limitations # under the License. -from openstackclient.tests.functional.volume.v2 import test_volume as v2 +import json +import uuid + from openstackclient.tests.functional.volume.v3 import common -class VolumeTests(common.BaseVolumeTests, v2.VolumeTests): +class VolumeTests(common.BaseVolumeTests): """Functional tests for volume. """ + + def test_volume_delete(self): + """Test create, delete multiple""" + name1 = uuid.uuid4().hex + cmd_output = json.loads(self.openstack( + 'volume create -f json ' + + '--size 1 ' + + name1 + )) + self.assertEqual( + 1, + cmd_output["size"], + ) + + name2 = uuid.uuid4().hex + cmd_output = json.loads(self.openstack( + 'volume create -f json ' + + '--size 2 ' + + name2 + )) + self.assertEqual( + 2, + cmd_output["size"], + ) + + self.wait_for_status("volume", name1, "available") + self.wait_for_status("volume", name2, "available") + del_output = self.openstack('volume delete ' + name1 + ' ' + name2) + self.assertOutput('', del_output) + + def test_volume_list(self): + """Test create, list filter""" + name1 = uuid.uuid4().hex + cmd_output = json.loads(self.openstack( + 'volume create -f json ' + + '--size 1 ' + + name1 + )) + self.addCleanup(self.openstack, 'volume delete ' + name1) + self.assertEqual( + 1, + cmd_output["size"], + ) + self.wait_for_status("volume", name1, "available") + + name2 = uuid.uuid4().hex + cmd_output = json.loads(self.openstack( + 'volume create -f json ' + + '--size 2 ' + + name2 + )) + self.addCleanup(self.openstack, 'volume delete ' + name2) + self.assertEqual( + 2, + cmd_output["size"], + ) + self.wait_for_status("volume", name2, "available") + raw_output = self.openstack( + 'volume set ' + + '--state error ' + + name2 + ) + self.assertOutput('', raw_output) + + # Test list --long + cmd_output = json.loads(self.openstack( + 'volume list -f json ' + + '--long' + )) + names = [x["Name"] for x in cmd_output] + self.assertIn(name1, names) + self.assertIn(name2, names) + + # Test list --status + cmd_output = json.loads(self.openstack( + 'volume list -f json ' + + '--status error' + )) + names = [x["Name"] for x in cmd_output] + self.assertNotIn(name1, names) + self.assertIn(name2, names) + + # TODO(qiangjiahui): Add project option to filter tests when we can + # specify volume with project + + def test_volume_set_and_unset(self): + """Tests create volume, set, unset, show, delete""" + name = uuid.uuid4().hex + new_name = name + "_" + cmd_output = json.loads(self.openstack( + 'volume create -f json ' + + '--size 1 ' + + '--description aaaa ' + + '--property Alpha=a ' + + name + )) + self.addCleanup(self.openstack, 'volume delete ' + new_name) + self.assertEqual( + name, + cmd_output["name"], + ) + self.assertEqual( + 1, + cmd_output["size"], + ) + self.assertEqual( + 'aaaa', + cmd_output["description"], + ) + self.assertEqual( + {'Alpha': 'a'}, + cmd_output["properties"], + ) + self.assertEqual( + 'false', + cmd_output["bootable"], + ) + self.wait_for_status("volume", name, "available") + + # Test volume set + raw_output = self.openstack( + 'volume set ' + + '--name ' + new_name + + ' --size 2 ' + + '--description bbbb ' + + '--no-property ' + + '--property Beta=b ' + + '--property Gamma=c ' + + '--image-property a=b ' + + '--image-property c=d ' + + '--bootable ' + + name, + ) + self.assertOutput('', raw_output) + + cmd_output = json.loads(self.openstack( + 'volume show -f json ' + + new_name + )) + self.assertEqual( + new_name, + cmd_output["name"], + ) + self.assertEqual( + 2, + cmd_output["size"], + ) + self.assertEqual( + 'bbbb', + cmd_output["description"], + ) + self.assertEqual( + {'Beta': 'b', 'Gamma': 'c'}, + cmd_output["properties"], + ) + self.assertEqual( + {'a': 'b', 'c': 'd'}, + cmd_output["volume_image_metadata"], + ) + self.assertEqual( + 'true', + cmd_output["bootable"], + ) + + # Test volume unset + raw_output = self.openstack( + 'volume unset ' + + '--property Beta ' + + '--image-property a ' + + new_name, + ) + self.assertOutput('', raw_output) + + cmd_output = json.loads(self.openstack( + 'volume show -f json ' + + new_name + )) + self.assertEqual( + {'Gamma': 'c'}, + cmd_output["properties"], + ) + self.assertEqual( + {'c': 'd'}, + cmd_output["volume_image_metadata"], + ) + + def test_volume_snapshot(self): + """Tests volume create from snapshot""" + + volume_name = uuid.uuid4().hex + snapshot_name = uuid.uuid4().hex + # Make a snapshot + cmd_output = json.loads(self.openstack( + 'volume create -f json ' + + '--size 1 ' + + volume_name + )) + self.wait_for_status("volume", volume_name, "available") + self.assertEqual( + volume_name, + cmd_output["name"], + ) + cmd_output = json.loads(self.openstack( + 'volume snapshot create -f json ' + + snapshot_name + + ' --volume ' + volume_name + )) + self.wait_for_status("volume snapshot", snapshot_name, "available") + + name = uuid.uuid4().hex + # Create volume from snapshot + cmd_output = json.loads(self.openstack( + 'volume create -f json ' + + '--snapshot ' + snapshot_name + + ' ' + name + )) + self.addCleanup(self.openstack, 'volume delete ' + name) + self.addCleanup(self.openstack, 'volume delete ' + volume_name) + self.assertEqual( + name, + cmd_output["name"], + ) + self.wait_for_status("volume", name, "available") + + # Delete snapshot + raw_output = self.openstack( + 'volume snapshot delete ' + snapshot_name) + self.assertOutput('', raw_output) + # Deleting snapshot may take time. If volume snapshot still exists when + # a parent volume delete is requested, the volume deletion will fail. + self.wait_for_delete('volume snapshot', snapshot_name) + + def test_volume_list_backward_compatibility(self): + """Test backward compatibility of list command""" + name1 = uuid.uuid4().hex + cmd_output = json.loads(self.openstack( + 'volume create -f json ' + + '--size 1 ' + + name1 + )) + self.addCleanup(self.openstack, 'volume delete ' + name1) + self.assertEqual( + 1, + cmd_output["size"], + ) + self.wait_for_status("volume", name1, "available") + + # Test list -c "Display Name" + cmd_output = json.loads(self.openstack( + 'volume list -f json ' + + '-c "Display Name"' + )) + for each_volume in cmd_output: + self.assertIn('Display Name', each_volume) + + # Test list -c "Name" + cmd_output = json.loads(self.openstack( + 'volume list -f json ' + + '-c "Name"' + )) + for each_volume in cmd_output: + self.assertIn('Name', each_volume) diff --git a/openstackclient/tests/functional/volume/v3/test_volume_snapshot.py b/openstackclient/tests/functional/volume/v3/test_volume_snapshot.py index 28eee6d2..edfdafb6 100644 --- a/openstackclient/tests/functional/volume/v3/test_volume_snapshot.py +++ b/openstackclient/tests/functional/volume/v3/test_volume_snapshot.py @@ -10,9 +10,245 @@ # License for the specific language governing permissions and limitations # under the License. -from openstackclient.tests.functional.volume.v2 import test_volume_snapshot as v2 # noqa +import json +import uuid + from openstackclient.tests.functional.volume.v3 import common -class VolumeSnapshotTests(common.BaseVolumeTests, v2.VolumeSnapshotTests): +class VolumeSnapshotTests(common.BaseVolumeTests): """Functional tests for volume snapshot. """ + + VOLLY = uuid.uuid4().hex + + @classmethod + def setUpClass(cls): + super(VolumeSnapshotTests, cls).setUpClass() + # create a volume for all tests to create snapshot + cmd_output = json.loads(cls.openstack( + 'volume create -f json ' + + '--size 1 ' + + cls.VOLLY + )) + cls.wait_for_status('volume', cls.VOLLY, 'available') + cls.VOLUME_ID = cmd_output['id'] + + @classmethod + def tearDownClass(cls): + try: + cls.wait_for_status('volume', cls.VOLLY, 'available') + raw_output = cls.openstack( + 'volume delete --force ' + cls.VOLLY) + cls.assertOutput('', raw_output) + finally: + super(VolumeSnapshotTests, cls).tearDownClass() + + def test_volume_snapshot_delete(self): + """Test create, delete multiple""" + name1 = uuid.uuid4().hex + cmd_output = json.loads(self.openstack( + 'volume snapshot create -f json ' + + name1 + + ' --volume ' + self.VOLLY + )) + self.assertEqual( + name1, + cmd_output["name"], + ) + + name2 = uuid.uuid4().hex + cmd_output = json.loads(self.openstack( + 'volume snapshot create -f json ' + + name2 + + ' --volume ' + self.VOLLY + )) + self.assertEqual( + name2, + cmd_output["name"], + ) + + self.wait_for_status('volume snapshot', name1, 'available') + self.wait_for_status('volume snapshot', name2, 'available') + + del_output = self.openstack( + 'volume snapshot delete ' + name1 + ' ' + name2) + self.assertOutput('', del_output) + self.wait_for_delete('volume snapshot', name1) + self.wait_for_delete('volume snapshot', name2) + + def test_volume_snapshot_list(self): + """Test create, list filter""" + name1 = uuid.uuid4().hex + cmd_output = json.loads(self.openstack( + 'volume snapshot create -f json ' + + name1 + + ' --volume ' + self.VOLLY + )) + self.addCleanup(self.wait_for_delete, 'volume snapshot', name1) + self.addCleanup(self.openstack, 'volume snapshot delete ' + name1) + self.assertEqual( + name1, + cmd_output["name"], + ) + self.assertEqual( + self.VOLUME_ID, + cmd_output["volume_id"], + ) + self.assertEqual( + 1, + cmd_output["size"], + ) + self.wait_for_status('volume snapshot', name1, 'available') + + name2 = uuid.uuid4().hex + cmd_output = json.loads(self.openstack( + 'volume snapshot create -f json ' + + name2 + + ' --volume ' + self.VOLLY + )) + self.addCleanup(self.wait_for_delete, 'volume snapshot', name2) + self.addCleanup(self.openstack, 'volume snapshot delete ' + name2) + self.assertEqual( + name2, + cmd_output["name"], + ) + self.assertEqual( + self.VOLUME_ID, + cmd_output["volume_id"], + ) + self.assertEqual( + 1, + cmd_output["size"], + ) + self.wait_for_status('volume snapshot', name2, 'available') + raw_output = self.openstack( + 'volume snapshot set ' + + '--state error ' + + name2 + ) + self.assertOutput('', raw_output) + + # Test list --long, --status + cmd_output = json.loads(self.openstack( + 'volume snapshot list -f json ' + + '--long ' + + '--status error' + )) + names = [x["Name"] for x in cmd_output] + self.assertNotIn(name1, names) + self.assertIn(name2, names) + + # Test list --volume + cmd_output = json.loads(self.openstack( + 'volume snapshot list -f json ' + + '--volume ' + self.VOLLY + )) + names = [x["Name"] for x in cmd_output] + self.assertIn(name1, names) + self.assertIn(name2, names) + + # Test list --name + cmd_output = json.loads(self.openstack( + 'volume snapshot list -f json ' + + '--name ' + name1 + )) + names = [x["Name"] for x in cmd_output] + self.assertIn(name1, names) + self.assertNotIn(name2, names) + + def test_volume_snapshot_set(self): + """Test create, set, unset, show, delete volume snapshot""" + name = uuid.uuid4().hex + new_name = name + "_" + cmd_output = json.loads(self.openstack( + 'volume snapshot create -f json ' + + '--volume ' + self.VOLLY + + ' --description aaaa ' + + '--property Alpha=a ' + + name + )) + self.addCleanup(self.wait_for_delete, 'volume snapshot', new_name) + self.addCleanup(self.openstack, 'volume snapshot delete ' + new_name) + self.assertEqual( + name, + cmd_output["name"], + ) + self.assertEqual( + 1, + cmd_output["size"], + ) + self.assertEqual( + 'aaaa', + cmd_output["description"], + ) + self.assertEqual( + {'Alpha': 'a'}, + cmd_output["properties"], + ) + self.wait_for_status('volume snapshot', name, 'available') + + # Test volume snapshot set + raw_output = self.openstack( + 'volume snapshot set ' + + '--name ' + new_name + + ' --description bbbb ' + + '--property Alpha=c ' + + '--property Beta=b ' + + name, + ) + self.assertOutput('', raw_output) + + # Show snapshot set result + cmd_output = json.loads(self.openstack( + 'volume snapshot show -f json ' + + new_name + )) + self.assertEqual( + new_name, + cmd_output["name"], + ) + self.assertEqual( + 1, + cmd_output["size"], + ) + self.assertEqual( + 'bbbb', + cmd_output["description"], + ) + self.assertEqual( + {'Alpha': 'c', 'Beta': 'b'}, + cmd_output["properties"], + ) + + # Test volume snapshot unset + raw_output = self.openstack( + 'volume snapshot unset ' + + '--property Alpha ' + + new_name, + ) + self.assertOutput('', raw_output) + + cmd_output = json.loads(self.openstack( + 'volume snapshot show -f json ' + + new_name + )) + self.assertEqual( + {'Beta': 'b'}, + cmd_output["properties"], + ) + + # Test volume snapshot set --no-property + raw_output = self.openstack( + 'volume snapshot set ' + + '--no-property ' + + new_name, + ) + self.assertOutput('', raw_output) + cmd_output = json.loads(self.openstack( + 'volume snapshot show -f json ' + + new_name + )) + self.assertNotIn( + {'Beta': 'b'}, + cmd_output["properties"], + ) diff --git a/openstackclient/tests/functional/volume/v3/test_volume_type.py b/openstackclient/tests/functional/volume/v3/test_volume_type.py index eb66515e..79d40969 100644 --- a/openstackclient/tests/functional/volume/v3/test_volume_type.py +++ b/openstackclient/tests/functional/volume/v3/test_volume_type.py @@ -10,9 +10,229 @@ # License for the specific language governing permissions and limitations # under the License. -from openstackclient.tests.functional.volume.v2 import test_volume_type as v2 +import json +import time +import uuid + from openstackclient.tests.functional.volume.v3 import common -class VolumeTypeTests(common.BaseVolumeTests, v2.VolumeTypeTests): +class VolumeTypeTests(common.BaseVolumeTests): """Functional tests for volume type. """ + + def test_volume_type_create_list(self): + name = uuid.uuid4().hex + cmd_output = json.loads(self.openstack( + 'volume type create -f json --private ' + + name, + )) + self.addCleanup( + self.openstack, + 'volume type delete ' + name, + ) + self.assertEqual(name, cmd_output['name']) + + cmd_output = json.loads(self.openstack( + 'volume type show -f json %s' % name + )) + self.assertEqual(name, cmd_output['name']) + + cmd_output = json.loads(self.openstack('volume type list -f json')) + self.assertIn(name, [t['Name'] for t in cmd_output]) + + cmd_output = json.loads(self.openstack( + 'volume type list -f json --default' + )) + self.assertEqual(1, len(cmd_output)) + self.assertEqual('lvmdriver-1', cmd_output[0]['Name']) + + def test_volume_type_set_unset_properties(self): + name = uuid.uuid4().hex + cmd_output = json.loads(self.openstack( + 'volume type create -f json --private ' + + name, + )) + self.addCleanup( + self.openstack, + 'volume type delete ' + name + ) + self.assertEqual(name, cmd_output['name']) + + raw_output = self.openstack( + 'volume type set --property a=b --property c=d %s' % name + ) + self.assertEqual("", raw_output) + cmd_output = json.loads(self.openstack( + 'volume type show -f json %s' % name + )) + self.assertEqual({'a': 'b', 'c': 'd'}, cmd_output['properties']) + + raw_output = self.openstack( + 'volume type unset --property a %s' % name + ) + self.assertEqual("", raw_output) + cmd_output = json.loads(self.openstack( + 'volume type show -f json %s' % name + )) + self.assertEqual({'c': 'd'}, cmd_output['properties']) + + def test_volume_type_set_unset_multiple_properties(self): + name = uuid.uuid4().hex + cmd_output = json.loads(self.openstack( + 'volume type create -f json --private ' + + name, + )) + self.addCleanup( + self.openstack, + 'volume type delete ' + name + ) + self.assertEqual(name, cmd_output['name']) + + raw_output = self.openstack( + 'volume type set --property a=b --property c=d %s' % name + ) + self.assertEqual("", raw_output) + cmd_output = json.loads(self.openstack( + 'volume type show -f json %s' % name + )) + self.assertEqual({'a': 'b', 'c': 'd'}, cmd_output['properties']) + + raw_output = self.openstack( + 'volume type unset --property a --property c %s' % name + ) + self.assertEqual("", raw_output) + cmd_output = json.loads(self.openstack( + 'volume type show -f json %s' % name + )) + self.assertEqual({}, cmd_output['properties']) + + def test_volume_type_set_unset_project(self): + name = uuid.uuid4().hex + cmd_output = json.loads(self.openstack( + 'volume type create -f json --private ' + + name, + )) + self.addCleanup( + self.openstack, + 'volume type delete ' + name + ) + self.assertEqual(name, cmd_output['name']) + + raw_output = self.openstack( + 'volume type set --project admin %s' % name + ) + self.assertEqual("", raw_output) + + raw_output = self.openstack( + 'volume type unset --project admin %s' % name + ) + self.assertEqual("", raw_output) + + def test_multi_delete(self): + vol_type1 = uuid.uuid4().hex + vol_type2 = uuid.uuid4().hex + self.openstack('volume type create %s' % vol_type1) + time.sleep(5) + self.openstack('volume type create %s' % vol_type2) + time.sleep(5) + cmd = 'volume type delete %s %s' % (vol_type1, vol_type2) + raw_output = self.openstack(cmd) + self.assertOutput('', raw_output) + + # NOTE: Add some basic funtional tests with the old format to + # make sure the command works properly, need to change + # these to new test format when beef up all tests for + # volume tye commands. + def test_encryption_type(self): + name = uuid.uuid4().hex + encryption_type = uuid.uuid4().hex + # test create new encryption type + cmd_output = json.loads(self.openstack( + 'volume type create -f json ' + '--encryption-provider LuksEncryptor ' + '--encryption-cipher aes-xts-plain64 ' + '--encryption-key-size 128 ' + '--encryption-control-location front-end ' + + encryption_type)) + expected = {'provider': 'LuksEncryptor', + 'cipher': 'aes-xts-plain64', + 'key_size': 128, + 'control_location': 'front-end'} + for attr, value in expected.items(): + self.assertEqual(value, cmd_output['encryption'][attr]) + # test show encryption type + cmd_output = json.loads(self.openstack( + 'volume type show -f json --encryption-type ' + encryption_type)) + expected = {'provider': 'LuksEncryptor', + 'cipher': 'aes-xts-plain64', + 'key_size': 128, + 'control_location': 'front-end'} + for attr, value in expected.items(): + self.assertEqual(value, cmd_output['encryption'][attr]) + # test list encryption type + cmd_output = json.loads(self.openstack( + 'volume type list -f json --encryption-type')) + encryption_output = [t['Encryption'] for t in cmd_output + if t['Name'] == encryption_type][0] + expected = {'provider': 'LuksEncryptor', + 'cipher': 'aes-xts-plain64', + 'key_size': 128, + 'control_location': 'front-end'} + for attr, value in expected.items(): + self.assertEqual(value, encryption_output[attr]) + # test set existing encryption type + raw_output = self.openstack( + 'volume type set ' + '--encryption-key-size 256 ' + '--encryption-control-location back-end ' + + encryption_type) + self.assertEqual('', raw_output) + cmd_output = json.loads(self.openstack( + 'volume type show -f json --encryption-type ' + encryption_type)) + expected = {'provider': 'LuksEncryptor', + 'cipher': 'aes-xts-plain64', + 'key_size': 256, + 'control_location': 'back-end'} + for attr, value in expected.items(): + self.assertEqual(value, cmd_output['encryption'][attr]) + # test set new encryption type + cmd_output = json.loads(self.openstack( + 'volume type create -f json --private ' + + name, + )) + self.addCleanup( + self.openstack, + 'volume type delete ' + name, + ) + self.assertEqual(name, cmd_output['name']) + + raw_output = self.openstack( + 'volume type set ' + '--encryption-provider LuksEncryptor ' + '--encryption-cipher aes-xts-plain64 ' + '--encryption-key-size 128 ' + '--encryption-control-location front-end ' + + name) + self.assertEqual('', raw_output) + + cmd_output = json.loads(self.openstack( + 'volume type show -f json --encryption-type ' + name + )) + expected = {'provider': 'LuksEncryptor', + 'cipher': 'aes-xts-plain64', + 'key_size': 128, + 'control_location': 'front-end'} + for attr, value in expected.items(): + self.assertEqual(value, cmd_output['encryption'][attr]) + # test unset encryption type + raw_output = self.openstack( + 'volume type unset --encryption-type ' + name + ) + self.assertEqual('', raw_output) + cmd_output = json.loads(self.openstack( + 'volume type show -f json --encryption-type ' + name + )) + self.assertEqual({}, cmd_output['encryption']) + # test delete encryption type + raw_output = self.openstack('volume type delete ' + encryption_type) + self.assertEqual('', raw_output) diff --git a/openstackclient/tests/unit/api/test_object_store_v1.py b/openstackclient/tests/unit/api/test_object_store_v1.py index 74b62493..96c68d5a 100644 --- a/openstackclient/tests/unit/api/test_object_store_v1.py +++ b/openstackclient/tests/unit/api/test_object_store_v1.py @@ -13,7 +13,7 @@ """Object Store v1 API Library Tests""" -import mock +from unittest import mock from keystoneauth1 import session from requests_mock.contrib import fixture @@ -151,12 +151,14 @@ class TestContainer(TestObjectAPIv1): 'X-Container-Meta-Owner': FAKE_ACCOUNT, 'x-container-object-count': '1', 'x-container-bytes-used': '577', + 'x-storage-policy': 'o1--sr-r3' } resp = { 'account': FAKE_ACCOUNT, 'container': 'qaz', 'object_count': '1', 'bytes_used': '577', + 'storage_policy': 'o1--sr-r3', 'properties': {'Owner': FAKE_ACCOUNT}, } self.requests_mock.register_uri( diff --git a/openstackclient/tests/unit/common/test_availability_zone.py b/openstackclient/tests/unit/common/test_availability_zone.py index 6c7adc43..8733b510 100644 --- a/openstackclient/tests/unit/common/test_availability_zone.py +++ b/openstackclient/tests/unit/common/test_availability_zone.py @@ -11,9 +11,7 @@ # under the License. # -import mock - -import six +from unittest import mock from openstackclient.common import availability_zone from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes @@ -31,8 +29,8 @@ def _build_compute_az_datalist(compute_az, long_datalist=False): 'available', ) else: - for host, services in six.iteritems(compute_az.hosts): - for service, state in six.iteritems(services): + for host, services in compute_az.hosts.items(): + for service, state in services.items(): datalist += ( compute_az.zoneName, 'available', diff --git a/openstackclient/tests/unit/common/test_command.py b/openstackclient/tests/unit/common/test_command.py index 6ddb7c12..4fde5301 100644 --- a/openstackclient/tests/unit/common/test_command.py +++ b/openstackclient/tests/unit/common/test_command.py @@ -12,7 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. -import mock +from unittest import mock from osc_lib.command import command from osc_lib import exceptions diff --git a/openstackclient/tests/unit/common/test_configuration.py b/openstackclient/tests/unit/common/test_configuration.py index e10522b9..bdd3debf 100644 --- a/openstackclient/tests/unit/common/test_configuration.py +++ b/openstackclient/tests/unit/common/test_configuration.py @@ -11,7 +11,7 @@ # under the License. # -import mock +from unittest import mock from openstackclient.common import configuration from openstackclient.tests.unit import fakes diff --git a/openstackclient/tests/unit/common/test_extension.py b/openstackclient/tests/unit/common/test_extension.py index 87c62da4..5093cbbb 100644 --- a/openstackclient/tests/unit/common/test_extension.py +++ b/openstackclient/tests/unit/common/test_extension.py @@ -11,7 +11,7 @@ # under the License. # -import mock +from unittest import mock from openstackclient.common import extension from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes diff --git a/openstackclient/tests/unit/common/test_logs.py b/openstackclient/tests/unit/common/test_logs.py index 421234d6..0e710561 100644 --- a/openstackclient/tests/unit/common/test_logs.py +++ b/openstackclient/tests/unit/common/test_logs.py @@ -15,8 +15,7 @@ # or Jun 2017. import logging - -import mock +from unittest import mock from osc_lib import logs diff --git a/openstackclient/tests/unit/common/test_module.py b/openstackclient/tests/unit/common/test_module.py index 2491d639..d2e8293f 100644 --- a/openstackclient/tests/unit/common/test_module.py +++ b/openstackclient/tests/unit/common/test_module.py @@ -15,7 +15,7 @@ """Test module module""" -import mock +from unittest import mock from openstackclient.common import module as osc_module from openstackclient.tests.unit import fakes diff --git a/openstackclient/tests/unit/common/test_project_purge.py b/openstackclient/tests/unit/common/test_project_purge.py index 6e8ce188..adc48ce2 100644 --- a/openstackclient/tests/unit/common/test_project_purge.py +++ b/openstackclient/tests/unit/common/test_project_purge.py @@ -10,7 +10,7 @@ # License for the specific language governing permissions and limitations # under the License. -import mock +from unittest import mock from osc_lib import exceptions diff --git a/openstackclient/tests/unit/common/test_quota.py b/openstackclient/tests/unit/common/test_quota.py index 297452a2..bd59ca77 100644 --- a/openstackclient/tests/unit/common/test_quota.py +++ b/openstackclient/tests/unit/common/test_quota.py @@ -11,8 +11,8 @@ # under the License. import copy +from unittest import mock -import mock from osc_lib import exceptions from openstackclient.common import quota diff --git a/openstackclient/tests/unit/compute/v2/fakes.py b/openstackclient/tests/unit/compute/v2/fakes.py index 7357e143..6e12f735 100644 --- a/openstackclient/tests/unit/compute/v2/fakes.py +++ b/openstackclient/tests/unit/compute/v2/fakes.py @@ -14,9 +14,9 @@ # import copy +from unittest import mock import uuid -import mock from novaclient import api_versions from openstackclient.api import compute_v2 diff --git a/openstackclient/tests/unit/compute/v2/test_agent.py b/openstackclient/tests/unit/compute/v2/test_agent.py index 169940e2..c6d4f2b6 100644 --- a/openstackclient/tests/unit/compute/v2/test_agent.py +++ b/openstackclient/tests/unit/compute/v2/test_agent.py @@ -13,8 +13,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib import exceptions diff --git a/openstackclient/tests/unit/compute/v2/test_aggregate.py b/openstackclient/tests/unit/compute/v2/test_aggregate.py index 0937047c..cd0c1525 100644 --- a/openstackclient/tests/unit/compute/v2/test_aggregate.py +++ b/openstackclient/tests/unit/compute/v2/test_aggregate.py @@ -13,8 +13,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib.cli import format_columns from osc_lib import exceptions diff --git a/openstackclient/tests/unit/compute/v2/test_console.py b/openstackclient/tests/unit/compute/v2/test_console.py index 3c708aae..99a14f04 100644 --- a/openstackclient/tests/unit/compute/v2/test_console.py +++ b/openstackclient/tests/unit/compute/v2/test_console.py @@ -13,7 +13,7 @@ # under the License. # -import mock +from unittest import mock from openstackclient.compute.v2 import console from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes diff --git a/openstackclient/tests/unit/compute/v2/test_flavor.py b/openstackclient/tests/unit/compute/v2/test_flavor.py index a112fc1f..fe7ce174 100644 --- a/openstackclient/tests/unit/compute/v2/test_flavor.py +++ b/openstackclient/tests/unit/compute/v2/test_flavor.py @@ -13,8 +13,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call import novaclient from osc_lib import exceptions diff --git a/openstackclient/tests/unit/compute/v2/test_host.py b/openstackclient/tests/unit/compute/v2/test_host.py index 244da413..4e1b5ad1 100644 --- a/openstackclient/tests/unit/compute/v2/test_host.py +++ b/openstackclient/tests/unit/compute/v2/test_host.py @@ -13,7 +13,7 @@ # under the License. # -import mock +from unittest import mock from openstackclient.compute.v2 import host from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes diff --git a/openstackclient/tests/unit/compute/v2/test_keypair.py b/openstackclient/tests/unit/compute/v2/test_keypair.py index 0e5fb143..1f3f56f9 100644 --- a/openstackclient/tests/unit/compute/v2/test_keypair.py +++ b/openstackclient/tests/unit/compute/v2/test_keypair.py @@ -13,10 +13,10 @@ # under the License. # +from unittest import mock +from unittest.mock import call import uuid -import mock -from mock import call from osc_lib import exceptions from osc_lib import utils diff --git a/openstackclient/tests/unit/compute/v2/test_server.py b/openstackclient/tests/unit/compute/v2/test_server.py index c2bac277..27eefd85 100644 --- a/openstackclient/tests/unit/compute/v2/test_server.py +++ b/openstackclient/tests/unit/compute/v2/test_server.py @@ -16,9 +16,9 @@ import argparse import collections import copy import getpass +from unittest import mock +from unittest.mock import call -import mock -from mock import call from novaclient import api_versions from openstack import exceptions as sdk_exceptions from osc_lib import exceptions @@ -860,7 +860,7 @@ class TestServerCreate(TestServer): ('key_name', 'keyname'), ('property', {'Beta': 'b'}), ('security_group', ['securitygroup']), - ('hint', ['a=b', 'a=c']), + ('hint', {'a': ['b', 'c']}), ('config_drive', False), ('server_name', self.new_server.name), ] @@ -2060,6 +2060,29 @@ class TestServerCreate(TestServer): self.cmd.take_action, parsed_args) + def test_server_create_invalid_hint(self): + # Not a key-value pair + arglist = [ + '--image', 'image1', + '--flavor', 'flavor1', + '--hint', 'a0cf03a5-d921-4877-bb5c-86d26cf818e1', + self.new_server.name, + ] + self.assertRaises(argparse.ArgumentTypeError, + self.check_parser, + self.cmd, arglist, []) + + # Empty key + arglist = [ + '--image', 'image1', + '--flavor', 'flavor1', + '--hint', '=a0cf03a5-d921-4877-bb5c-86d26cf818e1', + self.new_server.name, + ] + self.assertRaises(argparse.ArgumentTypeError, + self.check_parser, + self.cmd, arglist, []) + def test_server_create_with_description_api_newer(self): # Description is supported for nova api version 2.19 or above diff --git a/openstackclient/tests/unit/compute/v2/test_server_backup.py b/openstackclient/tests/unit/compute/v2/test_server_backup.py index 24a94531..7dd459d8 100644 --- a/openstackclient/tests/unit/compute/v2/test_server_backup.py +++ b/openstackclient/tests/unit/compute/v2/test_server_backup.py @@ -11,7 +11,7 @@ # under the License. # -import mock +from unittest import mock from osc_lib.cli import format_columns from osc_lib import exceptions diff --git a/openstackclient/tests/unit/compute/v2/test_server_group.py b/openstackclient/tests/unit/compute/v2/test_server_group.py index dc924e24..9cd876ea 100644 --- a/openstackclient/tests/unit/compute/v2/test_server_group.py +++ b/openstackclient/tests/unit/compute/v2/test_server_group.py @@ -13,7 +13,7 @@ # under the License. # -import mock +from unittest import mock from osc_lib import exceptions from osc_lib import utils diff --git a/openstackclient/tests/unit/compute/v2/test_server_image.py b/openstackclient/tests/unit/compute/v2/test_server_image.py index 02e43129..f9d7b10e 100644 --- a/openstackclient/tests/unit/compute/v2/test_server_image.py +++ b/openstackclient/tests/unit/compute/v2/test_server_image.py @@ -10,7 +10,7 @@ # License for the specific language governing permissions and limitations # under the License. # -import mock +from unittest import mock from osc_lib.cli import format_columns from osc_lib import exceptions diff --git a/openstackclient/tests/unit/compute/v2/test_service.py b/openstackclient/tests/unit/compute/v2/test_service.py index 0d663b2e..7a036833 100644 --- a/openstackclient/tests/unit/compute/v2/test_service.py +++ b/openstackclient/tests/unit/compute/v2/test_service.py @@ -13,8 +13,9 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call + from novaclient import api_versions from osc_lib import exceptions import six diff --git a/openstackclient/tests/unit/compute/v2/test_usage.py b/openstackclient/tests/unit/compute/v2/test_usage.py index 76dcc963..c0871025 100644 --- a/openstackclient/tests/unit/compute/v2/test_usage.py +++ b/openstackclient/tests/unit/compute/v2/test_usage.py @@ -12,8 +12,8 @@ # import datetime +from unittest import mock -import mock from novaclient import api_versions from openstackclient.compute.v2 import usage diff --git a/openstackclient/tests/unit/fakes.py b/openstackclient/tests/unit/fakes.py index bca457e4..e5476f06 100644 --- a/openstackclient/tests/unit/fakes.py +++ b/openstackclient/tests/unit/fakes.py @@ -15,9 +15,9 @@ import json import sys +from unittest import mock from keystoneauth1 import fixture -import mock import requests import six @@ -200,7 +200,7 @@ class FakeResource(object): self._loaded = loaded def _add_details(self, info): - for (k, v) in six.iteritems(info): + for (k, v) in info.items(): setattr(self, k, v) def _add_methods(self, methods): @@ -211,7 +211,7 @@ class FakeResource(object): @value. When users access the attribute with (), @value will be returned, which looks like a function call. """ - for (name, ret) in six.iteritems(methods): + for (name, ret) in methods.items(): method = mock.Mock(return_value=ret) setattr(self, name, method) diff --git a/openstackclient/tests/unit/identity/v2_0/fakes.py b/openstackclient/tests/unit/identity/v2_0/fakes.py index 5db94222..bd76a784 100644 --- a/openstackclient/tests/unit/identity/v2_0/fakes.py +++ b/openstackclient/tests/unit/identity/v2_0/fakes.py @@ -14,11 +14,11 @@ # import copy +from unittest import mock import uuid from keystoneauth1 import access from keystoneauth1 import fixture -import mock from openstackclient.tests.unit import fakes from openstackclient.tests.unit import utils diff --git a/openstackclient/tests/unit/identity/v2_0/test_catalog.py b/openstackclient/tests/unit/identity/v2_0/test_catalog.py index 362dec08..17355074 100644 --- a/openstackclient/tests/unit/identity/v2_0/test_catalog.py +++ b/openstackclient/tests/unit/identity/v2_0/test_catalog.py @@ -11,7 +11,7 @@ # under the License. # -import mock +from unittest import mock from openstackclient.identity.v2_0 import catalog from openstackclient.tests.unit.identity.v2_0 import fakes as identity_fakes diff --git a/openstackclient/tests/unit/identity/v2_0/test_project.py b/openstackclient/tests/unit/identity/v2_0/test_project.py index 7af7b394..cd8c825d 100644 --- a/openstackclient/tests/unit/identity/v2_0/test_project.py +++ b/openstackclient/tests/unit/identity/v2_0/test_project.py @@ -13,7 +13,7 @@ # under the License. # -import mock +from unittest import mock from keystoneauth1 import exceptions as ks_exc from osc_lib.cli import format_columns diff --git a/openstackclient/tests/unit/identity/v2_0/test_role.py b/openstackclient/tests/unit/identity/v2_0/test_role.py index 643d77f6..423884d9 100644 --- a/openstackclient/tests/unit/identity/v2_0/test_role.py +++ b/openstackclient/tests/unit/identity/v2_0/test_role.py @@ -13,7 +13,7 @@ # under the License. # -import mock +from unittest import mock from keystoneauth1 import exceptions as ks_exc from osc_lib import exceptions diff --git a/openstackclient/tests/unit/identity/v2_0/test_role_assignment.py b/openstackclient/tests/unit/identity/v2_0/test_role_assignment.py index 733fda6c..3e1231aa 100644 --- a/openstackclient/tests/unit/identity/v2_0/test_role_assignment.py +++ b/openstackclient/tests/unit/identity/v2_0/test_role_assignment.py @@ -12,8 +12,8 @@ # import copy +from unittest import mock -import mock from osc_lib import exceptions from openstackclient.identity.v2_0 import role_assignment diff --git a/openstackclient/tests/unit/identity/v2_0/test_token.py b/openstackclient/tests/unit/identity/v2_0/test_token.py index dd7f4f4a..c079ce67 100644 --- a/openstackclient/tests/unit/identity/v2_0/test_token.py +++ b/openstackclient/tests/unit/identity/v2_0/test_token.py @@ -13,7 +13,7 @@ # under the License. # -import mock +from unittest import mock from openstackclient.identity.v2_0 import token from openstackclient.tests.unit.identity.v2_0 import fakes as identity_fakes diff --git a/openstackclient/tests/unit/identity/v2_0/test_user.py b/openstackclient/tests/unit/identity/v2_0/test_user.py index 0a0d4b36..4308b05d 100644 --- a/openstackclient/tests/unit/identity/v2_0/test_user.py +++ b/openstackclient/tests/unit/identity/v2_0/test_user.py @@ -13,7 +13,7 @@ # under the License. # -import mock +from unittest import mock from keystoneauth1 import exceptions as ks_exc from osc_lib import exceptions diff --git a/openstackclient/tests/unit/identity/v3/fakes.py b/openstackclient/tests/unit/identity/v3/fakes.py index e9ff0689..eb3ce2a3 100644 --- a/openstackclient/tests/unit/identity/v3/fakes.py +++ b/openstackclient/tests/unit/identity/v3/fakes.py @@ -15,11 +15,11 @@ import copy import datetime +from unittest import mock import uuid from keystoneauth1 import access from keystoneauth1 import fixture -import mock from osc_lib.cli import format_columns from openstackclient.tests.unit import fakes @@ -176,6 +176,7 @@ ids_for_children = [PROJECT_WITH_GRANDPARENT['id']] role_id = 'r1' role_name = 'roller' +role_description = 'role description' ROLE = { 'id': role_id, @@ -470,6 +471,14 @@ app_cred_description = 'app credential for testing' app_cred_expires = datetime.datetime(2022, 1, 1, 0, 0) app_cred_expires_str = app_cred_expires.strftime('%Y-%m-%dT%H:%M:%S%z') app_cred_secret = 'moresecuresecret' +app_cred_access_rules = ( + '[{"path": "/v2.1/servers", "method": "GET", "service": "compute"}]' +) +app_cred_access_rules_path = '/tmp/access_rules.json' +access_rule_id = 'access-rule-id' +access_rule_service = 'compute' +access_rule_path = '/v2.1/servers' +access_rule_method = 'GET' APP_CRED_BASIC = { 'id': app_cred_id, 'name': app_cred_name, @@ -478,7 +487,8 @@ APP_CRED_BASIC = { 'description': None, 'expires_at': None, 'unrestricted': False, - 'secret': app_cred_secret + 'secret': app_cred_secret, + 'access_rules': None } APP_CRED_OPTIONS = { 'id': app_cred_id, @@ -488,7 +498,25 @@ APP_CRED_OPTIONS = { 'description': app_cred_description, 'expires_at': app_cred_expires_str, 'unrestricted': False, - 'secret': app_cred_secret + 'secret': app_cred_secret, + 'access_rules': None, +} +ACCESS_RULE = { + 'id': access_rule_id, + 'service': access_rule_service, + 'path': access_rule_path, + 'method': access_rule_method, +} +APP_CRED_ACCESS_RULES = { + 'id': app_cred_id, + 'name': app_cred_name, + 'project_id': project_id, + 'roles': app_cred_role, + 'description': None, + 'expires_at': None, + 'unrestricted': False, + 'secret': app_cred_secret, + 'access_rules': app_cred_access_rules } registered_limit_id = 'registered-limit-id' @@ -625,6 +653,8 @@ class FakeIdentityv3Client(object): self.application_credentials = mock.Mock() self.application_credentials.resource_class = fakes.FakeResource(None, {}) + self.access_rules = mock.Mock() + self.access_rules.resource_class = fakes.FakeResource(None, {}) self.inference_rules = mock.Mock() self.inference_rules.resource_class = fakes.FakeResource(None, {}) self.registered_limits = mock.Mock() diff --git a/openstackclient/tests/unit/identity/v3/test_access_rule.py b/openstackclient/tests/unit/identity/v3/test_access_rule.py new file mode 100644 index 00000000..f8b6093a --- /dev/null +++ b/openstackclient/tests/unit/identity/v3/test_access_rule.py @@ -0,0 +1,174 @@ +# Copyright 2019 SUSE LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +import copy + +import mock +from osc_lib import exceptions +from osc_lib import utils + +from openstackclient.identity.v3 import access_rule +from openstackclient.tests.unit import fakes +from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes + + +class TestAccessRule(identity_fakes.TestIdentityv3): + + def setUp(self): + super(TestAccessRule, self).setUp() + + identity_manager = self.app.client_manager.identity + self.access_rules_mock = identity_manager.access_rules + self.access_rules_mock.reset_mock() + self.roles_mock = identity_manager.roles + self.roles_mock.reset_mock() + + +class TestAccessRuleDelete(TestAccessRule): + + def setUp(self): + super(TestAccessRuleDelete, self).setUp() + + # This is the return value for utils.find_resource() + self.access_rules_mock.get.return_value = fakes.FakeResource( + None, + copy.deepcopy(identity_fakes.ACCESS_RULE), + loaded=True, + ) + self.access_rules_mock.delete.return_value = None + + # Get the command object to test + self.cmd = access_rule.DeleteAccessRule( + self.app, None) + + def test_access_rule_delete(self): + arglist = [ + identity_fakes.access_rule_id, + ] + verifylist = [ + ('access_rule', [identity_fakes.access_rule_id]) + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + + self.access_rules_mock.delete.assert_called_with( + identity_fakes.access_rule_id, + ) + self.assertIsNone(result) + + @mock.patch.object(utils, 'find_resource') + def test_delete_multi_access_rules_with_exception(self, find_mock): + find_mock.side_effect = [self.access_rules_mock.get.return_value, + exceptions.CommandError] + arglist = [ + identity_fakes.access_rule_id, + 'nonexistent_access_rule', + ] + verifylist = [ + ('access_rule', arglist), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + try: + self.cmd.take_action(parsed_args) + self.fail('CommandError should be raised.') + except exceptions.CommandError as e: + self.assertEqual('1 of 2 access rules failed to' + ' delete.', str(e)) + + find_mock.assert_any_call(self.access_rules_mock, + identity_fakes.access_rule_id) + find_mock.assert_any_call(self.access_rules_mock, + 'nonexistent_access_rule') + + self.assertEqual(2, find_mock.call_count) + self.access_rules_mock.delete.assert_called_once_with( + identity_fakes.access_rule_id) + + +class TestAccessRuleList(TestAccessRule): + + def setUp(self): + super(TestAccessRuleList, self).setUp() + + self.access_rules_mock.list.return_value = [ + fakes.FakeResource( + None, + copy.deepcopy(identity_fakes.ACCESS_RULE), + loaded=True, + ), + ] + + # Get the command object to test + self.cmd = access_rule.ListAccessRule(self.app, None) + + def test_access_rule_list(self): + arglist = [] + verifylist = [] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + self.access_rules_mock.list.assert_called_with(user=None) + + collist = ('ID', 'Service', 'Method', 'Path') + self.assertEqual(collist, columns) + datalist = (( + identity_fakes.access_rule_id, + identity_fakes.access_rule_service, + identity_fakes.access_rule_method, + identity_fakes.access_rule_path, + ), ) + self.assertEqual(datalist, tuple(data)) + + +class TestAccessRuleShow(TestAccessRule): + + def setUp(self): + super(TestAccessRuleShow, self).setUp() + + self.access_rules_mock.get.return_value = fakes.FakeResource( + None, + copy.deepcopy(identity_fakes.ACCESS_RULE), + loaded=True, + ) + + # Get the command object to test + self.cmd = access_rule.ShowAccessRule(self.app, None) + + def test_access_rule_show(self): + arglist = [ + identity_fakes.access_rule_id, + ] + verifylist = [ + ('access_rule', identity_fakes.access_rule_id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + self.access_rules_mock.get.assert_called_with( + identity_fakes.access_rule_id) + + collist = ('id', 'method', 'path', 'service') + self.assertEqual(collist, columns) + datalist = ( + identity_fakes.access_rule_id, + identity_fakes.access_rule_method, + identity_fakes.access_rule_path, + identity_fakes.access_rule_service, + ) + self.assertEqual(datalist, data) diff --git a/openstackclient/tests/unit/identity/v3/test_application_credential.py b/openstackclient/tests/unit/identity/v3/test_application_credential.py index e7c8ede8..24bafc9f 100644 --- a/openstackclient/tests/unit/identity/v3/test_application_credential.py +++ b/openstackclient/tests/unit/identity/v3/test_application_credential.py @@ -14,8 +14,9 @@ # import copy +import json +from unittest import mock -import mock from osc_lib import exceptions from osc_lib import utils @@ -79,18 +80,20 @@ class TestApplicationCredentialCreate(TestApplicationCredential): 'expires_at': None, 'description': None, 'unrestricted': False, + 'access_rules': None, } self.app_creds_mock.create.assert_called_with( name, **kwargs ) - collist = ('description', 'expires_at', 'id', 'name', 'project_id', - 'roles', 'secret', 'unrestricted') + collist = ('access_rules', 'description', 'expires_at', 'id', 'name', + 'project_id', 'roles', 'secret', 'unrestricted') self.assertEqual(collist, columns) datalist = ( None, None, + None, identity_fakes.app_cred_id, identity_fakes.app_cred_name, identity_fakes.project_id, @@ -135,17 +138,19 @@ class TestApplicationCredentialCreate(TestApplicationCredential): 'roles': [identity_fakes.role_id], 'expires_at': identity_fakes.app_cred_expires, 'description': 'credential for testing', - 'unrestricted': False + 'unrestricted': False, + 'access_rules': None, } self.app_creds_mock.create.assert_called_with( name, **kwargs ) - collist = ('description', 'expires_at', 'id', 'name', 'project_id', - 'roles', 'secret', 'unrestricted') + collist = ('access_rules', 'description', 'expires_at', 'id', 'name', + 'project_id', 'roles', 'secret', 'unrestricted') self.assertEqual(collist, columns) datalist = ( + None, identity_fakes.app_cred_description, identity_fakes.app_cred_expires_str, identity_fakes.app_cred_id, @@ -157,6 +162,111 @@ class TestApplicationCredentialCreate(TestApplicationCredential): ) self.assertEqual(datalist, data) + def test_application_credential_create_with_access_rules_string(self): + name = identity_fakes.app_cred_name + self.app_creds_mock.create.return_value = fakes.FakeResource( + None, + copy.deepcopy(identity_fakes.APP_CRED_ACCESS_RULES), + loaded=True, + ) + + arglist = [ + name, + '--access-rules', identity_fakes.app_cred_access_rules, + ] + verifylist = [ + ('name', identity_fakes.app_cred_name), + ('access_rules', identity_fakes.app_cred_access_rules), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + # Set expected values + kwargs = { + 'secret': None, + 'roles': [], + 'expires_at': None, + 'description': None, + 'unrestricted': False, + 'access_rules': json.loads(identity_fakes.app_cred_access_rules) + } + self.app_creds_mock.create.assert_called_with( + name, + **kwargs + ) + + collist = ('access_rules', 'description', 'expires_at', 'id', 'name', + 'project_id', 'roles', 'secret', 'unrestricted') + self.assertEqual(collist, columns) + datalist = ( + identity_fakes.app_cred_access_rules, + None, + None, + identity_fakes.app_cred_id, + identity_fakes.app_cred_name, + identity_fakes.project_id, + identity_fakes.role_name, + identity_fakes.app_cred_secret, + False, + ) + self.assertEqual(datalist, data) + + @mock.patch('openstackclient.identity.v3.application_credential.json.load') + @mock.patch('openstackclient.identity.v3.application_credential.open') + def test_application_credential_create_with_access_rules_file( + self, _, mock_json_load): + mock_json_load.return_value = identity_fakes.app_cred_access_rules + + name = identity_fakes.app_cred_name + self.app_creds_mock.create.return_value = fakes.FakeResource( + None, + copy.deepcopy(identity_fakes.APP_CRED_ACCESS_RULES), + loaded=True, + ) + + arglist = [ + name, + '--access-rules', identity_fakes.app_cred_access_rules_path, + ] + verifylist = [ + ('name', identity_fakes.app_cred_name), + ('access_rules', identity_fakes.app_cred_access_rules_path), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + # Set expected values + kwargs = { + 'secret': None, + 'roles': [], + 'expires_at': None, + 'description': None, + 'unrestricted': False, + 'access_rules': identity_fakes.app_cred_access_rules + } + self.app_creds_mock.create.assert_called_with( + name, + **kwargs + ) + + collist = ('access_rules', 'description', 'expires_at', 'id', 'name', + 'project_id', 'roles', 'secret', 'unrestricted') + self.assertEqual(collist, columns) + datalist = ( + identity_fakes.app_cred_access_rules, + None, + None, + identity_fakes.app_cred_id, + identity_fakes.app_cred_name, + identity_fakes.project_id, + identity_fakes.role_name, + identity_fakes.app_cred_secret, + False, + ) + self.assertEqual(datalist, data) + class TestApplicationCredentialDelete(TestApplicationCredential): @@ -293,12 +403,13 @@ class TestApplicationCredentialShow(TestApplicationCredential): self.app_creds_mock.get.assert_called_with(identity_fakes.app_cred_id) - collist = ('description', 'expires_at', 'id', 'name', 'project_id', - 'roles', 'secret', 'unrestricted') + collist = ('access_rules', 'description', 'expires_at', 'id', 'name', + 'project_id', 'roles', 'secret', 'unrestricted') self.assertEqual(collist, columns) datalist = ( None, None, + None, identity_fakes.app_cred_id, identity_fakes.app_cred_name, identity_fakes.project_id, diff --git a/openstackclient/tests/unit/identity/v3/test_catalog.py b/openstackclient/tests/unit/identity/v3/test_catalog.py index ba076dbd..3630ccb6 100644 --- a/openstackclient/tests/unit/identity/v3/test_catalog.py +++ b/openstackclient/tests/unit/identity/v3/test_catalog.py @@ -11,7 +11,7 @@ # under the License. # -import mock +from unittest import mock from openstackclient.identity.v3 import catalog from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes diff --git a/openstackclient/tests/unit/identity/v3/test_credential.py b/openstackclient/tests/unit/identity/v3/test_credential.py index de0306dd..40596d58 100644 --- a/openstackclient/tests/unit/identity/v3/test_credential.py +++ b/openstackclient/tests/unit/identity/v3/test_credential.py @@ -10,8 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib import exceptions diff --git a/openstackclient/tests/unit/identity/v3/test_endpoint_group.py b/openstackclient/tests/unit/identity/v3/test_endpoint_group.py index 6e9da9c7..c081fa1f 100644 --- a/openstackclient/tests/unit/identity/v3/test_endpoint_group.py +++ b/openstackclient/tests/unit/identity/v3/test_endpoint_group.py @@ -11,7 +11,7 @@ # under the License. # -import mock +from unittest import mock from openstackclient.identity.v3 import endpoint_group from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes diff --git a/openstackclient/tests/unit/identity/v3/test_group.py b/openstackclient/tests/unit/identity/v3/test_group.py index 81722631..04ba0dbe 100644 --- a/openstackclient/tests/unit/identity/v3/test_group.py +++ b/openstackclient/tests/unit/identity/v3/test_group.py @@ -11,8 +11,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from keystoneauth1 import exceptions as ks_exc from osc_lib import exceptions diff --git a/openstackclient/tests/unit/identity/v3/test_identity_provider.py b/openstackclient/tests/unit/identity/v3/test_identity_provider.py index 0163c6c8..a419a9bc 100644 --- a/openstackclient/tests/unit/identity/v3/test_identity_provider.py +++ b/openstackclient/tests/unit/identity/v3/test_identity_provider.py @@ -13,8 +13,7 @@ # under the License. import copy - -import mock +from unittest import mock from openstackclient.identity.v3 import identity_provider from openstackclient.tests.unit import fakes diff --git a/openstackclient/tests/unit/identity/v3/test_mappings.py b/openstackclient/tests/unit/identity/v3/test_mappings.py index 1d8e77d9..184bd2a2 100644 --- a/openstackclient/tests/unit/identity/v3/test_mappings.py +++ b/openstackclient/tests/unit/identity/v3/test_mappings.py @@ -13,8 +13,8 @@ # under the License. import copy +from unittest import mock -import mock from osc_lib import exceptions from openstackclient.identity.v3 import mapping diff --git a/openstackclient/tests/unit/identity/v3/test_project.py b/openstackclient/tests/unit/identity/v3/test_project.py index db27fedc..466bea18 100644 --- a/openstackclient/tests/unit/identity/v3/test_project.py +++ b/openstackclient/tests/unit/identity/v3/test_project.py @@ -13,8 +13,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib import exceptions from osc_lib import utils diff --git a/openstackclient/tests/unit/identity/v3/test_role.py b/openstackclient/tests/unit/identity/v3/test_role.py index 99f3a2de..4278ab1c 100644 --- a/openstackclient/tests/unit/identity/v3/test_role.py +++ b/openstackclient/tests/unit/identity/v3/test_role.py @@ -14,8 +14,8 @@ # import copy +from unittest import mock -import mock from osc_lib import exceptions from osc_lib import utils @@ -332,6 +332,7 @@ class TestRoleCreate(TestRole): kwargs = { 'domain': None, 'name': identity_fakes.role_name, + 'description': None, } # RoleManager.create(name=, domain=) @@ -375,6 +376,7 @@ class TestRoleCreate(TestRole): kwargs = { 'domain': identity_fakes.domain_id, 'name': identity_fakes.ROLE_2['name'], + 'description': None, } # RoleManager.create(name=, domain=) @@ -391,6 +393,49 @@ class TestRoleCreate(TestRole): ) self.assertEqual(datalist, data) + def test_role_create_with_description(self): + + self.roles_mock.create.return_value = fakes.FakeResource( + None, + copy.deepcopy(identity_fakes.ROLE_2), + loaded=True, + ) + arglist = [ + '--description', identity_fakes.role_description, + identity_fakes.ROLE_2['name'], + ] + verifylist = [ + ('description', identity_fakes.role_description), + ('name', identity_fakes.ROLE_2['name']), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # In base command class ShowOne in cliff, abstract method take_action() + # returns a two-part tuple with a tuple of column names and a tuple of + # data to be shown. + columns, data = self.cmd.take_action(parsed_args) + + # Set expected values + kwargs = { + 'description': identity_fakes.role_description, + 'name': identity_fakes.ROLE_2['name'], + 'domain': None, + } + + # RoleManager.create(name=, domain=) + self.roles_mock.create.assert_called_with( + **kwargs + ) + + collist = ('domain', 'id', 'name') + self.assertEqual(collist, columns) + datalist = ( + 'd1', + identity_fakes.ROLE_2['id'], + identity_fakes.ROLE_2['name'], + ) + self.assertEqual(datalist, data) + class TestRoleDelete(TestRole): @@ -825,6 +870,7 @@ class TestRoleSet(TestRole): # Set expected values kwargs = { 'name': 'over', + 'description': None, } # RoleManager.update(role, name=) self.roles_mock.update.assert_called_with( @@ -856,6 +902,39 @@ class TestRoleSet(TestRole): # Set expected values kwargs = { 'name': 'over', + 'description': None, + } + # RoleManager.update(role, name=) + self.roles_mock.update.assert_called_with( + identity_fakes.ROLE_2['id'], + **kwargs + ) + self.assertIsNone(result) + + def test_role_set_description(self): + self.roles_mock.get.return_value = fakes.FakeResource( + None, + copy.deepcopy(identity_fakes.ROLE_2), + loaded=True, + ) + arglist = [ + '--name', 'over', + '--description', identity_fakes.role_description, + identity_fakes.ROLE_2['name'], + ] + verifylist = [ + ('name', 'over'), + ('description', identity_fakes.role_description), + ('role', identity_fakes.ROLE_2['name']), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + + # Set expected values + kwargs = { + 'name': 'over', + 'description': identity_fakes.role_description, } # RoleManager.update(role, name=) self.roles_mock.update.assert_called_with( diff --git a/openstackclient/tests/unit/identity/v3/test_role_assignment.py b/openstackclient/tests/unit/identity/v3/test_role_assignment.py index bff6c56d..7d38d360 100644 --- a/openstackclient/tests/unit/identity/v3/test_role_assignment.py +++ b/openstackclient/tests/unit/identity/v3/test_role_assignment.py @@ -12,8 +12,7 @@ # import copy - -import mock +from unittest import mock from openstackclient.identity.v3 import role_assignment from openstackclient.tests.unit import fakes diff --git a/openstackclient/tests/unit/identity/v3/test_token.py b/openstackclient/tests/unit/identity/v3/test_token.py index 7321909f..adb491b3 100644 --- a/openstackclient/tests/unit/identity/v3/test_token.py +++ b/openstackclient/tests/unit/identity/v3/test_token.py @@ -13,7 +13,7 @@ # under the License. # -import mock +from unittest import mock from openstackclient.identity.v3 import token from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes diff --git a/openstackclient/tests/unit/identity/v3/test_trust.py b/openstackclient/tests/unit/identity/v3/test_trust.py index 1355b908..d8cfc59f 100644 --- a/openstackclient/tests/unit/identity/v3/test_trust.py +++ b/openstackclient/tests/unit/identity/v3/test_trust.py @@ -12,8 +12,8 @@ # import copy +from unittest import mock -import mock from osc_lib import exceptions from osc_lib import utils diff --git a/openstackclient/tests/unit/identity/v3/test_user.py b/openstackclient/tests/unit/identity/v3/test_user.py index 920ee950..4b14bca0 100644 --- a/openstackclient/tests/unit/identity/v3/test_user.py +++ b/openstackclient/tests/unit/identity/v3/test_user.py @@ -14,8 +14,8 @@ # import contextlib +from unittest import mock -import mock from osc_lib import exceptions from osc_lib import utils diff --git a/openstackclient/tests/unit/image/v1/fakes.py b/openstackclient/tests/unit/image/v1/fakes.py index bbec00fc..de232235 100644 --- a/openstackclient/tests/unit/image/v1/fakes.py +++ b/openstackclient/tests/unit/image/v1/fakes.py @@ -14,10 +14,9 @@ # import copy +from unittest import mock import uuid -import mock - from openstackclient.tests.unit import fakes from openstackclient.tests.unit import utils from openstackclient.tests.unit.volume.v1 import fakes as volume_fakes diff --git a/openstackclient/tests/unit/image/v1/test_image.py b/openstackclient/tests/unit/image/v1/test_image.py index 0997d765..970b36c6 100644 --- a/openstackclient/tests/unit/image/v1/test_image.py +++ b/openstackclient/tests/unit/image/v1/test_image.py @@ -14,8 +14,7 @@ # import copy - -import mock +from unittest import mock from osc_lib.cli import format_columns from osc_lib import exceptions diff --git a/openstackclient/tests/unit/image/v2/fakes.py b/openstackclient/tests/unit/image/v2/fakes.py index f69a2bc3..655ae341 100644 --- a/openstackclient/tests/unit/image/v2/fakes.py +++ b/openstackclient/tests/unit/image/v2/fakes.py @@ -15,10 +15,10 @@ import copy import random +from unittest import mock import uuid from glanceclient.v2 import schemas -import mock from osc_lib.cli import format_columns import warlock diff --git a/openstackclient/tests/unit/image/v2/test_image.py b/openstackclient/tests/unit/image/v2/test_image.py index 748a61aa..78d857e2 100644 --- a/openstackclient/tests/unit/image/v2/test_image.py +++ b/openstackclient/tests/unit/image/v2/test_image.py @@ -14,10 +14,10 @@ # import copy +from unittest import mock from glanceclient.common import utils as glanceclient_utils from glanceclient.v2 import schemas -import mock from osc_lib.cli import format_columns from osc_lib import exceptions import warlock diff --git a/openstackclient/tests/unit/integ/cli/test_shell.py b/openstackclient/tests/unit/integ/cli/test_shell.py index 25985171..0c98a129 100644 --- a/openstackclient/tests/unit/integ/cli/test_shell.py +++ b/openstackclient/tests/unit/integ/cli/test_shell.py @@ -11,9 +11,9 @@ # under the License. import copy +from unittest import mock import fixtures -import mock from osc_lib.tests import utils as osc_lib_utils from openstackclient import shell diff --git a/openstackclient/tests/unit/network/test_common.py b/openstackclient/tests/unit/network/test_common.py index 3a206878..cde321aa 100644 --- a/openstackclient/tests/unit/network/test_common.py +++ b/openstackclient/tests/unit/network/test_common.py @@ -12,8 +12,8 @@ # import argparse +from unittest import mock -import mock import openstack from osc_lib import exceptions diff --git a/openstackclient/tests/unit/network/v2/fakes.py b/openstackclient/tests/unit/network/v2/fakes.py index 35f0b1a5..a553f501 100644 --- a/openstackclient/tests/unit/network/v2/fakes.py +++ b/openstackclient/tests/unit/network/v2/fakes.py @@ -15,10 +15,9 @@ import argparse import copy from random import choice from random import randint +from unittest import mock import uuid -import mock - from openstackclient.tests.unit import fakes from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes_v3 from openstackclient.tests.unit import utils @@ -639,6 +638,7 @@ class FakePort(object): 'security_group_ids': [], 'status': 'ACTIVE', 'tenant_id': 'project-id-' + uuid.uuid4().hex, + 'qos_network_policy_id': 'qos-policy-id-' + uuid.uuid4().hex, 'qos_policy_id': 'qos-policy-id-' + uuid.uuid4().hex, 'tags': [], 'uplink_status_propagation': False, diff --git a/openstackclient/tests/unit/network/v2/test_address_scope.py b/openstackclient/tests/unit/network/v2/test_address_scope.py index 40067188..17f13e83 100644 --- a/openstackclient/tests/unit/network/v2/test_address_scope.py +++ b/openstackclient/tests/unit/network/v2/test_address_scope.py @@ -11,8 +11,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib import exceptions diff --git a/openstackclient/tests/unit/network/v2/test_floating_ip_compute.py b/openstackclient/tests/unit/network/v2/test_floating_ip_compute.py index df47e63e..18212cf7 100644 --- a/openstackclient/tests/unit/network/v2/test_floating_ip_compute.py +++ b/openstackclient/tests/unit/network/v2/test_floating_ip_compute.py @@ -11,8 +11,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib import exceptions diff --git a/openstackclient/tests/unit/network/v2/test_floating_ip_network.py b/openstackclient/tests/unit/network/v2/test_floating_ip_network.py index cbd4da38..dbcd5c97 100644 --- a/openstackclient/tests/unit/network/v2/test_floating_ip_network.py +++ b/openstackclient/tests/unit/network/v2/test_floating_ip_network.py @@ -11,8 +11,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib import exceptions @@ -776,6 +776,32 @@ class TestSetFloatingIP(TestFloatingIPNetwork): self.network.update_ip.assert_called_once_with( self.floating_ip, **attrs) + def test_description_option(self): + arglist = [ + self.floating_ip.id, + '--port', self.floating_ip.port_id, + '--description', self.floating_ip.description, + ] + verifylist = [ + ('floating_ip', self.floating_ip.id), + ('port', self.floating_ip.port_id), + ('description', self.floating_ip.description), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.cmd.take_action(parsed_args) + + attrs = { + 'port_id': self.floating_ip.port_id, + 'description': self.floating_ip.description, + } + self.network.find_ip.assert_called_once_with( + self.floating_ip.id, + ignore_missing=False, + ) + self.network.update_ip.assert_called_once_with( + self.floating_ip, **attrs) + def test_qos_policy_option(self): qos_policy = network_fakes.FakeNetworkQosPolicy.create_one_qos_policy() self.network.find_qos_policy = mock.Mock(return_value=qos_policy) diff --git a/openstackclient/tests/unit/network/v2/test_floating_ip_pool_compute.py b/openstackclient/tests/unit/network/v2/test_floating_ip_pool_compute.py index 591f58ca..3dd99362 100644 --- a/openstackclient/tests/unit/network/v2/test_floating_ip_pool_compute.py +++ b/openstackclient/tests/unit/network/v2/test_floating_ip_pool_compute.py @@ -11,7 +11,7 @@ # under the License. # -import mock +from unittest import mock from openstackclient.network.v2 import floating_ip_pool from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes diff --git a/openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py b/openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py index b51158be..ea6cdd26 100644 --- a/openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py +++ b/openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py @@ -13,8 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib import exceptions diff --git a/openstackclient/tests/unit/network/v2/test_ip_availability.py b/openstackclient/tests/unit/network/v2/test_ip_availability.py index 21508a8d..9a712704 100644 --- a/openstackclient/tests/unit/network/v2/test_ip_availability.py +++ b/openstackclient/tests/unit/network/v2/test_ip_availability.py @@ -11,7 +11,7 @@ # under the License. # -import mock +from unittest import mock from osc_lib.cli import format_columns diff --git a/openstackclient/tests/unit/network/v2/test_network.py b/openstackclient/tests/unit/network/v2/test_network.py index 5c97c363..45d6008b 100644 --- a/openstackclient/tests/unit/network/v2/test_network.py +++ b/openstackclient/tests/unit/network/v2/test_network.py @@ -12,9 +12,8 @@ # import random - -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib.cli import format_columns from osc_lib import exceptions @@ -279,6 +278,24 @@ class TestCreateNetworkIdentityV3(TestNetwork): def test_create_with_no_tag(self): self._test_create_with_tag(add_tags=False) + def test_create_default_internal(self): + arglist = [ + self._network.name, + "--default", + ] + verifylist = [ + ('name', self._network.name), + ('enable', True), + ('share', None), + ('project', None), + ('external', False), + ('default', True), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.assertRaises(exceptions.CommandError, self.cmd.take_action, + parsed_args) + class TestCreateNetworkIdentityV2(TestNetwork): @@ -1026,6 +1043,21 @@ class TestSetNetwork(TestNetwork): def test_set_with_no_tag(self): self._test_set_tags(with_tags=False) + def test_set_default_internal(self): + arglist = [ + self._network.name, + '--internal', + '--default', + ] + verifylist = [ + ('internal', True), + ('default', True), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.assertRaises(exceptions.CommandError, self.cmd.take_action, + parsed_args) + class TestShowNetwork(TestNetwork): diff --git a/openstackclient/tests/unit/network/v2/test_network_agent.py b/openstackclient/tests/unit/network/v2/test_network_agent.py index 8500d08e..3181ee78 100644 --- a/openstackclient/tests/unit/network/v2/test_network_agent.py +++ b/openstackclient/tests/unit/network/v2/test_network_agent.py @@ -11,8 +11,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib.cli import format_columns from osc_lib import exceptions diff --git a/openstackclient/tests/unit/network/v2/test_network_auto_allocated_topology.py b/openstackclient/tests/unit/network/v2/test_network_auto_allocated_topology.py index 1a231160..e9687a70 100644 --- a/openstackclient/tests/unit/network/v2/test_network_auto_allocated_topology.py +++ b/openstackclient/tests/unit/network/v2/test_network_auto_allocated_topology.py @@ -13,7 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. -import mock +from unittest import mock from openstackclient.network.v2 import network_auto_allocated_topology from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes diff --git a/openstackclient/tests/unit/network/v2/test_network_compute.py b/openstackclient/tests/unit/network/v2/test_network_compute.py index c649401c..89330fff 100644 --- a/openstackclient/tests/unit/network/v2/test_network_compute.py +++ b/openstackclient/tests/unit/network/v2/test_network_compute.py @@ -11,8 +11,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib import exceptions diff --git a/openstackclient/tests/unit/network/v2/test_network_flavor.py b/openstackclient/tests/unit/network/v2/test_network_flavor.py index 896a1725..010f53d3 100644 --- a/openstackclient/tests/unit/network/v2/test_network_flavor.py +++ b/openstackclient/tests/unit/network/v2/test_network_flavor.py @@ -14,7 +14,7 @@ # under the License. # -import mock +from unittest import mock from osc_lib import exceptions diff --git a/openstackclient/tests/unit/network/v2/test_network_flavor_profile.py b/openstackclient/tests/unit/network/v2/test_network_flavor_profile.py index 91683241..fcf24da9 100644 --- a/openstackclient/tests/unit/network/v2/test_network_flavor_profile.py +++ b/openstackclient/tests/unit/network/v2/test_network_flavor_profile.py @@ -10,7 +10,7 @@ # License for the specific language governing permissions and limitations # under the License. -import mock +from unittest import mock from osc_lib import exceptions diff --git a/openstackclient/tests/unit/network/v2/test_network_meter.py b/openstackclient/tests/unit/network/v2/test_network_meter.py index 2b96f7a6..4fadcfe1 100644 --- a/openstackclient/tests/unit/network/v2/test_network_meter.py +++ b/openstackclient/tests/unit/network/v2/test_network_meter.py @@ -13,8 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib import exceptions diff --git a/openstackclient/tests/unit/network/v2/test_network_meter_rule.py b/openstackclient/tests/unit/network/v2/test_network_meter_rule.py index af481793..8f8922c0 100644 --- a/openstackclient/tests/unit/network/v2/test_network_meter_rule.py +++ b/openstackclient/tests/unit/network/v2/test_network_meter_rule.py @@ -13,8 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib import exceptions diff --git a/openstackclient/tests/unit/network/v2/test_network_qos_policy.py b/openstackclient/tests/unit/network/v2/test_network_qos_policy.py index e7239932..d6a78410 100644 --- a/openstackclient/tests/unit/network/v2/test_network_qos_policy.py +++ b/openstackclient/tests/unit/network/v2/test_network_qos_policy.py @@ -13,8 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib import exceptions diff --git a/openstackclient/tests/unit/network/v2/test_network_qos_rule.py b/openstackclient/tests/unit/network/v2/test_network_qos_rule.py index 5b54d318..217e481e 100644 --- a/openstackclient/tests/unit/network/v2/test_network_qos_rule.py +++ b/openstackclient/tests/unit/network/v2/test_network_qos_rule.py @@ -13,7 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. -import mock +from unittest import mock from osc_lib import exceptions diff --git a/openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py b/openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py index 80c52bf7..08a83fab 100644 --- a/openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py +++ b/openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py @@ -13,7 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. -import mock +from unittest import mock from openstackclient.network.v2 import network_qos_rule_type as _qos_rule_type from openstackclient.tests.unit.network.v2 import fakes as network_fakes diff --git a/openstackclient/tests/unit/network/v2/test_network_rbac.py b/openstackclient/tests/unit/network/v2/test_network_rbac.py index 96440091..078188ce 100644 --- a/openstackclient/tests/unit/network/v2/test_network_rbac.py +++ b/openstackclient/tests/unit/network/v2/test_network_rbac.py @@ -11,8 +11,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib import exceptions diff --git a/openstackclient/tests/unit/network/v2/test_network_segment.py b/openstackclient/tests/unit/network/v2/test_network_segment.py index 0639766d..6cd948e3 100644 --- a/openstackclient/tests/unit/network/v2/test_network_segment.py +++ b/openstackclient/tests/unit/network/v2/test_network_segment.py @@ -11,8 +11,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib import exceptions diff --git a/openstackclient/tests/unit/network/v2/test_network_segment_range.py b/openstackclient/tests/unit/network/v2/test_network_segment_range.py index 22e25df1..b60f1710 100644 --- a/openstackclient/tests/unit/network/v2/test_network_segment_range.py +++ b/openstackclient/tests/unit/network/v2/test_network_segment_range.py @@ -14,8 +14,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib import exceptions @@ -24,6 +24,20 @@ from openstackclient.tests.unit.network.v2 import fakes as network_fakes from openstackclient.tests.unit import utils as tests_utils +class TestAuxiliaryFunctions(tests_utils.TestCase): + + def test__get_ranges(self): + input_reference = [ + ([1, 2, 3, 4, 5, 6, 7], ['1-7']), + ([1, 2, 5, 4, 3, 6, 7], ['1-7']), + ([1, 2, 4, 3, 7, 6], ['1-4', '6-7']), + ([1, 2, 4, 3, '13', 12, '7', '6'], ['1-4', '6-7', '12-13']) + ] + for input, reference in input_reference: + self.assertEqual(reference, + list(network_segment_range._get_ranges(input))) + + class TestNetworkSegmentRange(network_fakes.TestNetworkV2): def setUp(self): diff --git a/openstackclient/tests/unit/network/v2/test_network_service_provider.py b/openstackclient/tests/unit/network/v2/test_network_service_provider.py index 5ba85ddb..5e4ddea6 100644 --- a/openstackclient/tests/unit/network/v2/test_network_service_provider.py +++ b/openstackclient/tests/unit/network/v2/test_network_service_provider.py @@ -13,7 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. -import mock +from unittest import mock from openstackclient.network.v2 import network_service_provider \ as service_provider diff --git a/openstackclient/tests/unit/network/v2/test_port.py b/openstackclient/tests/unit/network/v2/test_port.py index c30d682f..b1a18da6 100644 --- a/openstackclient/tests/unit/network/v2/test_port.py +++ b/openstackclient/tests/unit/network/v2/test_port.py @@ -12,9 +12,9 @@ # import argparse +from unittest import mock +from unittest.mock import call -import mock -from mock import call from osc_lib.cli import format_columns from osc_lib import exceptions from osc_lib import utils @@ -61,6 +61,7 @@ class TestPort(network_fakes.TestNetworkV2): 'network_id', 'port_security_enabled', 'project_id', + 'qos_network_policy_id', 'qos_policy_id', 'security_group_ids', 'status', @@ -91,6 +92,7 @@ class TestPort(network_fakes.TestNetworkV2): fake_port.network_id, fake_port.port_security_enabled, fake_port.project_id, + fake_port.qos_network_policy_id, fake_port.qos_policy_id, format_columns.ListColumn(fake_port.security_group_ids), fake_port.status, diff --git a/openstackclient/tests/unit/network/v2/test_router.py b/openstackclient/tests/unit/network/v2/test_router.py index 079b9746..38861b0a 100644 --- a/openstackclient/tests/unit/network/v2/test_router.py +++ b/openstackclient/tests/unit/network/v2/test_router.py @@ -11,8 +11,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib.cli import format_columns from osc_lib import exceptions @@ -1285,6 +1285,24 @@ class TestShowRouter(TestRouter): self.assertNotIn("is_distributed", columns) self.assertNotIn("is_ha", columns) + def test_show_no_extra_route_extension(self): + _router = network_fakes.FakeRouter.create_one_router({'routes': None}) + + arglist = [ + _router.name, + ] + verifylist = [ + ('router', _router.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + with mock.patch.object( + self.network, "find_router", return_value=_router): + columns, data = self.cmd.take_action(parsed_args) + + self.assertIn("routes", columns) + self.assertIsNone(list(data)[columns.index('routes')].human_readable()) + class TestUnsetRouter(TestRouter): diff --git a/openstackclient/tests/unit/network/v2/test_security_group_compute.py b/openstackclient/tests/unit/network/v2/test_security_group_compute.py index df360068..b4ddcf80 100644 --- a/openstackclient/tests/unit/network/v2/test_security_group_compute.py +++ b/openstackclient/tests/unit/network/v2/test_security_group_compute.py @@ -11,8 +11,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib import exceptions diff --git a/openstackclient/tests/unit/network/v2/test_security_group_network.py b/openstackclient/tests/unit/network/v2/test_security_group_network.py index 57698ec5..67908fa8 100644 --- a/openstackclient/tests/unit/network/v2/test_security_group_network.py +++ b/openstackclient/tests/unit/network/v2/test_security_group_network.py @@ -11,8 +11,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib import exceptions @@ -285,7 +285,8 @@ class TestListSecurityGroupNetwork(TestSecurityGroupNetwork): columns, data = self.cmd.take_action(parsed_args) - self.network.security_groups.assert_called_once_with() + self.network.security_groups.assert_called_once_with( + fields=security_group.ListSecurityGroup.FIELDS_TO_RETRIEVE) self.assertEqual(self.columns, columns) self.assertListItemEqual(self.data, list(data)) @@ -300,7 +301,8 @@ class TestListSecurityGroupNetwork(TestSecurityGroupNetwork): columns, data = self.cmd.take_action(parsed_args) - self.network.security_groups.assert_called_once_with() + self.network.security_groups.assert_called_once_with( + fields=security_group.ListSecurityGroup.FIELDS_TO_RETRIEVE) self.assertEqual(self.columns, columns) self.assertListItemEqual(self.data, list(data)) @@ -316,7 +318,9 @@ class TestListSecurityGroupNetwork(TestSecurityGroupNetwork): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - filters = {'tenant_id': project.id, 'project_id': project.id} + filters = { + 'tenant_id': project.id, 'project_id': project.id, + 'fields': security_group.ListSecurityGroup.FIELDS_TO_RETRIEVE} self.network.security_groups.assert_called_once_with(**filters) self.assertEqual(self.columns, columns) @@ -336,7 +340,9 @@ class TestListSecurityGroupNetwork(TestSecurityGroupNetwork): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - filters = {'tenant_id': project.id, 'project_id': project.id} + filters = { + 'tenant_id': project.id, 'project_id': project.id, + 'fields': security_group.ListSecurityGroup.FIELDS_TO_RETRIEVE} self.network.security_groups.assert_called_once_with(**filters) self.assertEqual(self.columns, columns) @@ -362,7 +368,8 @@ class TestListSecurityGroupNetwork(TestSecurityGroupNetwork): **{'tags': 'red,blue', 'any_tags': 'red,green', 'not_tags': 'orange,yellow', - 'not_any_tags': 'black,white'} + 'not_any_tags': 'black,white', + 'fields': security_group.ListSecurityGroup.FIELDS_TO_RETRIEVE} ) self.assertEqual(self.columns, columns) self.assertEqual(self.data, list(data)) diff --git a/openstackclient/tests/unit/network/v2/test_security_group_rule_compute.py b/openstackclient/tests/unit/network/v2/test_security_group_rule_compute.py index cf5261b2..5720e305 100644 --- a/openstackclient/tests/unit/network/v2/test_security_group_rule_compute.py +++ b/openstackclient/tests/unit/network/v2/test_security_group_rule_compute.py @@ -11,8 +11,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib import exceptions diff --git a/openstackclient/tests/unit/network/v2/test_security_group_rule_network.py b/openstackclient/tests/unit/network/v2/test_security_group_rule_network.py index 49c3d5db..0a9522b0 100644 --- a/openstackclient/tests/unit/network/v2/test_security_group_rule_network.py +++ b/openstackclient/tests/unit/network/v2/test_security_group_rule_network.py @@ -11,8 +11,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib import exceptions diff --git a/openstackclient/tests/unit/network/v2/test_subnet.py b/openstackclient/tests/unit/network/v2/test_subnet.py index 9903b042..47d0c6b4 100644 --- a/openstackclient/tests/unit/network/v2/test_subnet.py +++ b/openstackclient/tests/unit/network/v2/test_subnet.py @@ -11,8 +11,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib.cli import format_columns from osc_lib import exceptions @@ -460,6 +460,44 @@ class TestCreateSubnet(TestSubnet): self.assertEqual(self.columns, columns) self.assertItemEqual(self.data, data) + def _test_create_with_dns(self, publish_dns=True): + arglist = [ + "--subnet-range", self._subnet.cidr, + "--network", self._subnet.network_id, + self._subnet.name, + ] + if publish_dns: + arglist += ['--dns-publish-fixed-ip'] + else: + arglist += ['--no-dns-publish-fixed-ip'] + verifylist = [ + ('name', self._subnet.name), + ('subnet_range', self._subnet.cidr), + ('network', self._subnet.network_id), + ('ip_version', self._subnet.ip_version), + ('gateway', 'auto'), + ] + verifylist.append(('dns_publish_fixed_ip', publish_dns)) + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = (self.cmd.take_action(parsed_args)) + + self.network.create_subnet.assert_called_once_with( + cidr=self._subnet.cidr, + ip_version=self._subnet.ip_version, + name=self._subnet.name, + network_id=self._subnet.network_id, + dns_publish_fixed_ip=publish_dns, + ) + self.assertEqual(self.columns, columns) + self.assertItemEqual(self.data, data) + + def test_create_with_dns(self): + self._test_create_with_dns(publish_dns=True) + + def test_create_with_no_dns(self): + self._test_create_with_dns(publish_dns=False) + def _test_create_with_tag(self, add_tags=True): arglist = [ "--subnet-range", self._subnet.cidr, diff --git a/openstackclient/tests/unit/network/v2/test_subnet_pool.py b/openstackclient/tests/unit/network/v2/test_subnet_pool.py index 2271c089..eb454646 100644 --- a/openstackclient/tests/unit/network/v2/test_subnet_pool.py +++ b/openstackclient/tests/unit/network/v2/test_subnet_pool.py @@ -12,9 +12,8 @@ # import argparse - -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib.cli import format_columns from osc_lib import exceptions diff --git a/openstackclient/tests/unit/object/v1/fakes.py b/openstackclient/tests/unit/object/v1/fakes.py index 5d65d106..0ed791a5 100644 --- a/openstackclient/tests/unit/object/v1/fakes.py +++ b/openstackclient/tests/unit/object/v1/fakes.py @@ -13,9 +13,8 @@ # under the License. # -import six - from keystoneauth1 import session +import six from openstackclient.api import object_store_v1 as object_store from openstackclient.tests.unit import utils diff --git a/openstackclient/tests/unit/object/v1/test_container.py b/openstackclient/tests/unit/object/v1/test_container.py index 39e2d80f..7d3cc8d8 100644 --- a/openstackclient/tests/unit/object/v1/test_container.py +++ b/openstackclient/tests/unit/object/v1/test_container.py @@ -14,8 +14,7 @@ # import copy - -import mock +from unittest import mock from openstackclient.api import object_store_v1 as object_store from openstackclient.object.v1 import container diff --git a/openstackclient/tests/unit/object/v1/test_container_all.py b/openstackclient/tests/unit/object/v1/test_container_all.py index 58c90e36..654cfbc7 100644 --- a/openstackclient/tests/unit/object/v1/test_container_all.py +++ b/openstackclient/tests/unit/object/v1/test_container_all.py @@ -70,6 +70,75 @@ class TestContainerCreate(TestContainerAll): )] self.assertEqual(datalist, list(data)) + def test_object_create_container_storage_policy(self): + self.requests_mock.register_uri( + 'PUT', + object_fakes.ENDPOINT + '/ernie', + headers={ + 'x-trans-id': '314159', + 'x-storage-policy': 'o1--sr-r3' + }, + status_code=200, + ) + + arglist = [ + 'ernie', + '--storage-policy', + 'o1--sr-r3' + ] + verifylist = [ + ('containers', ['ernie']), + ('storage_policy', 'o1--sr-r3') + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # In base command class ShowOne in cliff, abstract method take_action() + # returns a two-part tuple with a tuple of column names and a tuple of + # data to be shown. + columns, data = self.cmd.take_action(parsed_args) + + self.assertEqual(self.columns, columns) + datalist = [( + object_fakes.ACCOUNT_ID, + 'ernie', + '314159', + )] + self.assertEqual(datalist, list(data)) + + def test_object_create_container_public(self): + self.requests_mock.register_uri( + 'PUT', + object_fakes.ENDPOINT + '/ernie', + headers={ + 'x-trans-id': '314159', + 'x-container-read': '.r:*,.rlistings' + }, + status_code=200, + ) + + arglist = [ + 'ernie', + '--public' + ] + verifylist = [ + ('containers', ['ernie']), + ('public', True) + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # In base command class ShowOne in cliff, abstract method take_action() + # returns a two-part tuple with a tuple of column names and a tuple of + # data to be shown. + columns, data = self.cmd.take_action(parsed_args) + + self.assertEqual(self.columns, columns) + datalist = [( + object_fakes.ACCOUNT_ID, + 'ernie', + '314159', + )] + self.assertEqual(datalist, list(data)) + def test_object_create_container_more(self): self.requests_mock.register_uri( 'PUT', @@ -300,6 +369,7 @@ class TestContainerShow(TestContainerAll): 'x-container-write': 'wsx', 'x-container-sync-to': 'edc', 'x-container-sync-key': 'rfv', + 'x-storage-policy': 'o1--sr-r3' } self.requests_mock.register_uri( 'HEAD', @@ -327,6 +397,7 @@ class TestContainerShow(TestContainerAll): 'container', 'object_count', 'read_acl', + 'storage_policy', 'sync_key', 'sync_to', 'write_acl', @@ -338,6 +409,7 @@ class TestContainerShow(TestContainerAll): 'ernie', '42', 'qaz', + 'o1--sr-r3', 'rfv', 'edc', 'wsx', diff --git a/openstackclient/tests/unit/object/v1/test_object.py b/openstackclient/tests/unit/object/v1/test_object.py index b6299373..fc3073c8 100644 --- a/openstackclient/tests/unit/object/v1/test_object.py +++ b/openstackclient/tests/unit/object/v1/test_object.py @@ -14,8 +14,7 @@ # import copy - -import mock +from unittest import mock from openstackclient.api import object_store_v1 as object_store from openstackclient.object.v1 import object as obj diff --git a/openstackclient/tests/unit/object/v1/test_object_all.py b/openstackclient/tests/unit/object/v1/test_object_all.py index 08a7534d..dd587142 100644 --- a/openstackclient/tests/unit/object/v1/test_object_all.py +++ b/openstackclient/tests/unit/object/v1/test_object_all.py @@ -12,8 +12,8 @@ # import copy +from unittest import mock -import mock from osc_lib import exceptions from requests_mock.contrib import fixture import six diff --git a/openstackclient/tests/unit/test_shell.py b/openstackclient/tests/unit/test_shell.py index 31675c47..94f4f44d 100644 --- a/openstackclient/tests/unit/test_shell.py +++ b/openstackclient/tests/unit/test_shell.py @@ -15,8 +15,8 @@ import os import sys +from unittest import mock -import mock from osc_lib.tests import utils as osc_lib_test_utils from oslo_utils import importutils import wrapt diff --git a/openstackclient/tests/unit/utils.py b/openstackclient/tests/unit/utils.py index 8df81a50..4f1bc46a 100644 --- a/openstackclient/tests/unit/utils.py +++ b/openstackclient/tests/unit/utils.py @@ -16,12 +16,11 @@ import os +from cliff import columns as cliff_columns import fixtures from six.moves import StringIO import testtools -from cliff import columns as cliff_columns - from openstackclient.tests.unit import fakes diff --git a/openstackclient/tests/unit/volume/test_find_resource.py b/openstackclient/tests/unit/volume/test_find_resource.py index 60591eff..208f55b9 100644 --- a/openstackclient/tests/unit/volume/test_find_resource.py +++ b/openstackclient/tests/unit/volume/test_find_resource.py @@ -13,7 +13,7 @@ # under the License. # -import mock +from unittest import mock from cinderclient.v3 import volume_snapshots from cinderclient.v3 import volumes diff --git a/openstackclient/tests/unit/volume/v1/fakes.py b/openstackclient/tests/unit/volume/v1/fakes.py index de9c724f..adb775ed 100644 --- a/openstackclient/tests/unit/volume/v1/fakes.py +++ b/openstackclient/tests/unit/volume/v1/fakes.py @@ -15,10 +15,9 @@ import copy import random +from unittest import mock import uuid -import mock - from openstackclient.tests.unit import fakes from openstackclient.tests.unit.identity.v2_0 import fakes as identity_fakes from openstackclient.tests.unit import utils diff --git a/openstackclient/tests/unit/volume/v1/test_qos_specs.py b/openstackclient/tests/unit/volume/v1/test_qos_specs.py index 11dc8084..83c533b6 100644 --- a/openstackclient/tests/unit/volume/v1/test_qos_specs.py +++ b/openstackclient/tests/unit/volume/v1/test_qos_specs.py @@ -14,9 +14,8 @@ # import copy - -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib.cli import format_columns from osc_lib import exceptions diff --git a/openstackclient/tests/unit/volume/v1/test_transfer_request.py b/openstackclient/tests/unit/volume/v1/test_transfer_request.py index 680561d5..333bf526 100644 --- a/openstackclient/tests/unit/volume/v1/test_transfer_request.py +++ b/openstackclient/tests/unit/volume/v1/test_transfer_request.py @@ -12,8 +12,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib import exceptions from osc_lib import utils diff --git a/openstackclient/tests/unit/volume/v1/test_type.py b/openstackclient/tests/unit/volume/v1/test_type.py index beff8336..8bee5747 100644 --- a/openstackclient/tests/unit/volume/v1/test_type.py +++ b/openstackclient/tests/unit/volume/v1/test_type.py @@ -12,8 +12,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib.cli import format_columns from osc_lib import exceptions diff --git a/openstackclient/tests/unit/volume/v1/test_volume.py b/openstackclient/tests/unit/volume/v1/test_volume.py index c4154555..25cdf92a 100644 --- a/openstackclient/tests/unit/volume/v1/test_volume.py +++ b/openstackclient/tests/unit/volume/v1/test_volume.py @@ -14,9 +14,8 @@ # import argparse - -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib.cli import format_columns from osc_lib import exceptions diff --git a/openstackclient/tests/unit/volume/v1/test_volume_backup.py b/openstackclient/tests/unit/volume/v1/test_volume_backup.py index 20be6e46..20aadcd3 100644 --- a/openstackclient/tests/unit/volume/v1/test_volume_backup.py +++ b/openstackclient/tests/unit/volume/v1/test_volume_backup.py @@ -12,8 +12,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib import exceptions from osc_lib import utils diff --git a/openstackclient/tests/unit/volume/v2/fakes.py b/openstackclient/tests/unit/volume/v2/fakes.py index 5f976b06..5f18990e 100644 --- a/openstackclient/tests/unit/volume/v2/fakes.py +++ b/openstackclient/tests/unit/volume/v2/fakes.py @@ -14,10 +14,9 @@ import copy import random +from unittest import mock import uuid -import mock - from osc_lib.cli import format_columns from openstackclient.tests.unit import fakes diff --git a/openstackclient/tests/unit/volume/v2/test_consistency_group.py b/openstackclient/tests/unit/volume/v2/test_consistency_group.py index d2388182..c3bd71e3 100644 --- a/openstackclient/tests/unit/volume/v2/test_consistency_group.py +++ b/openstackclient/tests/unit/volume/v2/test_consistency_group.py @@ -12,8 +12,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib.cli import format_columns from osc_lib import exceptions diff --git a/openstackclient/tests/unit/volume/v2/test_consistency_group_snapshot.py b/openstackclient/tests/unit/volume/v2/test_consistency_group_snapshot.py index 3bfe93df..2202b85b 100644 --- a/openstackclient/tests/unit/volume/v2/test_consistency_group_snapshot.py +++ b/openstackclient/tests/unit/volume/v2/test_consistency_group_snapshot.py @@ -12,7 +12,7 @@ # under the License. # -from mock import call +from unittest.mock import call from openstackclient.tests.unit.volume.v2 import fakes as volume_fakes from openstackclient.volume.v2 import consistency_group_snapshot diff --git a/openstackclient/tests/unit/volume/v2/test_qos_specs.py b/openstackclient/tests/unit/volume/v2/test_qos_specs.py index 454747f5..073ec570 100644 --- a/openstackclient/tests/unit/volume/v2/test_qos_specs.py +++ b/openstackclient/tests/unit/volume/v2/test_qos_specs.py @@ -14,9 +14,8 @@ # import copy - -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib.cli import format_columns from osc_lib import exceptions diff --git a/openstackclient/tests/unit/volume/v2/test_transfer_request.py b/openstackclient/tests/unit/volume/v2/test_transfer_request.py index 1ea6648f..c9dce3ca 100644 --- a/openstackclient/tests/unit/volume/v2/test_transfer_request.py +++ b/openstackclient/tests/unit/volume/v2/test_transfer_request.py @@ -12,8 +12,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib import exceptions from osc_lib import utils diff --git a/openstackclient/tests/unit/volume/v2/test_type.py b/openstackclient/tests/unit/volume/v2/test_type.py index 17915928..f13d0851 100644 --- a/openstackclient/tests/unit/volume/v2/test_type.py +++ b/openstackclient/tests/unit/volume/v2/test_type.py @@ -12,8 +12,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib.cli import format_columns from osc_lib import exceptions diff --git a/openstackclient/tests/unit/volume/v2/test_volume.py b/openstackclient/tests/unit/volume/v2/test_volume.py index 332b50a7..5d41b3a1 100644 --- a/openstackclient/tests/unit/volume/v2/test_volume.py +++ b/openstackclient/tests/unit/volume/v2/test_volume.py @@ -13,9 +13,8 @@ # import argparse - -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib.cli import format_columns from osc_lib import exceptions diff --git a/openstackclient/tests/unit/volume/v2/test_volume_backup.py b/openstackclient/tests/unit/volume/v2/test_volume_backup.py index 30c7915d..4e1f7ee1 100644 --- a/openstackclient/tests/unit/volume/v2/test_volume_backup.py +++ b/openstackclient/tests/unit/volume/v2/test_volume_backup.py @@ -12,8 +12,8 @@ # under the License. # -import mock -from mock import call +from unittest import mock +from unittest.mock import call from osc_lib import exceptions from osc_lib import utils diff --git a/openstackclient/volume/client.py b/openstackclient/volume/client.py index fdd1794b..1fbfaaee 100644 --- a/openstackclient/volume/client.py +++ b/openstackclient/volume/client.py @@ -67,11 +67,15 @@ def make_client(instance): # Remember interface only if it is set kwargs = utils.build_kwargs_dict('endpoint_type', instance.interface) + endpoint_override = instance.sdk_connection.config.get_endpoint( + 'block-storage') + client = volume_client( session=instance.session, extensions=extensions, http_log_debug=http_log_debug, region_name=instance.region_name, + endpoint_override=endpoint_override, **kwargs ) diff --git a/openstackclient/volume/v1/qos_specs.py b/openstackclient/volume/v1/qos_specs.py index 0b6a7fa0..79dff1c6 100644 --- a/openstackclient/volume/v1/qos_specs.py +++ b/openstackclient/volume/v1/qos_specs.py @@ -22,7 +22,6 @@ from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -99,7 +98,7 @@ class CreateQos(command.ShowOne): {'properties': format_columns.DictColumn(qos_spec._info.pop('specs'))} ) - return zip(*sorted(six.iteritems(qos_spec._info))) + return zip(*sorted(qos_spec._info.items())) class DeleteQos(command.Command): @@ -273,7 +272,7 @@ class ShowQos(command.ShowOne): {'properties': format_columns.DictColumn(qos_spec._info.pop('specs'))}) - return zip(*sorted(six.iteritems(qos_spec._info))) + return zip(*sorted(qos_spec._info.items())) class UnsetQos(command.Command): diff --git a/openstackclient/volume/v1/volume.py b/openstackclient/volume/v1/volume.py index 36c7ef89..460bd85a 100644 --- a/openstackclient/volume/v1/volume.py +++ b/openstackclient/volume/v1/volume.py @@ -25,7 +25,6 @@ from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -253,7 +252,7 @@ class CreateVolume(command.ShowOne): volume._info, parsed_args.columns, {'display_name': 'name'} ) - return zip(*sorted(six.iteritems(volume_info))) + return zip(*sorted(volume_info.items())) class DeleteVolume(command.Command): @@ -614,7 +613,7 @@ class ShowVolume(command.ShowOne): volume._info, parsed_args.columns, {'display_name': 'name'} ) - return zip(*sorted(six.iteritems(volume_info))) + return zip(*sorted(volume_info.items())) class UnsetVolume(command.Command): diff --git a/openstackclient/volume/v1/volume_backup.py b/openstackclient/volume/v1/volume_backup.py index 2daa23cb..1a83a3c0 100644 --- a/openstackclient/volume/v1/volume_backup.py +++ b/openstackclient/volume/v1/volume_backup.py @@ -23,7 +23,6 @@ from cliff import columns as cliff_columns from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -98,7 +97,7 @@ class CreateVolumeBackup(command.ShowOne): ) backup._info.pop('links') - return zip(*sorted(six.iteritems(backup._info))) + return zip(*sorted(backup._info.items())) class DeleteVolumeBackup(command.Command): @@ -263,4 +262,4 @@ class ShowVolumeBackup(command.ShowOne): backup = utils.find_resource(volume_client.backups, parsed_args.backup) backup._info.pop('links') - return zip(*sorted(six.iteritems(backup._info))) + return zip(*sorted(backup._info.items())) diff --git a/openstackclient/volume/v1/volume_snapshot.py b/openstackclient/volume/v1/volume_snapshot.py index bfe249f5..2d1f0359 100644 --- a/openstackclient/volume/v1/volume_snapshot.py +++ b/openstackclient/volume/v1/volume_snapshot.py @@ -25,7 +25,6 @@ from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -110,7 +109,7 @@ class CreateVolumeSnapshot(command.ShowOne): format_columns.DictColumn(snapshot._info.pop('metadata'))} ) - return zip(*sorted(six.iteritems(snapshot._info))) + return zip(*sorted(snapshot._info.items())) class DeleteVolumeSnapshot(command.Command): @@ -342,7 +341,7 @@ class ShowVolumeSnapshot(command.ShowOne): format_columns.DictColumn(snapshot._info.pop('metadata'))} ) - return zip(*sorted(six.iteritems(snapshot._info))) + return zip(*sorted(snapshot._info.items())) class UnsetVolumeSnapshot(command.Command): diff --git a/openstackclient/volume/v1/volume_transfer_request.py b/openstackclient/volume/v1/volume_transfer_request.py index 6f79658e..971b9ab5 100644 --- a/openstackclient/volume/v1/volume_transfer_request.py +++ b/openstackclient/volume/v1/volume_transfer_request.py @@ -19,7 +19,6 @@ import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -67,7 +66,7 @@ class AcceptTransferRequest(command.ShowOne): ) transfer_accept._info.pop("links", None) - return zip(*sorted(six.iteritems(transfer_accept._info))) + return zip(*sorted(transfer_accept._info.items())) class CreateTransferRequest(command.ShowOne): @@ -99,7 +98,7 @@ class CreateTransferRequest(command.ShowOne): ) volume_transfer_request._info.pop("links", None) - return zip(*sorted(six.iteritems(volume_transfer_request._info))) + return zip(*sorted(volume_transfer_request._info.items())) class DeleteTransferRequest(command.Command): @@ -189,4 +188,4 @@ class ShowTransferRequest(command.ShowOne): ) volume_transfer_request._info.pop("links", None) - return zip(*sorted(six.iteritems(volume_transfer_request._info))) + return zip(*sorted(volume_transfer_request._info.items())) diff --git a/openstackclient/volume/v1/volume_type.py b/openstackclient/volume/v1/volume_type.py index e744e92f..4f015d13 100644 --- a/openstackclient/volume/v1/volume_type.py +++ b/openstackclient/volume/v1/volume_type.py @@ -24,7 +24,6 @@ from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -162,7 +161,7 @@ class CreateVolumeType(command.ShowOne): {'encryption': format_columns.DictColumn(encryption._info)}) volume_type._info.pop("os-volume-type-access:is_public", None) - return zip(*sorted(six.iteritems(volume_type._info))) + return zip(*sorted(volume_type._info.items())) class DeleteVolumeType(command.Command): @@ -388,7 +387,7 @@ class ShowVolumeType(command.ShowOne): LOG.error(_("Failed to display the encryption information " "of this volume type: %s"), e) volume_type._info.pop("os-volume-type-access:is_public", None) - return zip(*sorted(six.iteritems(volume_type._info))) + return zip(*sorted(volume_type._info.items())) class UnsetVolumeType(command.Command): diff --git a/openstackclient/volume/v2/backup_record.py b/openstackclient/volume/v2/backup_record.py index f4918032..64ff4f67 100644 --- a/openstackclient/volume/v2/backup_record.py +++ b/openstackclient/volume/v2/backup_record.py @@ -18,7 +18,6 @@ import logging from osc_lib.command import command from osc_lib import utils -import six from openstackclient.i18n import _ @@ -51,7 +50,7 @@ class ExportBackupRecord(command.ShowOne): backup_data['Backup Service'] = backup_data.pop('backup_service') backup_data['Metadata'] = backup_data.pop('backup_url') - return zip(*sorted(six.iteritems(backup_data))) + return zip(*sorted(backup_data.items())) class ImportBackupRecord(command.ShowOne): @@ -79,4 +78,4 @@ class ImportBackupRecord(command.ShowOne): parsed_args.backup_service, parsed_args.backup_metadata) backup_data.pop('links', None) - return zip(*sorted(six.iteritems(backup_data))) + return zip(*sorted(backup_data.items())) diff --git a/openstackclient/volume/v2/consistency_group.py b/openstackclient/volume/v2/consistency_group.py index 26dd8ffc..c50a1b5b 100644 --- a/openstackclient/volume/v2/consistency_group.py +++ b/openstackclient/volume/v2/consistency_group.py @@ -20,7 +20,6 @@ from osc_lib.cli import format_columns from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -161,7 +160,7 @@ class CreateConsistencyGroup(command.ShowOne): ) ) - return zip(*sorted(six.iteritems(consistency_group._info))) + return zip(*sorted(consistency_group._info.items())) class DeleteConsistencyGroup(command.Command): @@ -335,4 +334,4 @@ class ShowConsistencyGroup(command.ShowOne): consistency_group = utils.find_resource( volume_client.consistencygroups, parsed_args.consistency_group) - return zip(*sorted(six.iteritems(consistency_group._info))) + return zip(*sorted(consistency_group._info.items())) diff --git a/openstackclient/volume/v2/consistency_group_snapshot.py b/openstackclient/volume/v2/consistency_group_snapshot.py index 3cba4eca..7d5ba82f 100644 --- a/openstackclient/volume/v2/consistency_group_snapshot.py +++ b/openstackclient/volume/v2/consistency_group_snapshot.py @@ -19,7 +19,6 @@ import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -68,7 +67,7 @@ class CreateConsistencyGroupSnapshot(command.ShowOne): description=parsed_args.description, ) - return zip(*sorted(six.iteritems(consistency_group_snapshot._info))) + return zip(*sorted(consistency_group_snapshot._info.items())) class DeleteConsistencyGroupSnapshot(command.Command): @@ -187,4 +186,4 @@ class ShowConsistencyGroupSnapshot(command.ShowOne): consistency_group_snapshot = utils.find_resource( volume_client.cgsnapshots, parsed_args.consistency_group_snapshot) - return zip(*sorted(six.iteritems(consistency_group_snapshot._info))) + return zip(*sorted(consistency_group_snapshot._info.items())) diff --git a/openstackclient/volume/v2/qos_specs.py b/openstackclient/volume/v2/qos_specs.py index 3037d34a..e6e6b9f8 100644 --- a/openstackclient/volume/v2/qos_specs.py +++ b/openstackclient/volume/v2/qos_specs.py @@ -22,7 +22,6 @@ from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -100,7 +99,7 @@ class CreateQos(command.ShowOne): {'properties': format_columns.DictColumn(qos_spec._info.pop('specs'))} ) - return zip(*sorted(six.iteritems(qos_spec._info))) + return zip(*sorted(qos_spec._info.items())) class DeleteQos(command.Command): @@ -275,7 +274,7 @@ class ShowQos(command.ShowOne): {'properties': format_columns.DictColumn(qos_spec._info.pop('specs'))}) - return zip(*sorted(six.iteritems(qos_spec._info))) + return zip(*sorted(qos_spec._info.items())) class UnsetQos(command.Command): diff --git a/openstackclient/volume/v2/volume.py b/openstackclient/volume/v2/volume.py index 17ccd3d3..4dde1340 100644 --- a/openstackclient/volume/v2/volume.py +++ b/openstackclient/volume/v2/volume.py @@ -25,7 +25,6 @@ from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common as identity_common @@ -252,7 +251,7 @@ class CreateVolume(command.ShowOne): } ) volume._info.pop("links", None) - return zip(*sorted(six.iteritems(volume._info))) + return zip(*sorted(volume._info.items())) class DeleteVolume(command.Command): @@ -751,7 +750,7 @@ class ShowVolume(command.ShowOne): # Remove key links from being displayed volume._info.pop("links", None) - return zip(*sorted(six.iteritems(volume._info))) + return zip(*sorted(volume._info.items())) class UnsetVolume(command.Command): diff --git a/openstackclient/volume/v2/volume_backup.py b/openstackclient/volume/v2/volume_backup.py index 4d0d54c1..c336f6c9 100644 --- a/openstackclient/volume/v2/volume_backup.py +++ b/openstackclient/volume/v2/volume_backup.py @@ -23,7 +23,6 @@ from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -120,7 +119,7 @@ class CreateVolumeBackup(command.ShowOne): snapshot_id=snapshot_id, ) backup._info.pop("links", None) - return zip(*sorted(six.iteritems(backup._info))) + return zip(*sorted(backup._info.items())) class DeleteVolumeBackup(command.Command): @@ -289,7 +288,7 @@ class RestoreVolumeBackup(command.ShowOne): parsed_args.volume) backup = volume_client.restores.restore(backup.id, destination_volume.id) - return zip(*sorted(six.iteritems(backup._info))) + return zip(*sorted(backup._info.items())) class SetVolumeBackup(command.Command): @@ -371,4 +370,4 @@ class ShowVolumeBackup(command.ShowOne): backup = utils.find_resource(volume_client.backups, parsed_args.backup) backup._info.pop("links", None) - return zip(*sorted(six.iteritems(backup._info))) + return zip(*sorted(backup._info.items())) diff --git a/openstackclient/volume/v2/volume_snapshot.py b/openstackclient/volume/v2/volume_snapshot.py index 6cbd1156..656f59d4 100644 --- a/openstackclient/volume/v2/volume_snapshot.py +++ b/openstackclient/volume/v2/volume_snapshot.py @@ -24,7 +24,6 @@ from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common as identity_common @@ -140,7 +139,7 @@ class CreateVolumeSnapshot(command.ShowOne): {'properties': format_columns.DictColumn(snapshot._info.pop('metadata'))} ) - return zip(*sorted(six.iteritems(snapshot._info))) + return zip(*sorted(snapshot._info.items())) class DeleteVolumeSnapshot(command.Command): @@ -426,7 +425,7 @@ class ShowVolumeSnapshot(command.ShowOne): {'properties': format_columns.DictColumn(snapshot._info.pop('metadata'))} ) - return zip(*sorted(six.iteritems(snapshot._info))) + return zip(*sorted(snapshot._info.items())) class UnsetVolumeSnapshot(command.Command): diff --git a/openstackclient/volume/v2/volume_transfer_request.py b/openstackclient/volume/v2/volume_transfer_request.py index 4c4741bc..2a1ace1f 100644 --- a/openstackclient/volume/v2/volume_transfer_request.py +++ b/openstackclient/volume/v2/volume_transfer_request.py @@ -19,7 +19,6 @@ import logging from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ @@ -64,7 +63,7 @@ class AcceptTransferRequest(command.ShowOne): ) transfer_accept._info.pop("links", None) - return zip(*sorted(six.iteritems(transfer_accept._info))) + return zip(*sorted(transfer_accept._info.items())) class CreateTransferRequest(command.ShowOne): @@ -96,7 +95,7 @@ class CreateTransferRequest(command.ShowOne): ) volume_transfer_request._info.pop("links", None) - return zip(*sorted(six.iteritems(volume_transfer_request._info))) + return zip(*sorted(volume_transfer_request._info.items())) class DeleteTransferRequest(command.Command): @@ -186,4 +185,4 @@ class ShowTransferRequest(command.ShowOne): ) volume_transfer_request._info.pop("links", None) - return zip(*sorted(six.iteritems(volume_transfer_request._info))) + return zip(*sorted(volume_transfer_request._info.items())) diff --git a/openstackclient/volume/v2/volume_type.py b/openstackclient/volume/v2/volume_type.py index 54b1f497..483e6dd3 100644 --- a/openstackclient/volume/v2/volume_type.py +++ b/openstackclient/volume/v2/volume_type.py @@ -23,7 +23,6 @@ from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils -import six from openstackclient.i18n import _ from openstackclient.identity import common as identity_common @@ -235,7 +234,7 @@ class CreateVolumeType(command.ShowOne): {'encryption': format_columns.DictColumn(encryption._info)}) volume_type._info.pop("os-volume-type-access:is_public", None) - return zip(*sorted(six.iteritems(volume_type._info))) + return zip(*sorted(volume_type._info.items())) class DeleteVolumeType(command.Command): @@ -553,7 +552,7 @@ class ShowVolumeType(command.ShowOne): LOG.error(_("Failed to display the encryption information " "of this volume type: %s"), e) volume_type._info.pop("os-volume-type-access:is_public", None) - return zip(*sorted(six.iteritems(volume_type._info))) + return zip(*sorted(volume_type._info.items())) class UnsetVolumeType(command.Command): |
