From 1bb21c5bb3e1612cf4478465c1aa5a022b45f983 Mon Sep 17 00:00:00 2001 From: rabi Date: Fri, 19 Aug 2016 10:27:55 +0530 Subject: [PATCH] Delete RoleAssignment if user/group does not exist Currently deleting a user/group directly results in stack containing RoleAssignment resource stuck in DELETE_FAILED, when deleting the stack.This patch fixes it. Change-Id: I48d5e1a92b99fa7e495c6bb2f131f169b9cf8076 Related-Bug: #1614400 --- heat/engine/clients/os/keystone/__init__.py | 25 ++++++++++--------- .../openstack/keystone/role_assignments.py | 16 +++++++++--- heat/tests/clients/test_clients.py | 8 ++++++ .../keystone/test_role_assignments.py | 12 +++++++++ 4 files changed, 45 insertions(+), 16 deletions(-) diff --git a/heat/engine/clients/os/keystone/__init__.py b/heat/engine/clients/os/keystone/__init__.py index 52b160a223..1847053387 100644 --- a/heat/engine/clients/os/keystone/__init__.py +++ b/heat/engine/clients/os/keystone/__init__.py @@ -11,7 +11,7 @@ # License for the specific language governing permissions and limitations # under the License. -from keystoneclient import exceptions +from keystoneauth1 import exceptions as ks_exceptions from heat.common import exception from heat.engine.clients import client_plugin @@ -20,7 +20,7 @@ from heat.engine.clients.os.keystone import heat_keystoneclient as hkc class KeystoneClientPlugin(client_plugin.ClientPlugin): - exceptions_module = exceptions + exceptions_module = [ks_exceptions, exception] service_types = [IDENTITY] = ['identity'] @@ -28,19 +28,20 @@ class KeystoneClientPlugin(client_plugin.ClientPlugin): return hkc.KeystoneClient(self.context) def is_not_found(self, ex): - return isinstance(ex, exceptions.NotFound) + return isinstance(ex, (ks_exceptions.NotFound, + exception.EntityNotFound)) def is_over_limit(self, ex): - return isinstance(ex, exceptions.RequestEntityTooLarge) + return isinstance(ex, ks_exceptions.RequestEntityTooLarge) def is_conflict(self, ex): - return isinstance(ex, exceptions.Conflict) + return isinstance(ex, ks_exceptions.Conflict) def get_role_id(self, role): try: role_obj = self.client().client.roles.get(role) return role_obj.id - except exceptions.NotFound: + except ks_exceptions.NotFound: role_list = self.client().client.roles.list(name=role) for role_obj in role_list: if role_obj.name == role: @@ -54,7 +55,7 @@ class KeystoneClientPlugin(client_plugin.ClientPlugin): try: project_obj = self.client().client.projects.get(project) return project_obj.id - except exceptions.NotFound: + except ks_exceptions.NotFound: project_list = self.client().client.projects.list(name=project) for project_obj in project_list: if project_obj.name == project: @@ -69,7 +70,7 @@ class KeystoneClientPlugin(client_plugin.ClientPlugin): try: domain_obj = self.client().client.domains.get(domain) return domain_obj.id - except exceptions.NotFound: + except ks_exceptions.NotFound: domain_list = self.client().client.domains.list(name=domain) for domain_obj in domain_list: if domain_obj.name == domain: @@ -83,7 +84,7 @@ class KeystoneClientPlugin(client_plugin.ClientPlugin): try: group_obj = self.client().client.groups.get(group) return group_obj.id - except exceptions.NotFound: + except ks_exceptions.NotFound: group_list = self.client().client.groups.list(name=group) for group_obj in group_list: if group_obj.name == group: @@ -97,7 +98,7 @@ class KeystoneClientPlugin(client_plugin.ClientPlugin): try: service_obj = self.client().client.services.get(service) return service_obj.id - except exceptions.NotFound: + except ks_exceptions.NotFound: service_list = self.client().client.services.list(name=service) if len(service_list) == 1: @@ -114,7 +115,7 @@ class KeystoneClientPlugin(client_plugin.ClientPlugin): try: user_obj = self.client().client.users.get(user) return user_obj.id - except exceptions.NotFound: + except ks_exceptions.NotFound: user_list = self.client().client.users.list(name=user) for user_obj in user_list: if user_obj.name == user: @@ -126,6 +127,6 @@ class KeystoneClientPlugin(client_plugin.ClientPlugin): try: region_obj = self.client().client.regions.get(region) return region_obj.id - except exceptions.NotFound: + except ks_exceptions.NotFound: raise exception.EntityNotFound(entity='KeystoneRegion', name=region) diff --git a/heat/engine/resources/openstack/keystone/role_assignments.py b/heat/engine/resources/openstack/keystone/role_assignments.py index ae3039813f..e71722c462 100644 --- a/heat/engine/resources/openstack/keystone/role_assignments.py +++ b/heat/engine/resources/openstack/keystone/role_assignments.py @@ -349,8 +349,12 @@ class KeystoneUserRoleAssignment(resource.Resource, @property def user_id(self): - return (self.client_plugin().get_user_id( - self.properties.get(self.USER))) + try: + return self.client_plugin().get_user_id( + self.properties.get(self.USER)) + except Exception as ex: + self.client_plugin().ignore_not_found(ex) + return None def handle_create(self): self.create_assignment(user_id=self.user_id) @@ -406,8 +410,12 @@ class KeystoneGroupRoleAssignment(resource.Resource, @property def group_id(self): - return (self.client_plugin().get_group_id( - self.properties.get(self.GROUP))) + try: + return self.client_plugin().get_group_id( + self.properties.get(self.GROUP)) + except Exception as ex: + self.client_plugin().ignore_not_found(ex) + return None def handle_create(self): self.create_assignment(group_id=self.group_id) diff --git a/heat/tests/clients/test_clients.py b/heat/tests/clients/test_clients.py index c6db7a102f..94df3e4fcb 100644 --- a/heat/tests/clients/test_clients.py +++ b/heat/tests/clients/test_clients.py @@ -636,6 +636,14 @@ class TestIsNotFound(common.HeatTestCase): plugin='keystone', exception=lambda: keystone_exc.NotFound(details='gone'), )), + ('keystone_entity_not_found', dict( + is_not_found=True, + is_over_limit=False, + is_client_exception=True, + is_conflict=False, + plugin='keystone', + exception=lambda: exception.EntityNotFound(), + )), ('keystone_exception', dict( is_not_found=False, is_over_limit=False, diff --git a/heat/tests/openstack/keystone/test_role_assignments.py b/heat/tests/openstack/keystone/test_role_assignments.py index d7ef4ac7fb..c4c01c50a1 100644 --- a/heat/tests/openstack/keystone/test_role_assignments.py +++ b/heat/tests/openstack/keystone/test_role_assignments.py @@ -460,6 +460,12 @@ class KeystoneUserRoleAssignmentTest(common.HeatTestCase): user='user_1', project='project_1') + def test_user_role_assignment_delete_user_not_found(self): + self.keystone_client_plugin.get_user_id.side_effect = [ + exception.EntityNotFound] + self.assertIsNone(self.test_role_assignment.handle_delete()) + self.roles.revoke.assert_not_called() + class KeystoneGroupRoleAssignmentTest(common.HeatTestCase): @@ -573,3 +579,9 @@ class KeystoneGroupRoleAssignmentTest(common.HeatTestCase): role='role_1', group='group_1', project='project_1') + + def test_group_role_assignment_delete_group_not_found(self): + self.keystone_client_plugin.get_group_id.side_effect = [ + exception.EntityNotFound] + self.assertIsNone(self.test_role_assignment.handle_delete()) + self.roles.revoke.assert_not_called()