Skip to content

Commit 365d4c9

Browse files
Jenkinsopenstack-gerrit
authored andcommitted
Merge "Error handling for delete commands in identity"
2 parents 08fc39e + 96578cb commit 365d4c9

16 files changed

Lines changed: 392 additions & 45 deletions

File tree

openstackclient/identity/v2_0/project.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from keystoneauth1 import exceptions as ks_exc
2121
from osc_lib.cli import parseractions
2222
from osc_lib.command import command
23+
from osc_lib import exceptions
2324
from osc_lib import utils
2425
import six
2526

@@ -117,12 +118,25 @@ def get_parser(self, prog_name):
117118
def take_action(self, parsed_args):
118119
identity_client = self.app.client_manager.identity
119120

121+
errors = 0
120122
for project in parsed_args.projects:
121-
project_obj = utils.find_resource(
122-
identity_client.tenants,
123-
project,
124-
)
125-
identity_client.tenants.delete(project_obj.id)
123+
try:
124+
project_obj = utils.find_resource(
125+
identity_client.tenants,
126+
project,
127+
)
128+
identity_client.tenants.delete(project_obj.id)
129+
except Exception as e:
130+
errors += 1
131+
LOG.error(_("Failed to delete project with "
132+
"name or ID '%(project)s': %(e)s"),
133+
{'project': project, 'e': e})
134+
135+
if errors > 0:
136+
total = len(parsed_args.projects)
137+
msg = (_("%(errors)s of %(total)s projects failed "
138+
"to delete.") % {'errors': errors, 'total': total})
139+
raise exceptions.CommandError(msg)
126140

127141

128142
class ListProject(command.Lister):

openstackclient/identity/v2_0/role.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,25 @@ def get_parser(self, prog_name):
124124
def take_action(self, parsed_args):
125125
identity_client = self.app.client_manager.identity
126126

127+
errors = 0
127128
for role in parsed_args.roles:
128-
role_obj = utils.find_resource(
129-
identity_client.roles,
130-
role,
131-
)
132-
identity_client.roles.delete(role_obj.id)
129+
try:
130+
role_obj = utils.find_resource(
131+
identity_client.roles,
132+
role,
133+
)
134+
identity_client.roles.delete(role_obj.id)
135+
except Exception as e:
136+
errors += 1
137+
LOG.error(_("Failed to delete role with "
138+
"name or ID '%(role)s': %(e)s"),
139+
{'role': role, 'e': e})
140+
141+
if errors > 0:
142+
total = len(parsed_args.roles)
143+
msg = (_("%(errors)s of %(total)s roles failed "
144+
"to delete.") % {'errors': errors, 'total': total})
145+
raise exceptions.CommandError(msg)
133146

134147

135148
class ListRole(command.Lister):

openstackclient/identity/v2_0/user.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
from keystoneauth1 import exceptions as ks_exc
2121
from osc_lib.command import command
22+
from osc_lib import exceptions
2223
from osc_lib import utils
2324
import six
2425

@@ -145,12 +146,25 @@ def get_parser(self, prog_name):
145146
def take_action(self, parsed_args):
146147
identity_client = self.app.client_manager.identity
147148

149+
errors = 0
148150
for user in parsed_args.users:
149-
user_obj = utils.find_resource(
150-
identity_client.users,
151-
user,
152-
)
153-
identity_client.users.delete(user_obj.id)
151+
try:
152+
user_obj = utils.find_resource(
153+
identity_client.users,
154+
user,
155+
)
156+
identity_client.users.delete(user_obj.id)
157+
except Exception as e:
158+
errors += 1
159+
LOG.error(_("Failed to delete user with "
160+
"name or ID '%(user)s': %(e)s"),
161+
{'user': user, 'e': e})
162+
163+
if errors > 0:
164+
total = len(parsed_args.users)
165+
msg = (_("%(errors)s of %(total)s users failed "
166+
"to delete.") % {'errors': errors, 'total': total})
167+
raise exceptions.CommandError(msg)
154168

155169

156170
class ListUser(command.Lister):

openstackclient/identity/v3/group.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
from keystoneauth1 import exceptions as ks_exc
2222
from osc_lib.command import command
23+
from osc_lib import exceptions
2324
from osc_lib import utils
2425
import six
2526

@@ -194,11 +195,24 @@ def get_parser(self, prog_name):
194195
def take_action(self, parsed_args):
195196
identity_client = self.app.client_manager.identity
196197

