diff options
Diffstat (limited to 'openstackclient')
35 files changed, 456 insertions, 322 deletions
diff --git a/openstackclient/common/clientmanager.py b/openstackclient/common/clientmanager.py index bcb81990..928ab6ee 100644 --- a/openstackclient/common/clientmanager.py +++ b/openstackclient/common/clientmanager.py @@ -29,6 +29,8 @@ from openstackclient.identity import client as identity_client LOG = logging.getLogger(__name__) +PLUGIN_MODULES = [] + class ClientCache(object): """Descriptor class for caching created client handles.""" @@ -109,24 +111,26 @@ class ClientManager(object): return - def get_endpoint_for_service_type(self, service_type): + def get_endpoint_for_service_type(self, service_type, region_name=None): """Return the endpoint URL for the service type.""" # See if we are using password flow auth, i.e. we have a # service catalog to select endpoints from if self._service_catalog: endpoint = self._service_catalog.url_for( - service_type=service_type) + service_type=service_type, region_name=region_name) else: # Hope we were given the correct URL. endpoint = self._auth_url or self._url return endpoint -def get_extension_modules(group): - """Add extension clients""" +# Plugin Support + +def get_plugin_modules(group): + """Find plugin entry points""" mod_list = [] for ep in pkg_resources.iter_entry_points(group): - LOG.debug('found extension %r', ep.name) + LOG.debug('Found plugin %r', ep.name) __import__(ep.module_name) module = sys.modules[ep.module_name] @@ -135,6 +139,7 @@ def get_extension_modules(group): if init_func: init_func('x') + # Add the plugin to the ClientManager setattr( ClientManager, module.API_NAME, @@ -143,3 +148,22 @@ def get_extension_modules(group): ), ) return mod_list + + +def build_plugin_option_parser(parser): + """Add plugin options to the parser""" + + # Loop through extensions to get parser additions + for mod in PLUGIN_MODULES: + parser = mod.build_option_parser(parser) + return parser + + +# Get list of base plugin modules +PLUGIN_MODULES = get_plugin_modules( + 'openstack.cli.base', +) +# Append list of external plugin modules +PLUGIN_MODULES.extend(get_plugin_modules( + 'openstack.cli.extension', +)) diff --git a/openstackclient/common/commandmanager.py b/openstackclient/common/commandmanager.py index 9901ea20..2d9575d9 100644 --- a/openstackclient/common/commandmanager.py +++ b/openstackclient/common/commandmanager.py @@ -16,6 +16,7 @@ """Modify cliff.CommandManager""" import logging +import pkg_resources import cliff.commandmanager @@ -46,3 +47,17 @@ class CommandManager(cliff.commandmanager.CommandManager): def get_command_groups(self): """Returns a list of the loaded command groups""" return self.group_list + + def get_command_names(self, group=None): + """Returns a list of commands loaded for the specified group""" + group_list = [] + if group is not None: + for ep in pkg_resources.iter_entry_points(group): + cmd_name = ( + ep.name.replace('_', ' ') + if self.convert_underscores + else ep.name + ) + group_list.append(cmd_name) + return group_list + return self.commands.keys() diff --git a/openstackclient/common/module.py b/openstackclient/common/module.py index 7f9c52db..356cdca3 100644 --- a/openstackclient/common/module.py +++ b/openstackclient/common/module.py @@ -19,9 +19,25 @@ import logging import six import sys +from cliff import lister from cliff import show +class ListCommand(lister.Lister): + """List recognized commands by group""" + + auth_required = False + log = logging.getLogger(__name__ + '.ListCommand') + + def take_action(self, parsed_args): + self.log.debug('take_action(%s)', parsed_args) + cm = self.app.command_manager + groups = cm.get_command_groups() + + columns = ('Command Group', 'Commands') + return (columns, ((c, cm.get_command_names(group=c)) for c in groups)) + + class ListModule(show.ShowOne): """List module versions""" diff --git a/openstackclient/common/utils.py b/openstackclient/common/utils.py index 818f8d47..9ad3823c 100644 --- a/openstackclient/common/utils.py +++ b/openstackclient/common/utils.py @@ -26,8 +26,27 @@ from oslo.utils import importutils from openstackclient.common import exceptions -def find_resource(manager, name_or_id): - """Helper for the _find_* methods.""" +def find_resource(manager, name_or_id, **kwargs): + """Helper for the _find_* methods. + + :param manager: A client manager class + :param name_or_id: The resource we are trying to find + :param kwargs: To be used in calling .find() + :rtype: The found resource + + This method will attempt to find a resource in a variety of ways. + Primarily .get() methods will be called with `name_or_id` as an integer + value, and tried again as a string value. + + If both fail, then a .find() is attempted, which is essentially calling + a .list() function with a 'name' query parameter that is set to + `name_or_id`. + + Lastly, if any kwargs are passed in, they will be treated as additional + query parameters. This is particularly handy in the case of finding + resources in a domain. + + """ # Try to get entity as integer id try: @@ -49,7 +68,10 @@ def find_resource(manager, name_or_id): except Exception: pass - kwargs = {} + if len(kwargs) == 0: + kwargs = {} + + # Prepare the kwargs for calling find if 'NAME_ATTR' in manager.resource_class.__dict__: # novaclient does this for oddball resources kwargs[manager.resource_class.NAME_ATTR] = name_or_id diff --git a/openstackclient/compute/client.py b/openstackclient/compute/client.py index 6c03d24e..ff9ed88a 100644 --- a/openstackclient/compute/client.py +++ b/openstackclient/compute/client.py @@ -54,7 +54,7 @@ def make_client(instance): if 'token' not in instance._auth_params: # password flow client.client.management_url = instance.get_endpoint_for_service_type( - API_NAME) + API_NAME, region_name=instance._region_name) client.client.service_catalog = instance._service_catalog client.client.auth_token = instance.auth.get_token(instance.session) diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py index ec7f212d..355774c3 100644 --- a/openstackclient/compute/v2/server.py +++ b/openstackclient/compute/v2/server.py @@ -25,11 +25,12 @@ import sys from cliff import command from cliff import lister from cliff import show - from novaclient.v1_1 import servers + from openstackclient.common import exceptions from openstackclient.common import parseractions from openstackclient.common import utils +from openstackclient.i18n import _ # noqa def _format_servers_list_networks(networks): @@ -106,17 +107,17 @@ class AddServerVolume(command.Command): parser.add_argument( 'server', metavar='<server>', - help='Server (name or ID)', + help=_('Server (name or ID)'), ) parser.add_argument( 'volume', metavar='<volume>', - help='Volume to add (name or ID)', + help=_('Volume to add (name or ID)'), ) parser.add_argument( '--device', metavar='<device>', - help='Server internal device name for volume', + help=_('Server internal device name for volume'), ) return parser @@ -152,12 +153,12 @@ class AddServerSecurityGroup(command.Command): parser.add_argument( 'server', metavar='<server>', - help='Name or ID of server to use', + help=_('Name or ID of server to use'), ) parser.add_argument( 'group', metavar='<group>', - help='Name or ID of security group to add to server', + help=_('Name or ID of security group to add to server'), ) return parser @@ -189,91 +190,91 @@ class CreateServer(show.ShowOne): parser.add_argument( 'server_name', metavar='<server-name>', - help='New server name') + help=_('New server name')) parser.add_argument( '--image', metavar='<image>', required=True, - help='Create server from this image') + help=_('Create server from this image')) parser.add_argument( '--flavor', metavar='<flavor>', required=True, - help='Create server with this flavor') + help=_('Create server with this flavor')) parser.add_argument( '--security-group', metavar='<security-group-name>', action='append', default=[], - help='Security group to assign to this server ' - '(repeat for multiple groups)') + help=_('Security group to assign to this server ' + '(repeat for multiple groups)')) parser.add_argument( '--key-name', metavar='<key-name>', - help='Keypair to inject into this server (optional extension)') + help=_('Keypair to inject into this server (optional extension)')) parser.add_argument( '--property', metavar='<key=value>', action=parseractions.KeyValueAction, - help='Set a property on this server ' - '(repeat for multiple values)') + help=_('Set a property on this server ' + '(repeat for multiple values)')) parser.add_argument( '--file', metavar='<dest-filename=source-filename>', action='append', default=[], - help='File to inject into image before boot ' - '(repeat for multiple files)') + help=_('File to inject into image before boot ' + '(repeat for multiple files)')) parser.add_argument( '--user-data', metavar='<user-data>', - help='User data file to serve from the metadata server') + help=_('User data file to serve from the metadata server')) parser.add_argument( '--availability-zone', metavar='<zone-name>', - help='Select an availability zone for the server') + help=_('Select an availability zone for the server')) parser.add_argument( '--block-device-mapping', metavar='<dev-name=mapping>', action='append', default=[], - help='Map block devices; map is ' - '<id>:<type>:<size(GB)>:<delete_on_terminate> ' - '(optional extension)') + help=_('Map block devices; map is ' + '<id>:<type>:<size(GB)>:<delete_on_terminate> ' + '(optional extension)')) parser.add_argument( '--nic', metavar='<nic-config-string>', action='append', default=[], - help='Specify NIC configuration (optional extension)') + help=_('Specify NIC configuration (optional extension)')) parser.add_argument( '--hint', metavar='<key=value>', action='append', default=[], - help='Hints for the scheduler (optional extension)') + help=_('Hints for the scheduler (optional extension)')) parser.add_argument( '--config-drive', metavar='<config-drive-volume>|True', default=False, - help='Use specified volume as the config drive, ' - 'or \'True\' to use an ephemeral drive') + help=_('Use specified volume as the config drive, ' + 'or \'True\' to use an ephemeral drive')) parser.add_argument( '--min', metavar='<count>', type=int, default=1, - help='Minimum number of servers to launch (default=1)') + help=_('Minimum number of servers to launch (default=1)')) parser.add_argument( '--max', metavar='<count>', type=int, default=1, - help='Maximum number of servers to launch (default=1)') + help=_('Maximum number of servers to launch (default=1)')) parser.add_argument( '--wait', action='store_true', - help='Wait for build to complete', + help=_('Wait for build to complete'), ) return parser @@ -300,13 +301,13 @@ class CreateServer(show.ShowOne): raise exceptions.CommandError("Can't open '%s': %s" % (src, e)) if parsed_args.min > parsed_args.max: - msg = "min instances should be <= max instances" + msg = _("min instances should be <= max instances") raise exceptions.CommandError(msg) if parsed_args.min < 1: - msg = "min instances should be > 0" + msg = _("min instances should be > 0") raise exceptions.CommandError(msg) if parsed_args.max < 1: - msg = "max instances should be > 0" + msg = _("max instances should be > 0") raise exceptions.CommandError(msg) userdata = None @@ -315,8 +316,7 @@ class CreateServer(show.ShowOne): userdata = open(parsed_args.user_data) except IOError as e: msg = "Can't open '%s': %s" - raise exceptions.CommandError(msg % - (parsed_args.user_data, e)) + raise exceptions.CommandError(msg % (parsed_args.user_data, e)) block_device_mapping = dict(v.split('=', 1) for v in parsed_args.block_device_mapping) @@ -378,9 +378,9 @@ class CreateServer(show.ShowOne): ): sys.stdout.write('\n') else: - self.log.error('Error creating server: %s', + self.log.error(_('Error creating server: %s'), parsed_args.server_name) - sys.stdout.write('\nError creating server') + sys.stdout.write(_('\nError creating server')) raise SystemExit details = _prep_server_detail(compute_client, server) @@ -397,17 +397,17 @@ class CreateServerImage(show.ShowOne): parser.add_argument( 'server', metavar='<server>', - help='Server (name or ID)', + help=_('Server (name or ID)'), ) parser.add_argument( '--name', metavar='<image-name>', - help='Name of new image (default is server name)', + help=_('Name of new image (default is server name)'), ) parser.add_argument( '--wait', action='store_true', - help='Wait for image create to complete', + help=_('Wait for image create to complete'), ) return parser @@ -437,11 +437,9 @@ class CreateServerImage(show.ShowOne): ): sys.stdout.write('\n') else: - self.log.error( - 'Error creating server snapshot: %s', - parsed_args.image_name, - ) - sys.stdout.write('\nError creating server snapshot') + self.log.error(_('Error creating server snapshot: %s'), + parsed_args.image_name) + sys.stdout.write(_('\nError creating server snapshot')) raise SystemExit image = utils.find_resource( @@ -449,9 +447,7 @@ class CreateServerImage(show.ShowOne): image_id, ) - info = {} - info.update(image._info) - return zip(*sorted(six.iteritems(info))) + return zip(*sorted(six.iteritems(image._info))) class DeleteServer(command.Command): @@ -464,7 +460,7 @@ class DeleteServer(command.Command): parser.add_argument( 'server', metavar='<server>', - help='Name or ID of server to delete') + help=_('Name or ID of server to delete')) return parser def take_action(self, parsed_args): @@ -486,50 +482,50 @@ class ListServer(lister.Lister): parser.add_argument( '--reservation-id', metavar='<reservation-id>', - help='Only return instances that match the reservation') + help=_('Only return instances that match the reservation')) parser.add_argument( '--ip', metavar='<ip-address-regex>', - help='Regular expression to match IP addresses') + help=_('Regular expression to match IP addresses')) parser.add_argument( '--ip6', metavar='<ip-address-regex>', - help='Regular expression to match IPv6 addresses') + help=_('Regular expression to match IPv6 addresses')) parser.add_argument( '--name', metavar='<name>', - help='Regular expression to match names') + help=_('Regular expression to match names')) parser.add_argument( '--status', metavar='<status>', # FIXME(dhellmann): Add choices? - help='Search by server status') + help=_('Search by server status')) parser.add_argument( '--flavor', metavar='<flavor>', - help='Search by flavor ID') + help=_('Search by flavor ID')) parser.add_argument( '--image', metavar='<image>', - help='Search by image ID') + help=_('Search by image ID')) parser.add_argument( '--host', metavar='<hostname>', - help='Search by hostname') + help=_('Search by hostname')) parser.add_argument( '--instance-name', metavar='<server-name>', - help='Regular expression to match instance name (admin only)') + help=_('Regular expression to match instance name (admin only)')) parser.add_argument( '--all-projects', action='store_true', default=bool(int(os.environ.get("ALL_PROJECTS", 0))), - help='Include all projects (admin only)') + help=_('Include all projects (admin only)')) parser.add_argument( '--long', action='store_true', default=False, - help='List additional fields in output') + help=_('List additional fields in output')) return parser def take_action(self, parsed_args): @@ -598,7 +594,7 @@ class LockServer(command.Command): parser.add_argument( 'server', metavar='<server>', - help='Server (name or ID)', + help=_('Server (name or ID)'), ) return parser @@ -632,17 +628,17 @@ class MigrateServer(command.Command): parser.add_argument( 'server', metavar='<server>', - help='Server to migrate (name or ID)', + help=_('Server to migrate (name or ID)'), ) parser.add_argument( '--wait', action='store_true', - help='Wait for resize to complete', + help=_('Wait for resize to complete'), ) parser.add_argument( '--live', metavar='<hostname>', - help='Target hostname', + help=_('Target hostname'), ) migration_group = parser.add_mutually_exclusive_group() migration_group.add_argument( @@ -650,13 +646,13 @@ class MigrateServer(command.Command): dest='shared_migration', action='store_true', default=True, - help='Perform a shared live migration (default)', + help=_('Perform a shared live migration (default)'), ) migration_group.add_argument( '--block-migration', dest='shared_migration', action='store_false', - help='Perform a block live migration', + help=_('Perform a block live migration'), ) disk_group = parser.add_mutually_exclusive_group() disk_group.add_argument( @@ -664,13 +660,14 @@ class MigrateServer(command.Command): dest='disk_overcommit', action='store_false', default=False, - help='Do not over-commit disk on the destination host (default)', + help=_('Do not over-commit disk on the' + ' destination host (default)'), ) disk_group.add_argument( '--disk-overcommit', action='store_true', default=False, - help='Allow disk over-commit on the destination host', + help=_('Allow disk over-commit on the destination host'), ) return parser @@ -698,9 +695,9 @@ class MigrateServer(command.Command): server.id, callback=_show_progress, ): - sys.stdout.write('Complete\n') + sys.stdout.write(_('Complete\n')) else: - sys.stdout.write('\nError migrating server') + sys.stdout.write(_('\nError migrating server')) raise SystemExit @@ -714,7 +711,7 @@ class PauseServer(command.Command): parser.add_argument( 'server', metavar='<server>', - help='Server (name or ID)', + help=_('Server (name or ID)'), ) return parser @@ -738,7 +735,7 @@ class RebootServer(command.Command): parser.add_argument( 'server', metavar='<server>', - help='Server (name or ID)', + help=_('Server (name or ID)'), ) group = parser.add_mutually_exclusive_group() group.add_argument( @@ -747,7 +744,7 @@ class RebootServer(command.Command): action='store_const', const=servers.REBOOT_HARD, default=servers.REBOOT_SOFT, - help='Perform a hard reboot', + help=_('Perform a hard reboot'), ) group.add_argument( '--soft', @@ -755,12 +752,12 @@ class RebootServer(command.Command): action='store_const', const=servers.REBOOT_SOFT, default=servers.REBOOT_SOFT, - help='Perform a soft reboot', + help=_('Perform a soft reboot'), ) parser.add_argument( '--wait', action='store_true', - help='Wait for reboot to complete', + help=_('Wait for reboot to complete'), ) return parser @@ -777,9 +774,9 @@ class RebootServer(command.Command): server.id, callback=_show_progress, ): - sys.stdout.write('\nReboot complete\n') + sys.stdout.write(_('\nReboot complete\n')) else: - sys.stdout.write('\nError rebooting server\n') + sys.stdout.write(_('\nError rebooting server\n')) raise SystemExit @@ -793,13 +790,13 @@ class RebuildServer(show.ShowOne): parser.add_argument( 'server', metavar='<server>', - help='Server (name or ID)', + help=_('Server (name or ID)'), ) parser.add_argument( '--image', metavar='<image>', required=True, - help='Recreate server from this image', + help=_('Recreate server from this image'), ) parser.add_argument( '--password', @@ -809,7 +806,7 @@ class RebuildServer(show.ShowOne): parser.add_argument( '--wait', action='store_true', - help='Wait for rebuild to complete', + help=_('Wait for rebuild to complete'), ) return parser @@ -830,9 +827,9 @@ class RebuildServer(show.ShowOne): server.id, callback=_show_progress, ): - sys.stdout.write('\nComplete\n') + sys.stdout.write(_('\nComplete\n')) else: - sys.stdout.write('\nError rebuilding server') + sys.stdout.write(_('\nError rebuilding server')) raise SystemExit details = _prep_server_detail(compute_client, server) @@ -849,12 +846,12 @@ class RemoveServerSecurityGroup(command.Command): parser.add_argument( 'server', metavar='<server>', - help='Name or ID of server to use', + help=_('Name or ID of server to use'), ) parser.add_argument( 'group', metavar='<group>', - help='Name or ID of security group to remove from server', + help=_('Name or ID of security group to remove from server'), ) return parser @@ -885,12 +882,12 @@ class RemoveServerVolume(command.Command): parser.add_argument( 'server', metavar='<server>', - help='Server (name or ID)', + help=_('Server (name or ID)'), ) parser.add_argument( 'volume', metavar='<volume>', - help='Volume to remove (name or ID)', + help=_('Volume to remove (name or ID)'), ) return parser @@ -925,7 +922,7 @@ class RescueServer(show.ShowOne): parser.add_argument( 'server', metavar='<server>', - help='Server (name or ID)', + help=_('Server (name or ID)'), ) return parser @@ -951,27 +948,27 @@ class ResizeServer(command.Command): parser.add_argument( 'server', metavar='<server>', - help='Server (name or ID)', + help=_('Server (name or ID)'), ) phase_group.add_argument( '--flavor', metavar='<flavor>', - help='Resize server to specified flavor', + help=_('Resize server to specified flavor'), ) phase_group.add_argument( '--verify', action="store_true", - help='Verify server resize is complete', + help=_('Verify server resize is complete'), ) phase_group.add_argument( '--revert', action="store_true", - help='Restore server state before resize', + help=_('Restore server state before resize'), ) parser.add_argument( '--wait', action='store_true', - help='Wait for resize to complete', + help=_('Wait for resize to complete'), ) return parser @@ -996,9 +993,9 @@ class ResizeServer(command.Command): success_status=['active', 'verify_resize'], callback=_show_progress, ): - sys.stdout.write('Complete\n') + sys.stdout.write(_('Complete\n')) else: - sys.stdout.write('\nError resizing server') + sys.stdout.write(_('\nError resizing server')) raise SystemExit elif parsed_args.verify: compute_client.servers.confirm_resize(server) @@ -1016,7 +1013,7 @@ class ResumeServer(command.Command): parser.add_argument( 'server', metavar='<server>', - help='Server (name or ID)', + help=_('Server (name or ID)'), ) return parser @@ -1040,24 +1037,24 @@ class SetServer(command.Command): parser.add_argument( 'server', metavar='<server>', - help='Server (name or ID)', + help=_('Server (name or ID)'), ) parser.add_argument( '--name', metavar='<new-name>', - help='New server name', + help=_('New server name'), ) parser.add_argument( '--root-password', action="store_true", - help='Set new root password (interactive only)', + help=_('Set new root password (interactive only)'), ) parser.add_argument( "--property", metavar="<key=value>", action=parseractions.KeyValueAction, - help='Property to add/change for this server ' - '(repeat option to set multiple properties)', + help=_('Property to add/change for this server ' + '(repeat option to set multiple properties)'), ) return parser @@ -1080,12 +1077,12 @@ class SetServer(command.Command): ) if parsed_args.root_password: - p1 = getpass.getpass('New password: ') - p2 = getpass.getpass('Retype new password: ') + p1 = getpass.getpass(_('New password: ')) + p2 = getpass.getpass(_('Retype new password: ')) if p1 == p2: server.change_password(p1) else: - msg = "Passwords do not match, password unchanged" + msg = _("Passwords do not match, password unchanged") raise exceptions.CommandError(msg) @@ -1099,13 +1096,13 @@ class ShowServer(show.ShowOne): parser.add_argument( 'server', metavar='<server>', - help='Server to show (name or ID)', + help=_('Server to show (name or ID)'), ) parser.add_argument( '--diagnostics', action='store_true', default=False, - help='Display diagnostics information for a given server', + help=_('Display diagnostics information for a given server'), ) return parser @@ -1118,7 +1115,7 @@ class ShowServer(show.ShowOne): if parsed_args.diagnostics: (resp, data) = server.diagnostics() if not resp.status_code == 200: - sys.stderr.write("Error retrieving diagnostics data") + sys.stderr.write(_("Error retrieving diagnostics data")) return ({}, {}) else: data = _prep_server_detail(compute_client, server) @@ -1136,12 +1133,12 @@ class SshServer(command.Command): parser.add_argument( 'server', metavar='<server>', - help='Server (name or ID)', + help=_('Server (name or ID)'), ) parser.add_argument( '--login', metavar='<login-name>', - help='Login name (ssh -l option)', + help=_('Login name (ssh -l option)'), ) parser.add_argument( '-l', @@ -1152,7 +1149,7 @@ class SshServer(command.Command): '--port', metavar='<port>', type=int, - help='Destination port (ssh -p option)', + help=_('Destination port (ssh -p option)'), ) parser.add_argument( '-p', @@ -1164,7 +1161,7 @@ class SshServer(command.Command): parser.add_argument( '--identity', metavar='<keyfile>', - help='Private key file (ssh -i option)', + help=_('Private key file (ssh -i option)'), ) parser.add_argument( '-i', @@ -1175,7 +1172,7 @@ class SshServer(command.Command): parser.add_argument( '--option', metavar='<config-options>', - help='Options in ssh_config(5) format (ssh -o option)', + help=_('Options in ssh_config(5) format (ssh -o option)'), ) parser.add_argument( '-o', @@ -1189,14 +1186,14 @@ class SshServer(command.Command): dest='ipv4', action='store_true', default=False, - help='Use only IPv4 addresses', + help=_('Use only IPv4 addresses'), ) ip_group.add_argument( '-6', dest='ipv6', action='store_true', default=False, - help='Use only IPv6 addresses', + help=_('Use only IPv6 addresses'), ) type_group = parser.add_mutually_exclusive_group() type_group.add_argument( @@ -1205,7 +1202,7 @@ class SshServer(command.Command): action='store_const', const='public', default='public', - help='Use public IP address', + help=_('Use public IP address'), ) type_group.add_argument( '--private', @@ -1213,14 +1210,14 @@ class SshServer(command.Command): action='store_const', const='private', default='public', - help='Use private IP address', + help=_('Use private IP address'), ) type_group.add_argument( '--address-type', metavar='<address-type>', dest='address_type', default='public', - help='Use other IP address (public, private, etc)', + help=_('Use other IP address (public, private, etc)'), ) parser.add_argument( '-v', @@ -1294,7 +1291,7 @@ class SuspendServer(command.Command): parser.add_argument( 'server', metavar='<server>', - help='Server (name or ID)', + help=_('Server (name or ID)'), ) return parser @@ -1318,7 +1315,7 @@ class UnlockServer(command.Command): parser.add_argument( 'server', metavar='<server>', - help='Server (name or ID)', + help=_('Server (name or ID)'), ) return parser @@ -1342,7 +1339,7 @@ class UnpauseServer(command.Command): parser.add_argument( 'server', metavar='<server>', - help='Server (name or ID)', + help=_('Server (name or ID)'), ) return parser @@ -1366,7 +1363,7 @@ class UnrescueServer(command.Command): parser.add_argument( 'server', metavar='<server>', - help='Server (name or ID)', + help=_('Server (name or ID)'), ) return parser @@ -1390,15 +1387,15 @@ class UnsetServer(command.Command): parser.add_argument( 'server', metavar='<server>', - help='Server (name or ID)', + help=_('Server (name or ID)'), ) parser.add_argument( '--property', metavar='<key>', action='append', default=[], - help='Property key to remove from server ' - '(repeat to set multiple values)', + help=_('Property key to remove from server ' + '(repeat to set multiple values)'), ) return parser diff --git a/openstackclient/i18n.py b/openstackclient/i18n.py index bd52d648..3611b315 100644 --- a/openstackclient/i18n.py +++ b/openstackclient/i18n.py @@ -15,7 +15,7 @@ from oslo import i18n -_translators = i18n.TranslatorFactory(domain='openstackclient') +_translators = i18n.TranslatorFactory(domain='python-openstackclient') # The primary translation function using the well-known name "_" _ = _translators.primary diff --git a/openstackclient/identity/v2_0/catalog.py b/openstackclient/identity/v2_0/catalog.py index 7bda1acb..1a96fdf6 100644 --- a/openstackclient/identity/v2_0/catalog.py +++ b/openstackclient/identity/v2_0/catalog.py @@ -20,6 +20,7 @@ from cliff import lister from cliff import show from openstackclient.common import utils +from openstackclient.i18n import _ # noqa def _format_endpoints(eps=None): @@ -67,7 +68,7 @@ class ShowCatalog(show.ShowOne): parser.add_argument( 'service', metavar='<service>', - help='Service to display (type, name or ID)', + help=_('Service to display (type, name or ID)'), ) return parser diff --git a/openstackclient/identity/v2_0/ec2creds.py b/openstackclient/identity/v2_0/ec2creds.py index 74c9d5eb..fd8eef84 100644 --- a/openstackclient/identity/v2_0/ec2creds.py +++ b/openstackclient/identity/v2_0/ec2creds.py @@ -24,6 +24,7 @@ from cliff import lister from cliff import show from openstackclient.common import utils +from openstackclient.i18n import _ # noqa class CreateEC2Creds(show.ShowOne): @@ -36,12 +37,12 @@ class CreateEC2Creds(show.ShowOne): parser.add_argument( '--project', metavar='<project>', - help='Specify a project [admin only]', + help=_('Specify a project [admin only]'), ) parser.add_argument( '--user', metavar='<user>', - help='Specify a user [admin only]', + help=_('Specify a user [admin only]'), ) return parser @@ -83,12 +84,12 @@ class DeleteEC2Creds(command.Command): parser.add_argument( 'access_key', metavar='<access-key>', - help='Credentials access key', + help=_('Credentials access key'), ) parser.add_argument( '--user', metavar='<user>', - help='Specify a user [admin only]', + help=_('Specify a user [admin only]'), ) return parser @@ -118,7 +119,7 @@ class ListEC2Creds(lister.Lister): parser.add_argument( '--user', metavar='<user>', - help='Specify a user [admin only]', + help=_('Specify a user [admin only]'), ) return parser @@ -156,12 +157,12 @@ class ShowEC2Creds(show.ShowOne): parser.add_argument( 'access_key', metavar='<access-key>', - help='Credentials access key', + help=_('Credentials access key'), ) parser.add_argument( '--user', metavar='<user>', - help='Specify a user [admin only]', + help=_('Specify a user [admin only]'), ) return parser diff --git a/openstackclient/identity/v2_0/endpoint.py b/openstackclient/identity/v2_0/endpoint.py index 36f52cad..f7d78831 100644 --- a/openstackclient/identity/v2_0/endpoint.py +++ b/openstackclient/identity/v2_0/endpoint.py @@ -23,6 +23,7 @@ from cliff import lister from cliff import show from openstackclient.common import utils +from openstackclient.i18n import _ # noqa from openstackclient.identity import common @@ -36,24 +37,24 @@ class CreateEndpoint(show.ShowOne): parser.add_argument( 'service', metavar='<endpoint-service>', - help='New endpoint service') + help=_('New endpoint service')) parser.add_argument( '--region', metavar='<region>', - help='New endpoint region') + help=_('New endpoint region')) parser.add_argument( '--publicurl', metavar='<public-url>', required=True, - help='New endpoint public URL') + help=_('New endpoint public URL')) parser.add_argument( '--adminurl', metavar='<admin-url>', - help='New endpoint admin URL') + help=_('New endpoint admin URL')) parser.add_argument( '--internalurl', metavar='<internal-url>', - help='New endpoint internal URL') + help=_('New endpoint internal URL')) return parser def take_action(self, parsed_args): @@ -84,7 +85,7 @@ class DeleteEndpoint(command.Command): parser.add_argument( 'endpoint', metavar='<endpoint-id>', - help='ID of endpoint to delete') + help=_('ID of endpoint to delete')) return parser def take_action(self, parsed_args): @@ -105,7 +106,7 @@ class ListEndpoint(lister.Lister): '--long', action='store_true', default=False, - help='List additional fields in output') + help=_('List additional fields in output')) return parser def take_action(self, parsed_args): @@ -139,7 +140,7 @@ class ShowEndpoint(show.ShowOne): parser.add_argument( 'endpoint_or_service', metavar='<endpoint_or_service>', - help='Endpoint ID or name, type or ID of service to display') + help=_('Endpoint ID or name, type or ID of service to display')) return parser def take_action(self, parsed_args): diff --git a/openstackclient/identity/v2_0/project.py b/openstackclient/identity/v2_0/project.py index ebd65df7..7ead0890 100644 --- a/openstackclient/identity/v2_0/project.py +++ b/openstackclient/identity/v2_0/project.py @@ -21,10 +21,11 @@ import six from cliff import command from cliff import lister from cliff import show - from keystoneclient.openstack.common.apiclient import exceptions as ksc_exc + from openstackclient.common import parseractions from openstackclient.common import utils +from openstackclient.i18n import _ # noqa class CreateProject(show.ShowOne): @@ -37,30 +38,30 @@ class CreateProject(show.ShowOne): parser.add_argument( 'name', metavar='<project-name>', - help='New project name', + help=_('New project name'), ) parser.add_argument( '--description', metavar='<project-description>', - help='New project description', + help=_('New project description'), ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', - help='Enable project (default)', + help=_('Enable project (default)'), ) enable_group.add_argument( '--disable', action='store_true', - help='Disable project', + help=_('Disable project'), ) parser.add_argument( '--property', metavar='<key=value>', action=parseractions.KeyValueAction, - help='Property to add for this project ' - '(repeat option to set multiple properties)', + help=_('Property to add for this project ' + '(repeat option to set multiple properties)'), ) return parser @@ -97,7 +98,7 @@ class DeleteProject(command.Command): parser.add_argument( 'project', metavar='<project>', - help='Project to delete (name or ID)', + help=_('Project to delete (name or ID)'), ) return parser @@ -125,7 +126,7 @@ class ListProject(lister.Lister): '--long', action='store_true', default=False, - help='List additional fields in output', + help=_('List additional fields in output'), ) return parser @@ -153,35 +154,35 @@ class SetProject(command.Command): parser.add_argument( 'project', metavar='<project>', - help='Project to change (name or ID)', + help=_('Project to change (name or ID)'), ) parser.add_argument( '--name', metavar='<new-project-name>', - help='New project name', + help=_('New project name'), ) parser.add_argument( '--description', metavar='<project-description>', - help='New project description', + help=_('New project description'), ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', - help='Enable project', + help=_('Enable project'), ) enable_group.add_argument( '--disable', action='store_true', - help='Disable project', + help=_('Disable project'), ) parser.add_argument( '--property', metavar='<key=value>', action=parseractions.KeyValueAction, - help='Property to add for this project ' - '(repeat option to set multiple properties)', + help=_('Property to add for this project ' + '(repeat option to set multiple properties)'), ) return parser @@ -233,7 +234,7 @@ class ShowProject(show.ShowOne): parser.add_argument( 'project', metavar='<project>', - help='Project to display (name or ID)') + help=_('Project to display (name or ID)')) return parser def take_action(self, parsed_args): diff --git a/openstackclient/identity/v2_0/role.py b/openstackclient/identity/v2_0/role.py index faf48ed9..4c45004d 100644 --- a/openstackclient/identity/v2_0/role.py +++ b/openstackclient/identity/v2_0/role.py @@ -24,6 +24,7 @@ from cliff import show from openstackclient.common import exceptions from openstackclient.common import utils +from openstackclient.i18n import _ # noqa class AddRole(show.ShowOne): @@ -36,18 +37,17 @@ class AddRole(show.ShowOne): parser.add_argument( 'role', metavar='<role>', - help='Role name or ID to add to user') + help=_('Role name or ID to add to user')) parser.add_argument( '--project', metavar='<project>', required=True, - help='Include project (name or ID)', - ) + help=_('Include project (name or ID)')) parser.add_argument( '--user', metavar='<user>', required=True, - help='Name or ID of user to include') + help=_('Name or ID of user to include')) return parser def take_action(self, parsed_args): @@ -80,7 +80,7 @@ class CreateRole(show.ShowOne): parser.add_argument( 'role_name', metavar='<role-name>', - help='New role name') + help=_('New role name')) return parser def take_action(self, parsed_args): @@ -103,8 +103,7 @@ class DeleteRole(command.Command): parser.add_argument( 'role', metavar='<role>', - help='Name or ID of role to delete', - ) + help=_('Name or ID of role to delete')) return parser def take_action(self, parsed_args): @@ -147,12 +146,11 @@ class ListUserRole(lister.Lister): 'user', metavar='<user>', nargs='?', - help='Name or ID of user to include') + help=_('Name or ID of user to include')) parser.add_argument( '--project', metavar='<project>', - help='Include project (name or ID)', - ) + help=_('Include project (name or ID)')) return parser def take_action(self, parsed_args): @@ -167,13 +165,13 @@ class ListUserRole(lister.Lister): if self.app.client_manager.auth_ref: parsed_args.project = auth_ref.project_id else: - msg = "Project must be specified" + msg = _("Project must be specified") raise exceptions.CommandError(msg) if not parsed_args.user: if self.app.client_manager.auth_ref: parsed_args.user = auth_ref.user_id else: - msg = "User must be specified" + msg = _("User must be specified") raise exceptions.CommandError(msg) project = utils.find_resource( @@ -213,18 +211,17 @@ class RemoveRole(command.Command): parser.add_argument( 'role', metavar='<role>', - help='Role name or ID to remove from user') + help=_('Role name or ID to remove from user')) parser.add_argument( '--project', metavar='<project>', required=True, - help='Project to include (name or ID)', - ) + help=_('Project to include (name or ID)')) parser.add_argument( '--user', metavar='<user>', required=True, - help='Name or ID of user') + help=_('Name or ID of user')) return parser def take_action(self, parsed_args): @@ -252,7 +249,7 @@ class ShowRole(show.ShowOne): parser.add_argument( 'role', metavar='<role>', - help='Name or ID of role to display') + help=_('Name or ID of role to display')) return parser def take_action(self, parsed_args): diff --git a/openstackclient/identity/v2_0/service.py b/openstackclient/identity/v2_0/service.py index 138ed3b0..458dce7c 100644 --- a/openstackclient/identity/v2_0/service.py +++ b/openstackclient/identity/v2_0/service.py @@ -24,6 +24,7 @@ from cliff import show from openstackclient.common import exceptions from openstackclient.common import utils +from openstackclient.i18n import _ # noqa from openstackclient.identity import common @@ -37,18 +38,18 @@ class CreateService(show.ShowOne): parser.add_argument( 'name', metavar='<service-name>', - help='New service name', + help=_('New service name'), ) parser.add_argument( '--type', metavar='<service-type>', required=True, - help='New service type (compute, image, identity, volume, etc)', + help=_('New service type (compute, image, identity, volume, etc)'), ) parser.add_argument( '--description', metavar='<service-description>', - help='New service description', + help=_('New service description'), ) return parser @@ -76,7 +77,7 @@ class DeleteService(command.Command): parser.add_argument( 'service', metavar='<service>', - help='Service to delete (name or ID)', + help=_('Service to delete (name or ID)'), ) return parser @@ -99,7 +100,7 @@ class ListService(lister.Lister): '--long', action='store_true', default=False, - help='List additional fields in output') + help=_('List additional fields in output')) return parser def take_action(self, parsed_args): @@ -127,13 +128,13 @@ class ShowService(show.ShowOne): parser.add_argument( 'service', metavar='<service>', - help='Service to display (type, name or ID)', + help=_('Service to display (type, name or ID)'), ) parser.add_argument( '--catalog', action='store_true', default=False, - help='Show service catalog information', + help=_('Show service catalog information'), ) return parser @@ -150,8 +151,8 @@ class ShowService(show.ShowOne): info.update(service_endpoints[0]) return zip(*sorted(six.iteritems(info))) - msg = ("No service catalog with a type, name or ID of '%s' " - "exists." % (parsed_args.service)) + msg = _("No service catalog with a type, name or ID of '%s' " + "exists.") % (parsed_args.service) raise exceptions.CommandError(msg) else: service = common.find_service(identity_client, parsed_args.service) diff --git a/openstackclient/identity/v2_0/token.py b/openstackclient/identity/v2_0/token.py index f3fedc01..c8b003ee 100644 --- a/openstackclient/identity/v2_0/token.py +++ b/openstackclient/identity/v2_0/token.py @@ -21,6 +21,8 @@ import six from cliff import command from cliff import show +from openstackclient.i18n import _ # noqa + class IssueToken(show.ShowOne): """Issue new token""" @@ -49,7 +51,7 @@ class RevokeToken(command.Command): parser.add_argument( 'token', metavar='<token>', - help='Token to be deleted', + help=_('Token to be deleted'), ) return parser diff --git a/openstackclient/identity/v2_0/user.py b/openstackclient/identity/v2_0/user.py index 93ab94fe..729c6ac8 100644 --- a/openstackclient/identity/v2_0/user.py +++ b/openstackclient/identity/v2_0/user.py @@ -21,9 +21,10 @@ import six from cliff import command from cliff import lister from cliff import show - from keystoneclient.openstack.common.apiclient import exceptions as ksc_exc + from openstackclient.common import utils +from openstackclient.i18n import _ # noqa class CreateUser(show.ShowOne): @@ -36,39 +37,39 @@ class CreateUser(show.ShowOne): parser.add_argument( 'name', metavar='<user-name>', - help='New user name', + help=_('New user name'), ) parser.add_argument( '--password', metavar='<user-password>', - help='New user password', + help=_('New user password'), ) parser.add_argument( '--password-prompt', dest="password_prompt", action="store_true", - help='Prompt interactively for password', + help=_('Prompt interactively for password'), ) parser.add_argument( '--email', metavar='<user-email>', - help='New user email address', + help=_('New user email address'), ) parser.add_argument( '--project', metavar='<project>', - help='Set default project (name or ID)', + help=_('Set default project (name or ID)'), ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', - help='Enable user (default)', + help=_('Enable user (default)'), ) enable_group.add_argument( '--disable', action='store_true', - help='Disable user', + help=_('Disable user'), ) return parser @@ -120,7 +121,7 @@ class DeleteUser(command.Command): parser.add_argument( 'user', metavar='<user>', - help='User to delete (name or ID)', + help=_('User to delete (name or ID)'), ) return parser @@ -147,13 +148,13 @@ class ListUser(lister.Lister): parser.add_argument( '--project', metavar='<project>', - help='Filter users by project (name or ID)', + help=_('Filter users by project (name or ID)'), ) parser.add_argument( '--long', action='store_true', default=False, - help='List additional fields in output') + help=_('List additional fields in output')) return parser def take_action(self, parsed_args): @@ -237,44 +238,44 @@ class SetUser(command.Command): parser.add_argument( 'user', metavar='<user>', - help='User to change (name or ID)', + help=_('User to change (name or ID)'), ) parser.add_argument( '--name', metavar='<new-user-name>', - help='New user name', + help=_('New user name'), ) parser.add_argument( '--password', metavar='<user-password>', - help='New user password', + help=_('New user password'), ) parser.add_argument( '--password-prompt', dest="password_prompt", action="store_true", - help='Prompt interactively for password', + help=_('Prompt interactively for password'), ) parser.add_argument( '--email', metavar='<user-email>', - help='New user email address', + help=_('New user email address'), ) parser.add_argument( '--project', metavar='<project>', - help='New default project (name or ID)', + help=_('New default project (name or ID)'), ) enable_group = parser.add_mutually_exclusive_group() enable_group.add_argument( '--enable', action='store_true', - help='Enable user (default)', + help=_('Enable user (default)'), ) enable_group.add_argument( '--disable', action='store_true', - help='Disable user', + help=_('Disable user'), ) return parser @@ -340,7 +341,7 @@ class ShowUser(show.ShowOne): parser.add_argument( 'user', metavar='<user>', - help='User to display (name or ID)', + help=_('User to display (name or ID)'), ) return parser diff --git a/openstackclient/identity/v3/credential.py b/openstackclient/identity/v3/credential.py index f1e17b85..4d688954 100644 --- a/openstackclient/identity/v3/credential.py +++ b/openstackclient/identity/v3/credential.py @@ -73,6 +73,7 @@ class CreateCredential(show.ShowOne): blob=parsed_args.data, project=project) + credential._info.pop('links') return zip(*sorted(six.iteritems(credential._info))) @@ -193,4 +194,5 @@ class ShowCredential(show.ShowOne): credential = utils.find_resource(identity_client.credentials, parsed_args.credential) + credential._info.pop('links') return zip(*sorted(six.iteritems(credential._info))) diff --git a/openstackclient/identity/v3/domain.py b/openstackclient/identity/v3/domain.py index 49397afc..d14da486 100644 --- a/openstackclient/identity/v3/domain.py +++ b/openstackclient/identity/v3/domain.py @@ -66,6 +66,7 @@ class CreateDomain(show.ShowOne): enabled=parsed_args.enabled, ) + domain._info.pop('links') return zip(*sorted(six.iteritems(domain._info))) @@ -187,4 +188,5 @@ class ShowDomain(show.ShowOne): domain = utils.find_resource(identity_client.domains, parsed_args.domain) + domain._info.pop('links') return zip(*sorted(six.iteritems(domain._info))) diff --git a/openstackclient/identity/v3/endpoint.py b/openstackclient/identity/v3/endpoint.py index 39798b2d..0c077c5a 100644 --- a/openstackclient/identity/v3/endpoint.py +++ b/openstackclient/identity/v3/endpoint.py @@ -81,6 +81,7 @@ class CreateEndpoint(show.ShowOne): ) info = {} + endpoint._info.pop('links') info.update(endpoint._info) info['service_name'] = service.name info['service_type'] = service.type @@ -258,6 +259,7 @@ class ShowEndpoint(show.ShowOne): service = common.find_service(identity_client, endpoint.service_id) info = {} + endpoint._info.pop('links') info.update(endpoint._info) info['service_name'] = service.name info['service_type'] = service.type diff --git a/openstackclient/identity/v3/group.py b/openstackclient/identity/v3/group.py index 4eb14489..d2ffca27 100644 --- a/openstackclient/identity/v3/group.py +++ b/openstackclient/identity/v3/group.py @@ -24,6 +24,7 @@ from cliff import lister from cliff import show from openstackclient.common import utils +from openstackclient.identity import common class AddUserToGroup(command.Command): @@ -128,8 +129,8 @@ class CreateGroup(show.ShowOne): self.log.debug('take_action(%s)', parsed_args) identity_client = self.app.client_manager.identity if parsed_args.domain: - domain = utils.find_resource(identity_client.domains, - parsed_args.domain).id + domain = common.find_domain(identity_client, + parsed_args.domain).id else: domain = None group = identity_client.groups.create( @@ -137,9 +138,8 @@ class CreateGroup(show.ShowOne): domain=domain, description=parsed_args.description) - info = {} - info.update(group._info) - return zip(*sorted(six.iteritems(info))) + group._info.pop('links') + return zip(*sorted(six.iteritems(group._info))) class DeleteGroup(command.Command): @@ -173,7 +173,7 @@ class ListGroup(lister.Lister): parser.add_argument( '--domain', metavar='<domain>', - help='Filter group list by <domain>', + help='Filter group list by <domain> (name or ID)', ) parser.add_argument( '--user', @@ -193,10 +193,8 @@ class ListGroup(lister.Lister): identity_client = self.app.client_manager.identity if parsed_args.domain: - domain = utils.find_resource( - identity_client.domains, - parsed_args.domain, - ).id + domain = common.find_domain(identity_client, + parsed_args.domain).id else: domain = None @@ -300,10 +298,8 @@ class SetGroup(command.Command): if parsed_args.description: kwargs['description'] = parsed_args.description if parsed_args.domain: - domain = utils.find_resource( - identity_client.domains, parsed_args.domain).id - kwargs['domain'] = domain - + kwargs['domain'] = common.find_domain(identity_client, + parsed_args.domain).id if not len(kwargs): sys.stderr.write("Group not updated, no arguments present") return @@ -321,14 +317,27 @@ class ShowGroup(show.ShowOne): parser.add_argument( 'group', metavar='<group>', - help='Name or ID of group to display') + help='Name or ID of group to display', + ) + parser.add_argument( + '--domain', + metavar='<domain>', + help='Domain where group resides (name or ID)', + ) return parser def take_action(self, parsed_args): self.log.debug('take_action(%s)', parsed_args) identity_client = self.app.client_manager.identity - group = utils.find_resource(identity_client.groups, parsed_args.group) - info = {} - info.update(group._info) - return zip(*sorted(six.iteritems(info))) + if parsed_args.domain: + domain = common.find_domain(identity_client, parsed_args.domain) + group = utils.find_resource(identity_client.groups, + parsed_args.group, + domain_id=domain.id) + else: + group = utils.find_resource(identity_client.groups, + parsed_args.group) + + group._info.pop('links') + return zip(*sorted(six.iteritems(group._info))) diff --git a/openstackclient/identity/v3/policy.py b/openstackclient/identity/v3/policy.py index 87f3cbe9..802880bf 100644 --- a/openstackclient/identity/v3/policy.py +++ b/openstackclient/identity/v3/policy.py @@ -55,6 +55,7 @@ class CreatePolicy(show.ShowOne): blob=blob, type=parsed_args.type ) + policy._info.pop('links') return zip(*sorted(six.iteritems(policy._info))) @@ -173,4 +174,5 @@ class ShowPolicy(show.ShowOne): policy = utils.find_resource(identity_client.policies, parsed_args.policy) + policy._info.pop('links') return zip(*sorted(six.iteritems(policy._info))) diff --git a/openstackclient/identity/v3/project.py b/openstackclient/identity/v3/project.py index fa935f0b..1cdeb150 100644 --- a/openstackclient/identity/v3/project.py +++ b/openstackclient/identity/v3/project.py @@ -74,7 +74,8 @@ class CreateProject(show.ShowOne): identity_client = self.app.client_manager.identity if parsed_args.domain: - domain = common.find_domain(identity_client, parsed_args.domain).id + domain = common.find_domain(identity_client, + parsed_args.domain).id else: domain = None @@ -93,9 +94,8 @@ class CreateProject(show.ShowOne): **kwargs ) - info = {} - info.update(project._info) - return zip(*sorted(six.iteritems(info))) + project._info.pop('links') + return zip(*sorted(six.iteritems(project._info))) class DeleteProject(command.Command): @@ -141,7 +141,7 @@ class ListProject(lister.Lister): parser.add_argument( '--domain', metavar='<project-domain>', - help='Filter by a specific domain', + help='Filter by a specific domain (name or ID)', ) return parser @@ -154,8 +154,8 @@ class ListProject(lister.Lister): columns = ('ID', 'Name') kwargs = {} if parsed_args.domain: - domain = common.find_domain(identity_client, parsed_args.domain) - kwargs['domain'] = domain.id + kwargs['domain'] = common.find_domain(identity_client, + parsed_args.domain).id data = identity_client.projects.list(**kwargs) return (columns, (utils.get_item_properties( @@ -228,12 +228,12 @@ class SetProject(command.Command): parsed_args.project, ) - kwargs = project._info + kwargs = {} if parsed_args.name: kwargs['name'] = parsed_args.name if parsed_args.domain: - domain = common.find_domain(identity_client, parsed_args.domain) - kwargs['domain'] = domain.id + kwargs['domain'] = common.find_domain(identity_client, + parsed_args.domain).id if parsed_args.description: kwargs['description'] = parsed_args.description if parsed_args.enable: @@ -242,13 +242,6 @@ class SetProject(command.Command): kwargs['enabled'] = False if parsed_args.property: kwargs.update(parsed_args.property) - if 'id' in kwargs: - del kwargs['id'] - if 'domain_id' in kwargs: - # Hack around broken Identity API arg names - kwargs.update( - {'domain': kwargs.pop('domain_id')} - ) identity_client.projects.update(project.id, **kwargs) return @@ -264,15 +257,27 @@ class ShowProject(show.ShowOne): parser.add_argument( 'project', metavar='<project>', - help='Name or ID of project to display') + help='Name or ID of project to display', + ) + parser.add_argument( + '--domain', + metavar='<domain>', + help='Domain where project resides (name or ID)', + ) return parser def take_action(self, parsed_args): self.log.debug('take_action(%s)', parsed_args) identity_client = self.app.client_manager.identity - project = utils.find_resource(identity_client.projects, - parsed_args.project) - info = {} - info.update(project._info) - return zip(*sorted(six.iteritems(info))) + if parsed_args.domain: + domain = common.find_domain(identity_client, parsed_args.domain) + project = utils.find_resource(identity_client.projects, + parsed_args.project, + domain_id=domain.id) + else: + project = utils.find_resource(identity_client.projects, + parsed_args.project) + + project._info.pop('links') + return zip(*sorted(six.iteritems(project._info))) diff --git a/openstackclient/identity/v3/role.py b/openstackclient/identity/v3/role.py index d8de7c22..a3c24b7a 100644 --- a/openstackclient/identity/v3/role.py +++ b/openstackclient/identity/v3/role.py @@ -157,6 +157,7 @@ class CreateRole(show.ShowOne): role = identity_client.roles.create(name=parsed_args.name) + role._info.pop('links') return zip(*sorted(six.iteritems(role._info))) @@ -472,4 +473,5 @@ class ShowRole(show.ShowOne): parsed_args.role, ) + role._info.pop('links') return zip(*sorted(six.iteritems(role._info))) diff --git a/openstackclient/identity/v3/service.py b/openstackclient/identity/v3/service.py index 88301edc..4f622269 100644 --- a/openstackclient/identity/v3/service.py +++ b/openstackclient/identity/v3/service.py @@ -70,6 +70,7 @@ class CreateService(show.ShowOne): enabled=enabled, ) + service._info.pop('links') return zip(*sorted(six.iteritems(service._info))) @@ -161,7 +162,7 @@ class SetService(command.Command): service = common.find_service(identity_client, parsed_args.service) - kwargs = service._info + kwargs = {} if parsed_args.type: kwargs['type'] = parsed_args.type if parsed_args.name: @@ -170,8 +171,6 @@ class SetService(command.Command): kwargs['enabled'] = True if parsed_args.disable: kwargs['enabled'] = False - if 'id' in kwargs: - del kwargs['id'] identity_client.services.update( service.id, @@ -200,4 +199,5 @@ class ShowService(show.ShowOne): service = common.find_service(identity_client, parsed_args.service) + service._info.pop('links') return zip(*sorted(six.iteritems(service._info))) diff --git a/openstackclient/identity/v3/token.py b/openstackclient/identity/v3/token.py index 52ed439f..aca5c669 100644 --- a/openstackclient/identity/v3/token.py +++ b/openstackclient/identity/v3/token.py @@ -159,9 +159,9 @@ class IssueToken(show.ShowOne): def take_action(self, parsed_args): self.log.debug('take_action(%s)', parsed_args) - identity_client = self.app.client_manager.identity + session = self.app.client_manager.identity.session - token = identity_client.service_catalog.get_token() + token = session.auth.auth_ref.service_catalog.get_token() if 'tenant_id' in token: token['project_id'] = token.pop('tenant_id') return zip(*sorted(six.iteritems(token))) diff --git a/openstackclient/identity/v3/user.py b/openstackclient/identity/v3/user.py index e4eb7526..9a3e00b8 100644 --- a/openstackclient/identity/v3/user.py +++ b/openstackclient/identity/v3/user.py @@ -23,6 +23,7 @@ from cliff import lister from cliff import show from openstackclient.common import utils +from openstackclient.identity import common class CreateUser(show.ShowOne): @@ -94,8 +95,8 @@ class CreateUser(show.ShowOne): project_id = None if parsed_args.domain: - domain_id = utils.find_resource( - identity_client.domains, parsed_args.domain).id + domain_id = common.find_domain(identity_client, + parsed_args.domain).id else: domain_id = None @@ -115,9 +116,8 @@ class CreateUser(show.ShowOne): enabled=enabled ) - info = {} - info.update(user._info) - return zip(*sorted(six.iteritems(info))) + user._info.pop('links') + return zip(*sorted(six.iteritems(user._info))) class DeleteUser(command.Command): @@ -157,7 +157,7 @@ class ListUser(lister.Lister): parser.add_argument( '--domain', metavar='<domain>', - help='Filter group list by <domain>', + help='Filter user list by <domain> (name or ID)', ) parser.add_argument( '--group', @@ -177,10 +177,8 @@ class ListUser(lister.Lister): identity_client = self.app.client_manager.identity if parsed_args.domain: - domain = utils.find_resource( - identity_client.domains, - parsed_args.domain, - ).id + domain = common.find_domain(identity_client, + parsed_args.domain).id else: domain = None @@ -310,9 +308,8 @@ class SetUser(command.Command): identity_client.projects, parsed_args.project).id kwargs['project'] = project_id if parsed_args.domain: - domain_id = utils.find_resource( - identity_client.domains, parsed_args.domain).id - kwargs['domain'] = domain_id + kwargs['domain'] = common.find_domain(identity_client, + parsed_args.domain).id kwargs['enabled'] = user.enabled if parsed_args.enable: kwargs['enabled'] = True @@ -364,17 +361,25 @@ class ShowUser(show.ShowOne): metavar='<user>', help='User to display (name or ID)', ) + parser.add_argument( + '--domain', + metavar='<domain>', + help='Domain where user resides (name or ID)', + ) return parser def take_action(self, parsed_args): self.log.debug('take_action(%s)', parsed_args) identity_client = self.app.client_manager.identity - user = utils.find_resource( - identity_client.users, - parsed_args.user, - ) + if parsed_args.domain: + domain = common.find_domain(identity_client, parsed_args.domain) + user = utils.find_resource(identity_client.users, + parsed_args.user, + domain_id=domain.id) + else: + user = utils.find_resource(identity_client.users, + parsed_args.user) - info = {} - info.update(user._info) - return zip(*sorted(six.iteritems(info))) + user._info.pop('links') + return zip(*sorted(six.iteritems(user._info))) diff --git a/openstackclient/network/client.py b/openstackclient/network/client.py index d3102da1..870fdad1 100644 --- a/openstackclient/network/client.py +++ b/openstackclient/network/client.py @@ -35,7 +35,8 @@ def make_client(instance): LOG.debug('Instantiating network client: %s', network_client) if not instance._url: - instance._url = instance.get_endpoint_for_service_type("network") + instance._url = instance.get_endpoint_for_service_type( + "network", region_name=instance._region_name) return network_client( username=instance._username, tenant_name=instance._project_name, diff --git a/openstackclient/shell.py b/openstackclient/shell.py index 626e3f7d..1f9eb32b 100644 --- a/openstackclient/shell.py +++ b/openstackclient/shell.py @@ -68,19 +68,6 @@ class OpenStackShell(app.App): # Assume TLS host certificate verification is enabled self.verify = True - # Get list of base modules - self.ext_modules = clientmanager.get_extension_modules( - 'openstack.cli.base', - ) - # Append list of extension modules - self.ext_modules.extend(clientmanager.get_extension_modules( - 'openstack.cli.extension', - )) - - # Loop through extensions to get parser additions - for mod in self.ext_modules: - self.parser = mod.build_option_parser(self.parser) - # NOTE(dtroyer): This hack changes the help action that Cliff # automatically adds to the parser so we can defer # its execution until after the api-versioned commands @@ -170,6 +157,7 @@ class OpenStackShell(app.App): parser = super(OpenStackShell, self).build_option_parser( description, version) + # service token auth argument parser.add_argument( '--os-url', @@ -214,7 +202,7 @@ class OpenStackShell(app.App): help="Print API call timing info", ) - return parser + return clientmanager.build_plugin_option_parser(parser) def authenticate_user(self): """Verify the required authentication credentials are present""" @@ -332,7 +320,7 @@ class OpenStackShell(app.App): self.default_domain = self.options.os_default_domain # Loop through extensions to get API versions - for mod in self.ext_modules: + for mod in clientmanager.PLUGIN_MODULES: version_opt = getattr(self.options, mod.API_VERSION_OPTION, None) if version_opt: api = mod.API_NAME diff --git a/openstackclient/tests/common/test_clientmanager.py b/openstackclient/tests/common/test_clientmanager.py index 5ec86d59..d0738c79 100644 --- a/openstackclient/tests/common/test_clientmanager.py +++ b/openstackclient/tests/common/test_clientmanager.py @@ -16,8 +16,8 @@ import mock from requests_mock.contrib import fixture from keystoneclient.auth.identity import v2 as auth_v2 -from keystoneclient.openstack.common import jsonutils from keystoneclient import service_catalog +from oslo.serialization import jsonutils from openstackclient.api import auth from openstackclient.common import clientmanager diff --git a/openstackclient/tests/common/test_commandmanager.py b/openstackclient/tests/common/test_commandmanager.py index ca9ee9a7..e7803a48 100644 --- a/openstackclient/tests/common/test_commandmanager.py +++ b/openstackclient/tests/common/test_commandmanager.py @@ -86,3 +86,20 @@ class TestCommandManager(utils.TestCase): gl = mgr.get_command_groups() self.assertEqual(['test', 'greek'], gl) + + def test_get_command_names(self): + mock_cmd_one = mock.Mock() + mock_cmd_one.name = 'one' + mock_cmd_two = mock.Mock() + mock_cmd_two.name = 'cmd two' + mock_pkg_resources = mock.Mock( + return_value=[mock_cmd_one, mock_cmd_two], + ) + with mock.patch( + 'pkg_resources.iter_entry_points', + mock_pkg_resources, + ) as iter_entry_points: + mgr = commandmanager.CommandManager('test') + assert iter_entry_points.called_once_with('test') + cmds = mgr.get_command_names('test') + self.assertEqual(['one', 'cmd two'], cmds) diff --git a/openstackclient/tests/common/test_module.py b/openstackclient/tests/common/test_module.py index ce1592e4..6918c1b4 100644 --- a/openstackclient/tests/common/test_module.py +++ b/openstackclient/tests/common/test_module.py @@ -42,6 +42,38 @@ MODULES = { } +class TestCommandList(utils.TestCommand): + + def setUp(self): + super(TestCommandList, self).setUp() + + self.app.command_manager = mock.Mock() + self.app.command_manager.get_command_groups.return_value = ['test'] + self.app.command_manager.get_command_names.return_value = [ + 'one', + 'cmd two', + ] + + # Get the command object to test + self.cmd = osc_module.ListCommand(self.app, None) + + def test_command_list_no_options(self): + arglist = [] + verifylist = [] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # DisplayCommandBase.take_action() returns two tuples + columns, data = self.cmd.take_action(parsed_args) + + collist = ('Command Group', 'Commands') + self.assertEqual(collist, columns) + datalist = (( + 'test', + ['one', 'cmd two'], + ), ) + self.assertEqual(datalist, tuple(data)) + + @mock.patch.dict( 'openstackclient.common.module.sys.modules', values=MODULES, diff --git a/openstackclient/tests/identity/v3/fakes.py b/openstackclient/tests/identity/v3/fakes.py index b0df16f0..69c25905 100644 --- a/openstackclient/tests/identity/v3/fakes.py +++ b/openstackclient/tests/identity/v3/fakes.py @@ -18,6 +18,7 @@ import mock from openstackclient.tests import fakes from openstackclient.tests import utils +base_url = 'http://identity:5000/v3/' domain_id = 'd1' domain_name = 'oftheking' @@ -28,6 +29,7 @@ DOMAIN = { 'name': domain_name, 'description': domain_description, 'enabled': True, + 'links': base_url + 'domains/' + domain_id, } group_id = 'gr-010' @@ -36,6 +38,7 @@ group_name = 'spencer davis' GROUP = { 'id': group_id, 'name': group_name, + 'links': base_url + 'groups/' + group_id, } mapping_id = 'test_mapping' @@ -107,6 +110,7 @@ PROJECT = { 'description': project_description, 'enabled': True, 'domain_id': domain_id, + 'links': base_url + 'projects/' + project_id, } PROJECT_2 = { @@ -115,6 +119,7 @@ PROJECT_2 = { 'description': project_description + 'plus four more', 'enabled': True, 'domain_id': domain_id, + 'links': base_url + 'projects/' + project_id, } role_id = 'r1' @@ -123,6 +128,7 @@ role_name = 'roller' ROLE = { 'id': role_id, 'name': role_name, + 'links': base_url + 'roles/' + role_id, } service_id = 's-123' @@ -134,6 +140,7 @@ SERVICE = { 'name': service_name, 'type': service_type, 'enabled': True, + 'links': base_url + 'services/' + service_id, } endpoint_id = 'e-123' @@ -148,6 +155,7 @@ ENDPOINT = { 'interface': endpoint_interface, 'service_id': service_id, 'enabled': True, + 'links': base_url + 'endpoints/' + endpoint_id, } user_id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' @@ -162,6 +170,7 @@ USER = { 'email': user_email, 'enabled': True, 'domain_id': domain_id, + 'links': base_url + 'users/' + user_id, } token_expires = '2014-01-01T00:00:00Z' @@ -292,7 +301,9 @@ class FakeIdentityv3Client(object): self.roles.resource_class = fakes.FakeResource(None, {}) self.services = mock.Mock() self.services.resource_class = fakes.FakeResource(None, {}) - self.service_catalog = mock.Mock() + self.session = mock.Mock() + self.session.auth.auth_ref.service_catalog.resource_class = \ + fakes.FakeResource(None, {}) self.users = mock.Mock() self.users.resource_class = fakes.FakeResource(None, {}) self.role_assignments = mock.Mock() diff --git a/openstackclient/tests/identity/v3/test_project.py b/openstackclient/tests/identity/v3/test_project.py index 2e7bc54b..1060a277 100644 --- a/openstackclient/tests/identity/v3/test_project.py +++ b/openstackclient/tests/identity/v3/test_project.py @@ -533,9 +533,6 @@ class TestProjectSet(TestProject): # Set expected values kwargs = { - 'description': identity_fakes.project_description, - 'domain': identity_fakes.domain_id, - 'enabled': True, 'name': 'qwerty', } # ProjectManager.update(project, name=, domain=, description=, @@ -564,9 +561,6 @@ class TestProjectSet(TestProject): # Set expected values kwargs = { 'description': 'new desc', - 'domain': identity_fakes.domain_id, - 'enabled': True, - 'name': identity_fakes.project_name, } self.projects_mock.update.assert_called_with( identity_fakes.project_id, @@ -590,10 +584,7 @@ class TestProjectSet(TestProject): # Set expected values kwargs = { - 'description': identity_fakes.project_description, - 'domain': identity_fakes.domain_id, 'enabled': True, - 'name': identity_fakes.project_name, } self.projects_mock.update.assert_called_with( identity_fakes.project_id, @@ -617,10 +608,7 @@ class TestProjectSet(TestProject): # Set expected values kwargs = { - 'description': identity_fakes.project_description, - 'domain': identity_fakes.domain_id, 'enabled': False, - 'name': identity_fakes.project_name, } self.projects_mock.update.assert_called_with( identity_fakes.project_id, @@ -644,10 +632,6 @@ class TestProjectSet(TestProject): # Set expected values kwargs = { - 'description': identity_fakes.project_description, - 'domain': identity_fakes.domain_id, - 'enabled': True, - 'name': identity_fakes.project_name, 'fee': 'fi', 'fo': 'fum', } diff --git a/openstackclient/tests/identity/v3/test_service.py b/openstackclient/tests/identity/v3/test_service.py index 6733f7fa..57db77b1 100644 --- a/openstackclient/tests/identity/v3/test_service.py +++ b/openstackclient/tests/identity/v3/test_service.py @@ -267,9 +267,7 @@ class TestServiceSet(TestService): # Set expected values kwargs = { - 'name': identity_fakes.service_name, 'type': identity_fakes.service_type, - 'enabled': True, } # ServiceManager.update(service, name=, type=, enabled=, **kwargs) self.services_mock.update.assert_called_with( @@ -297,8 +295,6 @@ class TestServiceSet(TestService): # Set expected values kwargs = { 'name': identity_fakes.service_name, - 'type': identity_fakes.service_type, - 'enabled': True, } # ServiceManager.update(service, name=, type=, enabled=, **kwargs) self.services_mock.update.assert_called_with( @@ -325,8 +321,6 @@ class TestServiceSet(TestService): # Set expected values kwargs = { - 'name': identity_fakes.service_name, - 'type': identity_fakes.service_type, 'enabled': True, } # ServiceManager.update(service, name=, type=, enabled=, **kwargs) @@ -354,8 +348,6 @@ class TestServiceSet(TestService): # Set expected values kwargs = { - 'name': identity_fakes.service_name, - 'type': identity_fakes.service_type, 'enabled': False, } # ServiceManager.update(service, name=, type=, enabled=, **kwargs) diff --git a/openstackclient/tests/identity/v3/test_token.py b/openstackclient/tests/identity/v3/test_token.py index 8888b931..dbe85555 100644 --- a/openstackclient/tests/identity/v3/test_token.py +++ b/openstackclient/tests/identity/v3/test_token.py @@ -23,7 +23,8 @@ class TestToken(identity_fakes.TestIdentityv3): super(TestToken, self).setUp() # Get a shortcut to the Service Catalog Mock - self.sc_mock = self.app.client_manager.identity.service_catalog + session = self.app.client_manager.identity.session + self.sc_mock = session.auth.auth_ref.service_catalog self.sc_mock.reset_mock() diff --git a/openstackclient/volume/client.py b/openstackclient/volume/client.py index f71fbe8b..58cb267e 100644 --- a/openstackclient/volume/client.py +++ b/openstackclient/volume/client.py @@ -68,7 +68,7 @@ def make_client(instance): else: # password flow client.client.management_url = instance.get_endpoint_for_service_type( - API_NAME) + API_NAME, region_name=instance._region_name) client.client.service_catalog = instance._service_catalog client.client.auth_token = instance._token |
