diff --git a/keystone/catalog/backends/kvs.py b/keystone/catalog/backends/kvs.py deleted file mode 100644 index 644777ed2d..0000000000 --- a/keystone/catalog/backends/kvs.py +++ /dev/null @@ -1,371 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -from keystone import catalog -from keystone.common import driver_hints -from keystone.common import kvs - - -class Catalog(kvs.Base, catalog.CatalogDriverV8): - # Public interface - def get_catalog(self, user_id, tenant_id): - return self.db.get('catalog-%s-%s' % (tenant_id, user_id)) - - # region crud - - def _delete_child_regions(self, region_id, root_region_id): - """Delete all child regions. - - Recursively delete any region that has the supplied region - as its parent. - """ - children = [r for r in self.list_regions(driver_hints.Hints()) - if r['parent_region_id'] == region_id] - for child in children: - if child['id'] == root_region_id: - # Hit a circular region hierarchy - return - self._delete_child_regions(child['id'], root_region_id) - self._delete_region(child['id']) - - def _check_parent_region(self, region_ref): - """Raise a NotFound if the parent region does not exist. - - If the region_ref has a specified parent_region_id, check that - the parent exists, otherwise, raise a NotFound. - """ - parent_region_id = region_ref.get('parent_region_id') - if parent_region_id is not None: - # This will raise NotFound if the parent doesn't exist, - # which is the behavior we want. - self.get_region(parent_region_id) - - def create_region(self, region): - region_id = region['id'] - region.setdefault('parent_region_id') - self._check_parent_region(region) - self.db.set('region-%s' % region_id, region) - region_list = set(self.db.get('region_list', [])) - region_list.add(region_id) - self.db.set('region_list', list(region_list)) - return region - - def list_regions(self, hints): - return [self.get_region(x) for x in self.db.get('region_list', [])] - - def get_region(self, region_id): - return self.db.get('region-%s' % region_id) - - def update_region(self, region_id, region): - self._check_parent_region(region) - old_region = self.get_region(region_id) - old_region.update(region) - self._ensure_no_circle_in_hierarchical_regions(old_region) - self.db.set('region-%s' % region_id, old_region) - return old_region - - def _delete_region(self, region_id): - self.db.delete('region-%s' % region_id) - region_list = set(self.db.get('region_list', [])) - region_list.remove(region_id) - self.db.set('region_list', list(region_list)) - - def delete_region(self, region_id): - self._delete_child_regions(region_id, region_id) - self._delete_region(region_id) - - # service crud - - def create_service(self, service_id, service): - self.db.set('service-%s' % service_id, service) - service_list = set(self.db.get('service_list', [])) - service_list.add(service_id) - self.db.set('service_list', list(service_list)) - return service - - def list_services(self, hints): - return [self.get_service(x) for x in self.db.get('service_list', [])] - - def get_service(self, service_id): - return self.db.get('service-%s' % service_id) - - def update_service(self, service_id, service): - old_service = self.get_service(service_id) - old_service.update(service) - self.db.set('service-%s' % service_id, old_service) - return old_service - - def delete_service(self, service_id): - # delete referencing endpoints - for endpoint_id in self.db.get('endpoint_list', []): - if self.get_endpoint(endpoint_id)['service_id'] == service_id: - self.delete_endpoint(endpoint_id) - - self.db.delete('service-%s' % service_id) - service_list = set(self.db.get('service_list', [])) - service_list.remove(service_id) - self.db.set('service_list', list(service_list)) - - # endpoint crud - - def create_endpoint(self, endpoint_id, endpoint): - self.db.set('endpoint-%s' % endpoint_id, endpoint) - endpoint_list = set(self.db.get('endpoint_list', [])) - endpoint_list.add(endpoint_id) - self.db.set('endpoint_list', list(endpoint_list)) - return endpoint - - def list_endpoints(self, hints): - return [self.get_endpoint(x) for x in self.db.get('endpoint_list', [])] - - def get_endpoint(self, endpoint_id): - return self.db.get('endpoint-%s' % endpoint_id) - - def update_endpoint(self, endpoint_id, endpoint): - if endpoint.get('region_id') is not None: - self.get_region(endpoint['region_id']) - - old_endpoint = self.get_endpoint(endpoint_id) - old_endpoint.update(endpoint) - self.db.set('endpoint-%s' % endpoint_id, old_endpoint) - return old_endpoint - - def delete_endpoint(self, endpoint_id): - self.db.delete('endpoint-%s' % endpoint_id) - endpoint_list = set(self.db.get('endpoint_list', [])) - endpoint_list.remove(endpoint_id) - self.db.set('endpoint_list', list(endpoint_list)) - - # Private interface - def _create_catalog(self, user_id, tenant_id, data): - self.db.set('catalog-%s-%s' % (tenant_id, user_id), data) - return data - - # TODO(davechen): Apparently, these methods are not implemented but - # we cannot raise exception.NotImplemented() just because the notification - # to those resource will break some testcases, will look into CADF to - # see if there is any better way to do this. - def add_endpoint_to_project(self, endpoint_id, project_id): - """Create an endpoint to project association. - - :param endpoint_id: identity of endpoint to associate - :type endpoint_id: string - :param project_id: identity of the project to be associated with - :type project_id: string - :raises: keystone.exception.Conflict: If the endpoint was already - added to project. - :returns: None. - - """ - pass - - def remove_endpoint_from_project(self, endpoint_id, project_id): - """Removes an endpoint to project association. - - :param endpoint_id: identity of endpoint to remove - :type endpoint_id: string - :param project_id: identity of the project associated with - :type project_id: string - :raises keystone.exception.NotFound: If the endpoint was not found - in the project. - :returns: None. - - """ - pass - - def check_endpoint_in_project(self, endpoint_id, project_id): - """Checks if an endpoint is associated with a project. - - :param endpoint_id: identity of endpoint to check - :type endpoint_id: string - :param project_id: identity of the project associated with - :type project_id: string - :raises keystone.exception.NotFound: If the endpoint was not found - in the project. - :returns: None. - - """ - pass - - def list_endpoints_for_project(self, project_id): - """List all endpoints associated with a project. - - :param project_id: identity of the project to check - :type project_id: string - :returns: a list of identity endpoint ids or an empty list. - - """ - pass - - def list_projects_for_endpoint(self, endpoint_id): - """List all projects associated with an endpoint. - - :param endpoint_id: identity of endpoint to check - :type endpoint_id: string - :returns: a list of projects or an empty list. - - """ - pass - - def delete_association_by_endpoint(self, endpoint_id): - """Removes all the endpoints to project association with endpoint. - - :param endpoint_id: identity of endpoint to check - :type endpoint_id: string - :returns: None - - """ - pass - - def delete_association_by_project(self, project_id): - """Removes all the endpoints to project association with project. - - :param project_id: identity of the project to check - :type project_id: string - :returns: None - - """ - pass - - def create_endpoint_group(self, endpoint_group): - """Create an endpoint group. - - :param endpoint_group: endpoint group to create - :type endpoint_group: dictionary - :raises: keystone.exception.Conflict: If a duplicate endpoint group - already exists. - :returns: an endpoint group representation. - - """ - pass - - def get_endpoint_group(self, endpoint_group_id): - """Get an endpoint group. - - :param endpoint_group_id: identity of endpoint group to retrieve - :type endpoint_group_id: string - :raises keystone.exception.NotFound: If the endpoint group was not - found. - :returns: an endpoint group representation. - - """ - pass - - def update_endpoint_group(self, endpoint_group_id, endpoint_group): - """Update an endpoint group. - - :param endpoint_group_id: identity of endpoint group to retrieve - :type endpoint_group_id: string - :param endpoint_group: A full or partial endpoint_group - :type endpoint_group: dictionary - :raises keystone.exception.NotFound: If the endpoint group was not - found. - :returns: an endpoint group representation. - - """ - pass - - def delete_endpoint_group(self, endpoint_group_id): - """Delete an endpoint group. - - :param endpoint_group_id: identity of endpoint group to delete - :type endpoint_group_id: string - :raises keystone.exception.NotFound: If the endpoint group was not - found. - :returns: None. - - """ - pass - - def add_endpoint_group_to_project(self, endpoint_group_id, project_id): - """Adds an endpoint group to project association. - - :param endpoint_group_id: identity of endpoint to associate - :type endpoint_group_id: string - :param project_id: identity of project to associate - :type project_id: string - :raises keystone.exception.Conflict: If the endpoint group was already - added to the project. - :returns: None. - - """ - pass - - def get_endpoint_group_in_project(self, endpoint_group_id, project_id): - """Get endpoint group to project association. - - :param endpoint_group_id: identity of endpoint group to retrieve - :type endpoint_group_id: string - :param project_id: identity of project to associate - :type project_id: string - :raises keystone.exception.NotFound: If the endpoint group to the - project association was not found. - :returns: a project endpoint group representation. - - """ - pass - - def list_endpoint_groups(self): - """List all endpoint groups. - - :returns: None. - - """ - pass - - def list_endpoint_groups_for_project(self, project_id): - """List all endpoint group to project associations for a project. - - :param project_id: identity of project to associate - :type project_id: string - :returns: None. - - """ - pass - - def list_projects_associated_with_endpoint_group(self, endpoint_group_id): - """List all projects associated with endpoint group. - - :param endpoint_group_id: identity of endpoint to associate - :type endpoint_group_id: string - :returns: None. - - """ - pass - - def remove_endpoint_group_from_project(self, endpoint_group_id, - project_id): - """Remove an endpoint to project association. - - :param endpoint_group_id: identity of endpoint to associate - :type endpoint_group_id: string - :param project_id: identity of project to associate - :type project_id: string - :raises keystone.exception.NotFound: If endpoint group project - association was not found. - :returns: None. - - """ - pass - - def delete_endpoint_group_association_by_project(self, project_id): - """Remove endpoint group to project associations. - - :param project_id: identity of the project to check - :type project_id: string - :returns: None - - """ - pass diff --git a/keystone/catalog/backends/templated.py b/keystone/catalog/backends/templated.py index 4e667f7407..0f28d608d7 100644 --- a/keystone/catalog/backends/templated.py +++ b/keystone/catalog/backends/templated.py @@ -17,8 +17,8 @@ import os.path from oslo_config import cfg from oslo_log import log +import six -from keystone.catalog.backends import kvs from keystone.catalog import core from keystone import exception from keystone.i18n import _LC @@ -56,7 +56,7 @@ def parse_templates(template_lines): return o -class Catalog(kvs.Catalog): +class Catalog(core.Driver): """A backend that generates endpoints for the Catalog based on templates. It is usually configured via config entries that look like: @@ -105,6 +105,95 @@ class Catalog(kvs.Catalog): LOG.critical(_LC('Unable to open template file %s'), template_file) raise + # region crud + + def create_region(self, region_ref): + raise exception.NotImplemented() + + def list_regions(self, hints): + return [{'id': region_id, 'description': '', 'parent_region_id': ''} + for region_id in self.templates] + + def get_region(self, region_id): + if region_id in self.templates: + return {'id': region_id, 'description': '', 'parent_region_id': ''} + raise exception.RegionNotFound(region_id=region_id) + + def update_region(self, region_id, region_ref): + raise exception.NotImplemented() + + def delete_region(self, region_id): + raise exception.NotImplemented() + + # service crud + + def create_service(self, service_id, service_ref): + raise exception.NotImplemented() + + def _list_services(self, hints): + for region_ref in six.itervalues(self.templates): + for service_type, service_ref in six.iteritems(region_ref): + yield { + 'id': service_type, + 'enabled': True, + 'name': service_ref.get('name', ''), + 'description': service_ref.get('description', ''), + 'type': service_type, + } + + def list_services(self, hints): + return list(self._list_services()) + + def get_service(self, service_id): + for service in self._list_services(hints=None): + if service['id'] == service_id: + return service + raise exception.ServiceNotFound(service_id=service_id) + + def update_service(self, service_id, service_ref): + raise exception.NotImplemented() + + def delete_service(self, service_id): + raise exception.NotImplemented() + + # endpoint crud + + def create_endpoint(self, endpoint_id, endpoint_ref): + raise exception.NotImplemented() + + def _list_endpoints(self): + for region_id, region_ref in six.iteritems(self.templates): + for service_type, service_ref in six.iteritems(region_ref): + for key in service_ref: + if key.endswith('URL'): + interface = key[:-3] + endpoint_id = ('%s-%s-%s' % + (region_id, service_type, interface)) + yield { + 'id': endpoint_id, + 'service_id': service_type, + 'interface': interface, + 'url': service_ref[key], + 'legacy_endpoint_id': None, + 'region_id': region_id, + 'enabled': True, + } + + def list_endpoints(self, hints): + return list(self._list_endpoints()) + + def get_endpoint(self, endpoint_id): + for endpoint in self._list_endpoints(): + if endpoint['id'] == endpoint_id: + return endpoint + raise exception.EndpointNotFound(endpoint_id=endpoint_id) + + def update_endpoint(self, endpoint_id, endpoint_ref): + raise exception.NotImplemented() + + def delete_endpoint(self, endpoint_id): + raise exception.NotImplemented() + def get_catalog(self, user_id, tenant_id): """Retrieve and format the V2 service catalog. @@ -148,3 +237,58 @@ class Catalog(kvs.Catalog): catalog[region][service] = service_data return catalog + + def add_endpoint_to_project(self, endpoint_id, project_id): + raise exception.NotImplemented() + + def remove_endpoint_from_project(self, endpoint_id, project_id): + raise exception.NotImplemented() + + def check_endpoint_in_project(self, endpoint_id, project_id): + raise exception.NotImplemented() + + def list_endpoints_for_project(self, project_id): + raise exception.NotImplemented() + + def list_projects_for_endpoint(self, endpoint_id): + raise exception.NotImplemented() + + def delete_association_by_endpoint(self, endpoint_id): + raise exception.NotImplemented() + + def delete_association_by_project(self, project_id): + raise exception.NotImplemented() + + def create_endpoint_group(self, endpoint_group): + raise exception.NotImplemented() + + def get_endpoint_group(self, endpoint_group_id): + raise exception.NotImplemented() + + def update_endpoint_group(self, endpoint_group_id, endpoint_group): + raise exception.NotImplemented() + + def delete_endpoint_group(self, endpoint_group_id): + raise exception.NotImplemented() + + def add_endpoint_group_to_project(self, endpoint_group_id, project_id): + raise exception.NotImplemented() + + def get_endpoint_group_in_project(self, endpoint_group_id, project_id): + raise exception.NotImplemented() + + def list_endpoint_groups(self): + raise exception.NotImplemented() + + def list_endpoint_groups_for_project(self, project_id): + raise exception.NotImplemented() + + def list_projects_associated_with_endpoint_group(self, endpoint_group_id): + raise exception.NotImplemented() + + def remove_endpoint_group_from_project(self, endpoint_group_id, + project_id): + raise exception.NotImplemented() + + def delete_endpoint_group_association_by_project(self, project_id): + raise exception.NotImplemented() diff --git a/keystone/common/kvs/__init__.py b/keystone/common/kvs/__init__.py index 9a406a85bd..354bbd8ad8 100644 --- a/keystone/common/kvs/__init__.py +++ b/keystone/common/kvs/__init__.py @@ -15,7 +15,6 @@ from dogpile.cache import region from keystone.common.kvs.core import * # noqa -from keystone.common.kvs.legacy import Base, DictKvs, INMEMDB # noqa # NOTE(morganfainberg): Provided backends are registered here in the __init__ diff --git a/keystone/common/kvs/legacy.py b/keystone/common/kvs/legacy.py deleted file mode 100644 index 7e27d97fbb..0000000000 --- a/keystone/common/kvs/legacy.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright 2012 OpenStack Foundation -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oslo_log import versionutils - -from keystone import exception - - -class DictKvs(dict): - def get(self, key, default=None): - try: - if isinstance(self[key], dict): - return self[key].copy() - else: - return self[key][:] - except KeyError: - if default is not None: - return default - raise exception.NotFound(target=key) - - def set(self, key, value): - if isinstance(value, dict): - self[key] = value.copy() - else: - self[key] = value[:] - - def delete(self, key): - """Deletes an item, returning True on success, False otherwise.""" - try: - del self[key] - except KeyError: - raise exception.NotFound(target=key) - - -INMEMDB = DictKvs() - - -class Base(object): - @versionutils.deprecated(versionutils.deprecated.ICEHOUSE, - in_favor_of='keystone.common.kvs.KeyValueStore', - remove_in=+2, - what='keystone.common.kvs.Base') - def __init__(self, db=None): - if db is None: - db = INMEMDB - elif isinstance(db, DictKvs): - db = db - elif isinstance(db, dict): - db = DictKvs(db) - self.db = db diff --git a/keystone/tests/unit/core.py b/keystone/tests/unit/core.py index f90874a296..9d955d2f28 100644 --- a/keystone/tests/unit/core.py +++ b/keystone/tests/unit/core.py @@ -49,7 +49,6 @@ environment.use_eventlet() from keystone import auth from keystone.common import config from keystone.common import dependency -from keystone.common import kvs from keystone.common.kvs import core as kvs_core from keystone.common import sql from keystone import exception @@ -534,7 +533,7 @@ class TestCase(BaseTestCase): proxies=['oslo_cache.testing.CacheIsolatingProxy']) self.config_fixture.config( group='catalog', - driver='templated', + driver='sql', template_file=dirs.tests('default_catalog.templates')) self.config_fixture.config( group='kvs', @@ -619,8 +618,6 @@ class TestCase(BaseTestCase): # tests aren't used. self.addCleanup(dependency.reset) - self.addCleanup(kvs.INMEMDB.clear) - # Ensure Notification subscriptions and resource types are empty self.addCleanup(notifications.clear_subscribers) self.addCleanup(notifications.reset_notifier) diff --git a/keystone/tests/unit/test_backend.py b/keystone/tests/unit/test_backend.py index 7f720cd055..feb205d520 100644 --- a/keystone/tests/unit/test_backend.py +++ b/keystone/tests/unit/test_backend.py @@ -4801,7 +4801,7 @@ class TrustTests(object): class CatalogTests(object): - _legacy_endpoint_id_in_endpoint = False + _legacy_endpoint_id_in_endpoint = True _enabled_default_to_true_when_creating_endpoint = False def test_region_crud(self): @@ -5261,6 +5261,7 @@ class CatalogTests(object): res = self.catalog_api.update_endpoint(endpoint_ref['id'], {'interface': 'private'}) expected_endpoint = endpoint_ref.copy() + expected_endpoint['enabled'] = True expected_endpoint['interface'] = 'private' if self._legacy_endpoint_id_in_endpoint: expected_endpoint['legacy_endpoint_id'] = None diff --git a/keystone/tests/unit/test_backend_kvs.py b/keystone/tests/unit/test_backend_kvs.py index 1fbbcd48b4..d29ebab662 100644 --- a/keystone/tests/unit/test_backend_kvs.py +++ b/keystone/tests/unit/test_backend_kvs.py @@ -103,60 +103,6 @@ class KvsToken(unit.TestCase, test_backend.TokenTests): self.assertEqual(expected_user_token_list, user_token_list) -class KvsCatalog(unit.TestCase, test_backend.CatalogTests): - def setUp(self): - super(KvsCatalog, self).setUp() - self.load_backends() - self._load_fake_catalog() - - def config_overrides(self): - super(KvsCatalog, self).config_overrides() - self.config_fixture.config(group='catalog', driver='kvs') - - def _load_fake_catalog(self): - self.catalog_foobar = self.catalog_api.driver._create_catalog( - 'foo', 'bar', - {'RegionFoo': {'service_bar': {'foo': 'bar'}}}) - - def test_get_catalog_returns_not_found(self): - # FIXME(dolph): this test should be moved up to test_backend - # FIXME(dolph): exceptions should be UserNotFound and ProjectNotFound - self.assertRaises(exception.NotFound, - self.catalog_api.get_catalog, - uuid.uuid4().hex, - 'bar') - - self.assertRaises(exception.NotFound, - self.catalog_api.get_catalog, - 'foo', - uuid.uuid4().hex) - - def test_get_catalog(self): - catalog_ref = self.catalog_api.get_catalog('foo', 'bar') - self.assertDictEqual(self.catalog_foobar, catalog_ref) - - def test_get_catalog_endpoint_disabled(self): - # This test doesn't apply to KVS because with the KVS backend the - # application creates the catalog (including the endpoints) for each - # user and project. Whether endpoints are enabled or disabled isn't - # a consideration. - f = super(KvsCatalog, self).test_get_catalog_endpoint_disabled - self.assertRaises(exception.NotFound, f) - - def test_get_v3_catalog_endpoint_disabled(self): - # There's no need to have disabled endpoints in the kvs catalog. Those - # endpoints should just be removed from the store. This just tests - # what happens currently when the super impl is called. - f = super(KvsCatalog, self).test_get_v3_catalog_endpoint_disabled - self.assertRaises(exception.NotFound, f) - - def test_list_regions_filtered_by_parent_region_id(self): - self.skipTest('KVS backend does not support hints') - - def test_service_filtering(self): - self.skipTest("kvs backend doesn't support filtering") - - class KvsTokenCacheInvalidation(unit.TestCase, test_backend.TokenCacheInvalidation): def setUp(self): diff --git a/keystone/tests/unit/test_backend_templated.py b/keystone/tests/unit/test_backend_templated.py index f65c6d472d..7e69fd07f0 100644 --- a/keystone/tests/unit/test_backend_templated.py +++ b/keystone/tests/unit/test_backend_templated.py @@ -232,11 +232,11 @@ class TestTemplatedCatalog(unit.TestCase, test_backend.CatalogTests): self.skipTest(BROKEN_WRITE_FUNCTIONALITY_MSG) def test_list_endpoints(self): - # NOTE(dstanek): a future commit will fix this functionality and - # this test - expected_ids = set() + expected_urls = set(['http://localhost:$(public_port)s/v2.0', + 'http://localhost:$(admin_port)s/v2.0', + 'http://localhost:8774/v1.1/$(tenant_id)s']) endpoints = self.catalog_api.list_endpoints() - self.assertEqual(expected_ids, set(e['id'] for e in endpoints)) + self.assertEqual(expected_urls, set(e['url'] for e in endpoints)) @unit.skip_if_cache_disabled('catalog') def test_invalidate_cache_when_updating_endpoint(self): diff --git a/keystone/tests/unit/test_v2.py b/keystone/tests/unit/test_v2.py index da85b25dce..ff5175ff23 100644 --- a/keystone/tests/unit/test_v2.py +++ b/keystone/tests/unit/test_v2.py @@ -23,6 +23,7 @@ from six.moves import http_client from testtools import matchers from keystone.common import extension as keystone_extension +from keystone.tests import unit from keystone.tests.unit import ksfixtures from keystone.tests.unit import rest @@ -987,6 +988,14 @@ class RestfulTestCase(rest.RestfulTestCase): class V2TestCase(RestfulTestCase, CoreApiTests, LegacyV2UsernameTests): + + def config_overrides(self): + super(V2TestCase, self).config_overrides() + self.config_fixture.config( + group='catalog', + driver='templated', + template_file=unit.dirs.tests('default_catalog.templates')) + def _get_user_id(self, r): return r['user']['id'] diff --git a/releasenotes/notes/impl-templated-catalog-1d8f6333726b34f8.yaml b/releasenotes/notes/impl-templated-catalog-1d8f6333726b34f8.yaml new file mode 100644 index 0000000000..3afd9159a1 --- /dev/null +++ b/releasenotes/notes/impl-templated-catalog-1d8f6333726b34f8.yaml @@ -0,0 +1,9 @@ +--- +other: + - > + [`bug 1367113 <https://bugs.launchpad.net/keystone/+bug/1367113>`_] + The "get entity" and "list entities" functionality for the KVS catalog + backend has been reimplemented to use the data from the catalog template. + Previously this would only act on temporary data that was created at + runtime. The create, update and delete entity functionality now raises + an exception. diff --git a/releasenotes/notes/removed-as-of-mitaka-9ff14f87d0b98e7e.yaml b/releasenotes/notes/removed-as-of-mitaka-9ff14f87d0b98e7e.yaml index 2afa8ce399..de383f01ec 100644 --- a/releasenotes/notes/removed-as-of-mitaka-9ff14f87d0b98e7e.yaml +++ b/releasenotes/notes/removed-as-of-mitaka-9ff14f87d0b98e7e.yaml @@ -22,3 +22,7 @@ other: Removed ``check_role_for_trust`` from the trust controller, ensure policy files do not refer to this target. This was deprecated in the Kilo release. + - > + [`blueprint removed-as-of-mitaka <https://blueprints.launchpad.net/keystone/+spec/removed-as-of-mitaka>`_] + Removed Catalog KVS backend (``keystone.catalog.backends.sql.Catalog``). + This was deprecated in the Icehouse release. diff --git a/setup.cfg b/setup.cfg index 210f13a790..a5c1cf1188 100644 --- a/setup.cfg +++ b/setup.cfg @@ -106,7 +106,6 @@ keystone.auth.x509 = default = keystone.auth.plugins.mapped:Mapped keystone.catalog = - kvs = keystone.catalog.backends.kvs:Catalog sql = keystone.catalog.backends.sql:Catalog templated = keystone.catalog.backends.templated:Catalog endpoint_filter.sql = keystone.contrib.endpoint_filter.backends.catalog_sql:EndpointFilterCatalog