Skip to content

Commit 537f5cb

Browse files
author
Huanxuan Ao
committed
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
1 parent 9da02d1 commit 537f5cb

4 files changed

Lines changed: 104 additions & 15 deletions

File tree

doc/source/command-objects/address-scope.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,18 @@ Create new address scope
5050
address scope delete
5151
--------------------
5252
53-
Delete an address scope
53+
Delete address scope(s)
5454
5555
.. program:: address scope delete
5656
.. code:: bash
5757
5858
os address scope delete
59-
<address-scope>
59+
<address-scope> [<address-scope> ...]
6060
6161
.. _address_scope_delete-address-scope:
6262
.. describe:: <address-scope>
6363
64-
Address scope to delete (name or ID)
64+
Address scope(s) to delete (name or ID)
6565
6666
address scope list
6767
------------------

openstackclient/network/v2/address_scope.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,22 +98,38 @@ def take_action(self, parsed_args):
9898

9999

100100
class DeleteAddressScope(command.Command):
101-
"""Delete an address scope"""
101+
"""Delete address scope(s)"""
102102

103103
def get_parser(self, prog_name):
104104
parser = super(DeleteAddressScope, self).get_parser(prog_name)
105105
parser.add_argument(
106106
'address_scope',
107107
metavar="<address-scope>",
108-
help=_("Address scope to delete (name or ID)")
108+
nargs='+',
109+
help=_("Address scope(s) to delete (name or ID)")
109110
)
110111

111112
return parser
112113

113114
def take_action(self, parsed_args):
114115
client = self.app.client_manager.network
115-
obj = client.find_address_scope(parsed_args.address_scope)
116-
client.delete_address_scope(obj)
116+
result = 0
117+
118+
for scope in parsed_args.address_scope:
119+
try:
120+
obj = client.find_address_scope(scope, ignore_missing=False)
121+
client.delete_address_scope(obj)
122+
except Exception as e:
123+
result += 1
124+
self.app.log.error(_("Failed to delete address scope with "
125+
"name or ID '%(scope)s': %(e)s")
126+
% {'scope': scope, 'e': e})
127+
128+
if result > 0:
129+
total = len(parsed_args.address_scope)
130+
msg = (_("%(result)s of %(total)s address scopes failed "
131+
"to delete.") % {'result': result, 'total': total})
132+
raise exceptions.CommandError(msg)
117133

118134

119135
class ListAddressScope(command.Lister):

openstackclient/tests/network/v2/fakes.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,25 @@ def create_address_scopes(attrs=None, count=2):
127127

128128
return address_scopes
129129

130+
@staticmethod
131+
def get_address_scopes(address_scopes=None, count=2):
132+
"""Get an iterable MagicMock object with a list of faked address scopes.
133+
134+
If address scopes list is provided, then initialize the Mock object
135+
with the list. Otherwise create one.
136+
137+
:param List address scopes:
138+
A list of FakeResource objects faking address scopes
139+
:param int count:
140+
The number of address scopes to fake
141+
:return:
142+
An iterable Mock object with side_effect set to a list of faked
143+
address scopes
144+
"""
145+
if address_scopes is None:
146+
address_scopes = FakeAddressScope.create_address_scopes(count)
147+
return mock.MagicMock(side_effect=address_scopes)
148+
130149

131150
class FakeAvailabilityZone(object):
132151
"""Fake one or more network availability zones (AZs)."""

openstackclient/tests/network/v2/test_address_scope.py

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import copy
1515
import mock
1616

17+
from mock import call
1718
from openstackclient.common import exceptions
1819
from openstackclient.network.v2 import address_scope
1920
from openstackclient.tests import fakes
@@ -168,33 +169,86 @@ def test_create_no_share(self):
168169
class TestDeleteAddressScope(TestAddressScope):
169170

170171
# The address scope to delete.
171-
_address_scope = (
172-
network_fakes.FakeAddressScope.create_one_address_scope())
172+
_address_scopes = (
173+
network_fakes.FakeAddressScope.create_address_scopes(count=2))
173174

174175
def setUp(self):
175176
super(TestDeleteAddressScope, self).setUp()
176177
self.network.delete_address_scope = mock.Mock(return_value=None)
177-
self.network.find_address_scope = mock.Mock(
178-
return_value=self._address_scope)
178+
self.network.find_address_scope = (
179+
network_fakes.FakeAddressScope.get_address_scopes(
180+
address_scopes=self._address_scopes)
181+
)
179182

180183
# Get the command object to test
181184
self.cmd = address_scope.DeleteAddressScope(self.app, self.namespace)
182185

183-
def test_delete(self):
186+
def test_address_scope_delete(self):
184187
arglist = [
185-
self._address_scope.name,
188+
self._address_scopes[0].name,
186189
]
187190
verifylist = [
188-
('address_scope', self._address_scope.name),
191+
('address_scope', [self._address_scopes[0].name]),
189192
]
190193

191194
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
192195

193196
result = self.cmd.take_action(parsed_args)
197+
self.network.find_address_scope.assert_called_once_with(
198+
self._address_scopes[0].name, ignore_missing=False)
194199
self.network.delete_address_scope.assert_called_once_with(
195-
self._address_scope)
200+
self._address_scopes[0])
196201
self.assertIsNone(result)
197202

203+
def test_multi_address_scopes_delete(self):
204+
arglist = []
205+
verifylist = []
206+
207+
for a in self._address_scopes:
208+
arglist.append(a.name)
209+
verifylist = [
210+
('address_scope', arglist),
211+
]
212+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
213+
214+
result = self.cmd.take_action(parsed_args)
215+
216+
calls = []
217+
for a in self._address_scopes:
218+
calls.append(call(a))
219+
self.network.delete_address_scope.assert_has_calls(calls)
220+
self.assertIsNone(result)
221+
222+
def test_multi_address_scopes_delete_with_exception(self):
223+
arglist = [
224+
self._address_scopes[0].name,
225+
'unexist_address_scope',
226+
]
227+
verifylist = [
228+
('address_scope',
229+
[self._address_scopes[0].name, 'unexist_address_scope']),
230+
]
231+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
232+
233+
find_mock_result = [self._address_scopes[0], exceptions.CommandError]
234+
self.network.find_address_scope = (
235+
mock.MagicMock(side_effect=find_mock_result)
236+
)
237+
238+
try:
239+
self.cmd.take_action(parsed_args)
240+
self.fail('CommandError should be raised.')
241+
except exceptions.CommandError as e:
242+
self.assertEqual('1 of 2 address scopes failed to delete.', str(e))
243+
244+
self.network.find_address_scope.assert_any_call(
245+
self._address_scopes[0].name, ignore_missing=False)
246+
self.network.find_address_scope.assert_any_call(
247+
'unexist_address_scope', ignore_missing=False)
248+
self.network.delete_address_scope.assert_called_once_with(
249+
self._address_scopes[0]
250+
)
251+
198252

199253
class TestListAddressScope(TestAddressScope):
200254

0 commit comments

Comments
 (0)