Support multi-delete for commands in identity V2

Commands are "ec2 credentials delete", "service delete", "endpoint delete".
Also update their unit tests and functional tests.

Partial-Bug: #1592906
Change-Id: I1a0b7160b803a523646d09d030e6f112c81c4c24
This commit is contained in:
sunyajing 2016-06-23 12:55:54 +08:00 committed by Steve Martinelli
parent 5b144334bf
commit 6df09fd377
12 changed files with 108 additions and 22 deletions

View File

@ -55,7 +55,7 @@ Delete EC2 credentials
os ec2 credentials delete os ec2 credentials delete
[--user <user>] [--user <user>]
[--user-domain <user-domain>] [--user-domain <user-domain>]
<access-key> <access-key> [<access-key> ...]
.. option:: --user <user> .. option:: --user <user>
@ -71,7 +71,7 @@ Delete EC2 credentials
.. _ec2_credentials_delete-access-key: .. _ec2_credentials_delete-access-key:
.. describe:: access-key .. describe:: access-key
Credentials access key Credentials access key(s)
The :option:`--user` option is typically only useful for admin users, but The :option:`--user` option is typically only useful for admin users, but
may be allowed for other users depending on the policy of the cloud and may be allowed for other users depending on the policy of the cloud and

View File

@ -81,18 +81,18 @@ Create new endpoint
endpoint delete endpoint delete
--------------- ---------------
Delete endpoint Delete endpoint(s)
.. program:: endpoint delete .. program:: endpoint delete
.. code:: bash .. code:: bash
os endpoint delete os endpoint delete
<endpoint-id> <endpoint-id> [<endpoint-id> ...]
.. _endpoint_delete-endpoint: .. _endpoint_delete-endpoint:
.. describe:: <endpoint-id> .. describe:: <endpoint-id>
Endpoint to delete (ID only) Endpoint(s) to delete (ID only)
endpoint list endpoint list
------------- -------------

View File

@ -46,18 +46,18 @@ Create new service
service delete service delete
-------------- --------------
Delete service Delete service(s)
.. program:: service delete .. program:: service delete
.. code-block:: bash .. code-block:: bash
os service delete os service delete
<service> <service> [<service> ...]
.. _service_delete-type: .. _service_delete-type:
.. describe:: <service> .. describe:: <service>
Service to delete (type, name or ID) Service(s) to delete (type, name or ID)
service list service list
------------ ------------

View File

@ -25,6 +25,14 @@ class EC2CredentialsTests(common.IdentityTests):
) )
self.assertEqual(0, len(raw_output)) self.assertEqual(0, len(raw_output))
def test_ec2_credentials_multi_delete(self):
access_key_1 = self._create_dummy_ec2_credentials(add_clean_up=False)
access_key_2 = self._create_dummy_ec2_credentials(add_clean_up=False)
raw_output = self.openstack(
'ec2 credentials delete ' + access_key_1 + ' ' + access_key_2
)
self.assertEqual(0, len(raw_output))
def test_ec2_credentials_list(self): def test_ec2_credentials_list(self):
self._create_dummy_ec2_credentials() self._create_dummy_ec2_credentials()
raw_output = self.openstack('ec2 credentials list') raw_output = self.openstack('ec2 credentials list')

View File

@ -24,6 +24,13 @@ class EndpointTests(common.IdentityTests):
'endpoint delete %s' % endpoint_id) 'endpoint delete %s' % endpoint_id)
self.assertEqual(0, len(raw_output)) self.assertEqual(0, len(raw_output))
def test_endpoint_multi_delete(self):
endpoint_id_1 = self._create_dummy_endpoint(add_clean_up=False)
endpoint_id_2 = self._create_dummy_endpoint(add_clean_up=False)
raw_output = self.openstack(
'endpoint delete ' + endpoint_id_1 + ' ' + endpoint_id_2)
self.assertEqual(0, len(raw_output))
def test_endpoint_list(self): def test_endpoint_list(self):
endpoint_id = self._create_dummy_endpoint() endpoint_id = self._create_dummy_endpoint()
raw_output = self.openstack('endpoint list') raw_output = self.openstack('endpoint list')

View File

@ -23,6 +23,13 @@ class ServiceTests(common.IdentityTests):
raw_output = self.openstack('service delete %s' % service_name) raw_output = self.openstack('service delete %s' % service_name)
self.assertEqual(0, len(raw_output)) self.assertEqual(0, len(raw_output))
def test_service_multi_delete(self):
service_name_1 = self._create_dummy_service(add_clean_up=False)
service_name_2 = self._create_dummy_service(add_clean_up=False)
raw_output = self.openstack(
'service delete ' + service_name_1 + ' ' + service_name_2)
self.assertEqual(0, len(raw_output))
def test_service_list(self): def test_service_list(self):
self._create_dummy_service() self._create_dummy_service()
raw_output = self.openstack('service list') raw_output = self.openstack('service list')

View File

