Skip to content

Commit 6e3f717

Browse files
Jenkinsopenstack-gerrit
authored andcommitted
Merge "Support deleting multi address scopes in networkv2"
2 parents 1dfc7d4 + 537f5cb commit 6e3f717

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)