diff --git a/keystone/identity/core.py b/keystone/identity/core.py index afa397ba2f..b53d269aae 100644 --- a/keystone/identity/core.py +++ b/keystone/identity/core.py @@ -15,6 +15,7 @@ """Main entry point into the Identity service.""" import functools +import itertools import operator import os import threading @@ -530,15 +531,19 @@ class Manager(manager.Manager): """ project_id = payload['resource_info'] - try: - self.driver.unset_default_project_id(project_id) - except exception.Forbidden: - # NOTE(lbragstad): If the driver throws a Forbidden, it's because - # the driver doesn't support writes. This is the case with the - # in-tree LDAP implementation since it is read-only. This also - # ensures consistency for out-of-tree backends that might be - # read-only. - pass + drivers = itertools.chain( + self.domain_configs.values(), [{'driver': self.driver}] + ) + for d in drivers: + try: + d['driver'].unset_default_project_id(project_id) + except exception.Forbidden: + # NOTE(lbragstad): If the driver throws a Forbidden, it's + # because the driver doesn't support writes. This is the case + # with the in-tree LDAP implementation since it is read-only. + # This also ensures consistency for out-of-tree backends that + # might be read-only. + pass # Domain ID normalization methods def _set_domain_id_and_mapping(self, ref, domain_id, driver, diff --git a/keystone/tests/unit/test_backend_ldap.py b/keystone/tests/unit/test_backend_ldap.py index a553504c7d..ddf8852a5d 100644 --- a/keystone/tests/unit/test_backend_ldap.py +++ b/keystone/tests/unit/test_backend_ldap.py @@ -33,6 +33,7 @@ from keystone import exception from keystone import identity from keystone.identity.backends import ldap as ldap_identity from keystone.identity.backends.ldap import common as common_ldap +from keystone.identity.backends import sql as sql_identity from keystone.identity.mapping_backends import mapping as map from keystone.tests import unit from keystone.tests.unit.assignment import test_backends as assignment_tests @@ -2500,6 +2501,19 @@ class MultiLDAPandSQLIdentity(BaseLDAPIdentity, unit.SQLDriverOverrides, base = super(BaseLDAPIdentity, self) base.test_remove_foreign_assignments_when_deleting_a_domain() + @mock.patch.object(ldap_identity.Identity, 'unset_default_project_id') + @mock.patch.object(sql_identity.Identity, 'unset_default_project_id') + def test_delete_project_unset_project_ids_for_all_backends(self, sql_mock, + ldap_mock): + ldap_mock.side_effect = exception.Forbidden + project = unit.new_project_ref( + domain_id=CONF.identity.default_domain_id + ) + project = self.resource_api.create_project(project['id'], project) + self.resource_api.delete_project(project['id']) + ldap_mock.assert_called_with(project['id']) + sql_mock.assert_called_with(project['id']) + class MultiLDAPandSQLIdentityDomainConfigsInSQL(MultiLDAPandSQLIdentity): """Class to test the use of domain configs stored in the database.