198+
errors = 0
197199
for group in parsed_args.groups:
198-
group_obj = common.find_group(identity_client,
199-
group,
200-
parsed_args.domain)
201-
identity_client.groups.delete(group_obj.id)
200+
try:
201+
group_obj = common.find_group(identity_client,
202+
group,
203+
parsed_args.domain)
204+
identity_client.groups.delete(group_obj.id)
205+
except Exception as e:
206+
errors += 1
207+
LOG.error(_("Failed to delete group with "
208+
"name or ID '%(group)s': %(e)s"),
209+
{'group': group, 'e': e})
210+
211+
if errors > 0:
212+
total = len(parsed_args.groups)
213+
msg = (_("%(errors)s of %(total)s groups failed "
214+
"to delete.") % {'errors': errors, 'total': total})
215+
raise exceptions.CommandError(msg)
202216

203217

204218
class ListGroup(command.Lister):

openstackclient/identity/v3/project.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from keystoneauth1 import exceptions as ks_exc
2121
from osc_lib.cli import parseractions
2222
from osc_lib.command import command
23+
from osc_lib import exceptions
2324
from osc_lib import utils
2425
import six
2526

@@ -148,15 +149,28 @@ def take_action(self, parsed_args):
148149
domain = None
149150
if parsed_args.domain:
150151
domain = common.find_domain(identity_client, parsed_args.domain)
152+
errors = 0
151153
for project in parsed_args.projects:
152-
if domain is not None:
153-
project_obj = utils.find_resource(identity_client.projects,
154-
project,
155-
domain_id=domain.id)
156-
else:
157-
project_obj = utils.find_resource(identity_client.projects,
158-
project)
159-
identity_client.projects.delete(project_obj.id)
154+
try:
155+
if domain is not None:
156+
project_obj = utils.find_resource(identity_client.projects,
157+
project,
158+
domain_id=domain.id)
159+
else:
160+
project_obj = utils.find_resource(identity_client.projects,
161+
project)
162+
identity_client.projects.delete(project_obj.id)
163+
except Exception as e:
164+
errors += 1
165+
LOG.error(_("Failed to delete project with "
166+
"name or ID '%(project)s': %(e)s"),
167+
{'project': project, 'e': e})
168+
169+
if errors > 0:
170+
total = len(parsed_args.projects)
171+
msg = (_("%(errors)s of %(total)s projects failed "
172+
"to delete.") % {'errors': errors, 'total': total})
173+
raise exceptions.CommandError(msg)
160174

161175

162176
class ListProject(command.Lister):

openstackclient/identity/v3/role.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
from keystoneauth1 import exceptions as ks_exc
2222
from osc_lib.command import command
23+
from osc_lib import exceptions
2324
from osc_lib import utils
2425
import six
2526

@@ -223,14 +224,26 @@ def take_action(self, parsed_args):
223224
if parsed_args.domain:
224225
domain_id = common.find_domain(identity_client,
225226
parsed_args.domain).id
226-
227+
errors = 0
227228
for role in parsed_args.roles:
228-
role_obj = utils.find_resource(
229-
identity_client.roles,
230-
role,
231-
domain_id=domain_id
232-
)
233-
identity_client.roles.delete(role_obj.id)
229+
try:
230+
role_obj = utils.find_resource(
231+
identity_client.roles,
232+
role,
233+
domain_id=domain_id
234+
)
235+
identity_client.roles.delete(role_obj.id)
236+
except Exception as e:
237+
errors += 1
238+
LOG.error(_("Failed to delete role with "
239+
"name or ID '%(role)s': %(e)s"),
240+
{'role': role, 'e': e})
241+
242+
if errors > 0:
243+
total = len(parsed_args.roles)
244+
msg = (_("%(errors)s of %(total)s roles failed "
245+
"to delete.") % {'errors': errors, 'total': total})
246+
raise exceptions.CommandError(msg)
234247

235248

236249
class ListRole(command.Lister):

openstackclient/identity/v3/trust.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,20 @@
1414
"""Identity v3 Trust action implementations"""
1515

1616
import datetime
17+
import logging
1718

1819
from osc_lib.command import command
20+
from osc_lib import exceptions
1921
from osc_lib import utils
2022
import six
2123

2224
from openstackclient.i18n import _
2325
from openstackclient.identity import common
2426

2527