@ -16,13 +16,19 @@
"""Identity v2 EC2 Credentials action implementations""" """Identity v2 EC2 Credentials action implementations"""
import logging
from osc_lib.command import command from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils from osc_lib import utils
import six import six
from openstackclient.i18n import _ from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
class CreateEC2Creds(command.ShowOne): class CreateEC2Creds(command.ShowOne):
"""Create EC2 credentials""" """Create EC2 credentials"""
@ -85,9 +91,10 @@ class DeleteEC2Creds(command.Command):
def get_parser(self, prog_name): def get_parser(self, prog_name):
parser = super(DeleteEC2Creds, self).get_parser(prog_name) parser = super(DeleteEC2Creds, self).get_parser(prog_name)
parser.add_argument( parser.add_argument(
'access_key', 'access_keys',
metavar='<access-key>', metavar='<access-key>',
help=_('Credentials access key'), nargs='+',
help=_('Credentials access keys'),
) )
parser.add_argument( parser.add_argument(
'--user', '--user',
@ -108,7 +115,21 @@ class DeleteEC2Creds(command.Command):
# Get the user from the current auth # Get the user from the current auth
user = self.app.client_manager.auth_ref.user_id user = self.app.client_manager.auth_ref.user_id
identity_client.ec2.delete(user, parsed_args.access_key) result = 0
for access_key in parsed_args.access_keys:
try:
identity_client.ec2.delete(user, access_key)
except Exception as e:
result += 1
LOG.error(_("Failed to delete EC2 keys with "
"access key '%(access_key)s': %(e)s")
% {'access_key': access_key, 'e': e})
if result > 0:
total = len(parsed_args.access_keys)
msg = (_("%(result)s of %(total)s EC2 keys failed "
"to delete.") % {'result': result, 'total': total})
raise exceptions.CommandError(msg)
class ListEC2Creds(command.Lister): class ListEC2Creds(command.Lister):

View File

@ -15,7 +15,10 @@
"""Endpoint action implementations""" """Endpoint action implementations"""
import logging
from osc_lib.command import command from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils from osc_lib import utils
import six import six
@ -23,6 +26,9 @@ from openstackclient.i18n import _
from openstackclient.identity import common from openstackclient.identity import common
LOG = logging.getLogger(__name__)
class CreateEndpoint(command.ShowOne): class CreateEndpoint(command.ShowOne):
"""Create new endpoint""" """Create new endpoint"""
@ -74,20 +80,36 @@ class CreateEndpoint(command.ShowOne):
class DeleteEndpoint(command.Command): class DeleteEndpoint(command.Command):
"""Delete endpoint""" """Delete endpoint(s)"""
def get_parser(self, prog_name): def get_parser(self, prog_name):
parser = super(DeleteEndpoint, self).get_parser(prog_name) parser = super(DeleteEndpoint, self).get_parser(prog_name)
parser.add_argument( parser.add_argument(
'endpoint', 'endpoints',
metavar='<endpoint-id>', metavar='<endpoint-id>',
help=_('Endpoint to delete (ID only)'), nargs='+',
help=_('Endpoint(s) to delete (ID only)'),
) )
return parser return parser
def take_action(self, parsed_args): def take_action(self, parsed_args):
identity_client = self.app.client_manager.identity identity_client = self.app.client_manager.identity
identity_client.endpoints.delete(parsed_args.endpoint)
result = 0
for endpoint in parsed_args.endpoints:
try:
identity_client.endpoints.delete(endpoint)
except Exception as e:
result += 1
LOG.error(_("Failed to delete endpoint with "
"ID '%(endpoint)s': %(e)s")
% {'endpoint': endpoint, 'e': e})
if result > 0:
total = len(parsed_args.endpoints)
msg = (_("%(result)s of %(total)s endpoints failed "
"to delete.") % {'result': result, 'total': total})
raise exceptions.CommandError(msg)
class ListEndpoint(command.Lister): class ListEndpoint(command.Lister):

View File

@ -91,21 +91,37 @@ class CreateService(command.ShowOne):
class DeleteService(command.Command): class DeleteService(command.Command):
"""Delete service""" """Delete service(s)"""
def get_parser(self, prog_name): def get_parser(self, prog_name):
parser = super(DeleteService, self).get_parser(prog_name) parser = super(DeleteService, self).get_parser(prog_name)
parser.add_argument( parser.add_argument(
'service', 'services',
metavar='<service>', metavar='<service>',
help=_('Service to delete (type, name or ID)'), nargs='+',
help=_('Service(s) to delete (type, name or ID)'),
) )
return parser return parser
def take_action(self, parsed_args): def take_action(self, parsed_args):
identity_client = self.app.client_manager.identity identity_client = self.app.client_manager.identity
service = common.find_service(identity_client, parsed_args.service)
result = 0
for service in parsed_args.services:
try:
service = common.find_service(identity_client, service)
identity_client.services.delete(service.id) identity_client.services.delete(service.id)
except Exception as e:
result += 1
LOG.error(_("Failed to delete service with "
"name or ID '%(service)s': %(e)s")
% {'service': service, 'e': e})
if result > 0:
total = len(parsed_args.services)
msg = (_("%(result)s of %(total)s services failed "
"to delete.") % {'result': result, 'total': total})
raise exceptions.CommandError(msg)
class ListService(command.Lister): class ListService(command.Lister):

View File

@ -112,7 +112,7 @@ class TestEndpointDelete(TestEndpoint):
self.fake_endpoint.id, self.fake_endpoint.id,
] ]
verifylist = [ verifylist = [
('endpoint', self.fake_endpoint.id), ('endpoints', [self.fake_endpoint.id]),
] ]
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)

View File

@ -190,7 +190,7 @@ class TestServiceDelete(TestService):
identity_fakes.service_name, identity_fakes.service_name,
] ]
verifylist = [ verifylist = [
('service', identity_fakes.service_name), ('services', [identity_fakes.service_name]),
] ]
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)

View File

@ -0,0 +1,5 @@
---
features:
- Support bulk deletion for ``ec2 credentials delete``, ``endpoint delete``,
``service delete`` in identity V2.0 .
[Bug `1592906 <https://bugs.launchpad.net/bugs/1592906>`_]