Support deleting multi address scopes in networkv2
This patch adds support for deleting multi address scopes by using "address scope delete" command. Change-Id: Ic8d3ebc17db44ca5d42c336d2c4d5633f70d4e8b Partially-Implements: blueprint multi-argument-network
This commit is contained in:
		| @@ -50,18 +50,18 @@ Create new address scope | |||||||
| address scope delete | address scope delete | ||||||
| -------------------- | -------------------- | ||||||
|  |  | ||||||
| Delete an address scope | Delete address scope(s) | ||||||
|  |  | ||||||
| .. program:: address scope delete | .. program:: address scope delete | ||||||
| .. code:: bash | .. code:: bash | ||||||
|  |  | ||||||
|     os address scope delete |     os address scope delete | ||||||
|         <address-scope> |         <address-scope> [<address-scope> ...] | ||||||
|  |  | ||||||
| .. _address_scope_delete-address-scope: | .. _address_scope_delete-address-scope: | ||||||
| .. describe:: <address-scope> | .. describe:: <address-scope> | ||||||
|  |  | ||||||
|     Address scope to delete (name or ID) |     Address scope(s) to delete (name or ID) | ||||||
|  |  | ||||||
| address scope list | address scope list | ||||||
| ------------------ | ------------------ | ||||||
|   | |||||||
| @@ -98,22 +98,38 @@ class CreateAddressScope(command.ShowOne): | |||||||
|  |  | ||||||
|  |  | ||||||
| class DeleteAddressScope(command.Command): | class DeleteAddressScope(command.Command): | ||||||
|     """Delete an address scope""" |     """Delete address scope(s)""" | ||||||
|  |  | ||||||
|     def get_parser(self, prog_name): |     def get_parser(self, prog_name): | ||||||
|         parser = super(DeleteAddressScope, self).get_parser(prog_name) |         parser = super(DeleteAddressScope, self).get_parser(prog_name) | ||||||
|         parser.add_argument( |         parser.add_argument( | ||||||
|             'address_scope', |             'address_scope', | ||||||
|             metavar="<address-scope>", |             metavar="<address-scope>", | ||||||
|             help=_("Address scope to delete (name or ID)") |             nargs='+', | ||||||
|  |             help=_("Address scope(s) to delete (name or ID)") | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         return parser |         return parser | ||||||
|  |  | ||||||
|     def take_action(self, parsed_args): |     def take_action(self, parsed_args): | ||||||
|         client = self.app.client_manager.network |         client = self.app.client_manager.network | ||||||
|         obj = client.find_address_scope(parsed_args.address_scope) |         result = 0 | ||||||
|         client.delete_address_scope(obj) |  | ||||||
|  |         for scope in parsed_args.address_scope: | ||||||
|  |             try: | ||||||
|  |                 obj = client.find_address_scope(scope, ignore_missing=False) | ||||||
|  |                 client.delete_address_scope(obj) | ||||||
|  |             except Exception as e: | ||||||
|  |                 result += 1 | ||||||
|  |                 self.app.log.error(_("Failed to delete address scope with " | ||||||
|  |                                    "name or ID '%(scope)s': %(e)s") | ||||||
|  |                                    % {'scope': scope, 'e': e}) | ||||||
|  |  | ||||||
|  |         if result > 0: | ||||||
|  |             total = len(parsed_args.address_scope) | ||||||
|  |             msg = (_("%(result)s of %(total)s address scopes failed " | ||||||
|  |                    "to delete.") % {'result': result, 'total': total}) | ||||||
|  |             raise exceptions.CommandError(msg) | ||||||
|  |  | ||||||
|  |  | ||||||
| class ListAddressScope(command.Lister): | class ListAddressScope(command.Lister): | ||||||
|   | |||||||
| @@ -127,6 +127,25 @@ class FakeAddressScope(object): | |||||||
|  |  | ||||||
|         return address_scopes |         return address_scopes | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def get_address_scopes(address_scopes=None, count=2): | ||||||
|  |         """Get an iterable MagicMock object with a list of faked address scopes. | ||||||
|  |  | ||||||
|  |         If address scopes list is provided, then initialize the Mock object | ||||||
|  |         with the list. Otherwise create one. | ||||||
|  |  | ||||||
|  |         :param List address scopes: | ||||||
|  |             A list of FakeResource objects faking address scopes | ||||||
|  |         :param int count: | ||||||
|  |             The number of address scopes to fake | ||||||
|  |         :return: | ||||||
|  |             An iterable Mock object with side_effect set to a list of faked | ||||||
|  |             address scopes | ||||||
|  |         """ | ||||||
|  |         if address_scopes is None: | ||||||
|  |             address_scopes = FakeAddressScope.create_address_scopes(count) | ||||||
|  |         return mock.MagicMock(side_effect=address_scopes) | ||||||
|  |  | ||||||
|  |  | ||||||
| class FakeAvailabilityZone(object): | class FakeAvailabilityZone(object): | ||||||
|     """Fake one or more network availability zones (AZs).""" |     """Fake one or more network availability zones (AZs).""" | ||||||
|   | |||||||
| @@ -14,6 +14,7 @@ | |||||||
| import copy | import copy | ||||||
| import mock | import mock | ||||||
|  |  | ||||||
|  | from mock import call | ||||||
| from openstackclient.common import exceptions | from openstackclient.common import exceptions | ||||||
| from openstackclient.network.v2 import address_scope | from openstackclient.network.v2 import address_scope | ||||||
| from openstackclient.tests import fakes | from openstackclient.tests import fakes | ||||||
| @@ -168,33 +169,86 @@ class TestCreateAddressScope(TestAddressScope): | |||||||
| class TestDeleteAddressScope(TestAddressScope): | class TestDeleteAddressScope(TestAddressScope): | ||||||
|  |  | ||||||
|     # The address scope to delete. |     # The address scope to delete. | ||||||
|     _address_scope = ( |     _address_scopes = ( | ||||||
|         network_fakes.FakeAddressScope.create_one_address_scope()) |         network_fakes.FakeAddressScope.create_address_scopes(count=2)) | ||||||
|  |  | ||||||
|     def setUp(self): |     def setUp(self): | ||||||
|         super(TestDeleteAddressScope, self).setUp() |         super(TestDeleteAddressScope, self).setUp() | ||||||
|         self.network.delete_address_scope = mock.Mock(return_value=None) |         self.network.delete_address_scope = mock.Mock(return_value=None) | ||||||
|         self.network.find_address_scope = mock.Mock( |         self.network.find_address_scope = ( | ||||||
|             return_value=self._address_scope) |             network_fakes.FakeAddressScope.get_address_scopes( | ||||||
|  |                 address_scopes=self._address_scopes) | ||||||
|  |         ) | ||||||
|  |  | ||||||
|         # Get the command object to test |         # Get the command object to test | ||||||
|         self.cmd = address_scope.DeleteAddressScope(self.app, self.namespace) |         self.cmd = address_scope.DeleteAddressScope(self.app, self.namespace) | ||||||
|  |  | ||||||
|     def test_delete(self): |     def test_address_scope_delete(self): | ||||||
|         arglist = [ |         arglist = [ | ||||||
|             self._address_scope.name, |             self._address_scopes[0].name, | ||||||
|         ] |         ] | ||||||
|         verifylist = [ |         verifylist = [ | ||||||
|             ('address_scope', self._address_scope.name), |             ('address_scope', [self._address_scopes[0].name]), | ||||||
|         ] |         ] | ||||||
|  |  | ||||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) |         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||||
|  |  | ||||||
|         result = self.cmd.take_action(parsed_args) |         result = self.cmd.take_action(parsed_args) | ||||||
|  |         self.network.find_address_scope.assert_called_once_with( | ||||||
|  |             self._address_scopes[0].name, ignore_missing=False) | ||||||
|         self.network.delete_address_scope.assert_called_once_with( |         self.network.delete_address_scope.assert_called_once_with( | ||||||
|             self._address_scope) |             self._address_scopes[0]) | ||||||
|         self.assertIsNone(result) |         self.assertIsNone(result) | ||||||
|  |  | ||||||
|  |     def test_multi_address_scopes_delete(self): | ||||||
|  |         arglist = [] | ||||||
|  |         verifylist = [] | ||||||
|  |  | ||||||
|  |         for a in self._address_scopes: | ||||||
|  |             arglist.append(a.name) | ||||||
|  |         verifylist = [ | ||||||
|  |             ('address_scope', arglist), | ||||||
|  |         ] | ||||||
|  |         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||||
|  |  | ||||||
|  |         result = self.cmd.take_action(parsed_args) | ||||||
|  |  | ||||||
|  |         calls = [] | ||||||
|  |         for a in self._address_scopes: | ||||||
|  |             calls.append(call(a)) | ||||||
|  |         self.network.delete_address_scope.assert_has_calls(calls) | ||||||
|  |         self.assertIsNone(result) | ||||||
|  |  | ||||||
|  |     def test_multi_address_scopes_delete_with_exception(self): | ||||||
|  |         arglist = [ | ||||||
|  |             self._address_scopes[0].name, | ||||||
|  |             'unexist_address_scope', | ||||||
|  |         ] | ||||||
|  |         verifylist = [ | ||||||
|  |             ('address_scope', | ||||||
|  |              [self._address_scopes[0].name, 'unexist_address_scope']), | ||||||
|  |         ] | ||||||
|  |         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||||
|  |  | ||||||
|  |         find_mock_result = [self._address_scopes[0], exceptions.CommandError] | ||||||
|  |         self.network.find_address_scope = ( | ||||||
|  |             mock.MagicMock(side_effect=find_mock_result) | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         try: | ||||||
|  |             self.cmd.take_action(parsed_args) | ||||||
|  |             self.fail('CommandError should be raised.') | ||||||
|  |         except exceptions.CommandError as e: | ||||||
|  |             self.assertEqual('1 of 2 address scopes failed to delete.', str(e)) | ||||||
|  |  | ||||||
|  |         self.network.find_address_scope.assert_any_call( | ||||||
|  |             self._address_scopes[0].name, ignore_missing=False) | ||||||
|  |         self.network.find_address_scope.assert_any_call( | ||||||
|  |             'unexist_address_scope', ignore_missing=False) | ||||||
|  |         self.network.delete_address_scope.assert_called_once_with( | ||||||
|  |             self._address_scopes[0] | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestListAddressScope(TestAddressScope): | class TestListAddressScope(TestAddressScope): | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Huanxuan Ao
					Huanxuan Ao