28+
LOG = logging.getLogger(__name__)
29+
30+
2631
class CreateTrust(command.ShowOne):
2732
_description = _("Create new trust")
2833

@@ -145,9 +150,24 @@ def get_parser(self, prog_name):
145150

146151
def take_action(self, parsed_args):
147152
identity_client = self.app.client_manager.identity
148-
for t in parsed_args.trust:
149-
trust_obj = utils.find_resource(identity_client.trusts, t)
150-
identity_client.trusts.delete(trust_obj.id)
153+
154+
errors = 0
155+
for trust in parsed_args.trust:
156+
try:
157+
trust_obj = utils.find_resource(identity_client.trusts,
158+
trust)
159+
identity_client.trusts.delete(trust_obj.id)
160+
except Exception as e:
161+
errors += 1
162+
LOG.error(_("Failed to delete trust with "
163+
"name or ID '%(trust)s': %(e)s"),
164+
{'trust': trust, 'e': e})
165+
166+
if errors > 0:
167+
total = len(parsed_args.trust)
168+
msg = (_("%(errors)s of %(total)s trusts failed "
169+
"to delete.") % {'errors': errors, 'total': total})
170+
raise exceptions.CommandError(msg)
151171

152172

153173
class ListTrust(command.Lister):

openstackclient/identity/v3/user.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
from keystoneauth1 import exceptions as ks_exc
2222
from osc_lib.command import command
23+
from osc_lib import exceptions
2324
from osc_lib import utils
2425
import six
2526

@@ -161,15 +162,28 @@ def take_action(self, parsed_args):
161162
domain = None
162163
if parsed_args.domain:
163164
domain = common.find_domain(identity_client, parsed_args.domain)
165+
errors = 0
164166
for user in parsed_args.users:
165-
if domain is not None:
166-
user_obj = utils.find_resource(identity_client.users,
167-
user,
168-
domain_id=domain.id)
169-
else:
170-
user_obj = utils.find_resource(identity_client.users,
171-
user)
172-
identity_client.users.delete(user_obj.id)
167+
try:
168+
if domain is not None:
169+
user_obj = utils.find_resource(identity_client.users,
170+
user,
171+
domain_id=domain.id)
172+
else:
173+
user_obj = utils.find_resource(identity_client.users,
174+
user)
175+
identity_client.users.delete(user_obj.id)
176+
except Exception as e:
177+
errors += 1
178+
LOG.error(_("Failed to delete user with "
179+
"name or ID '%(user)s': %(e)s"),
180+
{'user': user, 'e': e})
181+
182+
if errors > 0:
183+
total = len(parsed_args.users)
184+
msg = (_("%(errors)s of %(total)s users failed "
185+
"to delete.") % {'errors': errors, 'total': total})
186+
raise exceptions.CommandError(msg)
173187

174188

175189
class ListUser(command.Lister):

openstackclient/tests/unit/identity/v2_0/test_project.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@
1313
# under the License.
1414
#
1515

16+
import mock
17+
1618
from keystoneauth1 import exceptions as ks_exc
1719
from osc_lib import exceptions
20+
from osc_lib import utils
1821

1922
from openstackclient.identity.v2_0 import project
2023
from openstackclient.tests.unit.identity.v2_0 import fakes as identity_fakes
@@ -302,6 +305,32 @@ def test_project_delete_no_options(self):
302305
)
303306
self.assertIsNone(result)
304307

308+
@mock.patch.object(utils, 'find_resource')
309+
def test_delete_multi_projects_with_exception(self, find_mock):
310+
find_mock.side_effect = [self.fake_project,
311+
exceptions.CommandError]
312+
arglist = [
313+
self.fake_project.id,
314+
'unexist_project',
315+
]
316+
verifylist = [
317+
('projects', arglist),
318+
]
319+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
320+
321+
try:
322+
self.cmd.take_action(parsed_args)
323+
self.fail('CommandError should be raised.')
324+
except exceptions.CommandError as e:
325+
self.assertEqual('1 of 2 projects failed to delete.',
326+
str(e))
327+
328+
find_mock.assert_any_call(self.projects_mock, self.fake_project.id)
329+
find_mock.assert_any_call(self.projects_mock, 'unexist_project')
330+
331+
self.assertEqual(2, find_mock.call_count)
332+
self.projects_mock.delete.assert_called_once_with(self.fake_project.id)
333+
305334

306335
class TestProjectList(TestProject):
307336

0 commit comments

Comments
 (0)