diff --git a/keystone/resource/core.py b/keystone/resource/core.py index 13389fd467..e427dfb677 100644 --- a/keystone/resource/core.py +++ b/keystone/resource/core.py @@ -469,13 +469,12 @@ class Manager(manager.Manager): """ project = self.driver.get_project(project_id) if project.get('is_domain'): - self.delete_domain(project_id, initiator) + self._delete_domain(project, initiator) else: - self._delete_project(project_id, initiator, cascade) + self._delete_project(project, initiator, cascade) - def _delete_project(self, project_id, initiator=None, cascade=False): - # Use the driver directly to prevent using old cached value. - project = self.driver.get_project(project_id) + def _delete_project(self, project, initiator=None, cascade=False): + project_id = project['id'] if project['is_domain'] and project['enabled']: raise exception.ValidationError( message=_('cannot delete an enabled project acting as a ' @@ -787,7 +786,9 @@ class Manager(manager.Manager): domain = self.driver.get_project(domain_id) except exception.ProjectNotFound: raise exception.DomainNotFound(domain_id=domain_id) + self._delete_domain(domain, initiator) + def _delete_domain(self, domain, initiator=None): # To help avoid inadvertent deletes, we insist that the domain # has been previously disabled. This also prevents a user deleting # their own domain since, once it is disabled, they won't be able @@ -797,11 +798,12 @@ class Manager(manager.Manager): _('Cannot delete a domain that is enabled, please disable it ' 'first.')) + domain_id = domain['id'] self._delete_domain_contents(domain_id) notifications.Audit.internal( notifications.DOMAIN_DELETED, domain_id ) - self._delete_project(domain_id, initiator) + self._delete_project(domain, initiator) try: self.get_domain.invalidate(self, domain_id) self.get_domain_by_name.invalidate(self, domain['name']) @@ -836,7 +838,7 @@ class Manager(manager.Manager): _delete_projects(proj, projects, examined) try: - self.delete_project(project['id'], initiator=None) + self._delete_project(project, initiator=None) except exception.ProjectNotFound: LOG.debug(('Project %(projectid)s not found when ' 'deleting domain contents for %(domainid)s, ' diff --git a/keystone/tests/unit/resource/test_backends.py b/keystone/tests/unit/resource/test_backends.py index abc26db925..814ff12fde 100644 --- a/keystone/tests/unit/resource/test_backends.py +++ b/keystone/tests/unit/resource/test_backends.py @@ -21,6 +21,7 @@ from keystone.common import driver_hints from keystone.common import provider_api import keystone.conf from keystone import exception +from keystone.resource.backends import sql as resource_sql from keystone.tests import unit from keystone.tests.unit import default_fixtures from keystone.tests.unit import utils as test_utils @@ -1294,6 +1295,23 @@ class ResourceTests(object): PROVIDERS.resource_api.get_domain, domain['id']) + @unit.skip_if_no_multiple_domains_support + def test_delete_domain_call_db_time(self): + domain = unit.new_domain_ref() + PROVIDERS.resource_api.create_domain(domain['id'], domain) + # Disable the domain + domain['enabled'] = False + PROVIDERS.resource_api.update_domain(domain['id'], domain) + + domain_ref = PROVIDERS.resource_api.get_project(domain['id']) + with mock.patch.object(resource_sql.Resource, + "get_project") as mock_get_project: + + mock_get_project.return_value = domain_ref + # Delete the domain + PROVIDERS.resource_api.delete_domain(domain['id']) + self.assertEqual(mock_get_project.call_count, 1) + @unit.skip_if_no_multiple_domains_support def test_domain_name_case_sensitivity(self): # create a ref with a lowercase name diff --git a/keystone/tests/unit/test_backend_ldap.py b/keystone/tests/unit/test_backend_ldap.py index fa4a0a7bab..1d8d632210 100644 --- a/keystone/tests/unit/test_backend_ldap.py +++ b/keystone/tests/unit/test_backend_ldap.py @@ -254,6 +254,9 @@ class ResourceTests(resource_tests.ResourceTests): def test_domain_crud(self): self.skip_test_overrides('N/A: Not relevant for multi ldap testing') + def test_delete_domain_call_db_time(self): + self.skip_test_overrides('Domains are read-only against LDAP') + def test_create_project_with_parent_id_and_without_domain_id(self): self.skip_test_overrides('Resource LDAP has been removed')