Merge "Clean up EP-Filter after delete project/endpoint"

This commit is contained in:
Jenkins 2014-07-25 18:21:04 +00:00 committed by Gerrit Code Review
commit 411359362a
4 changed files with 82 additions and 4 deletions

View File

@ -73,3 +73,17 @@ class EndpointFilter(object):
query = query.filter_by(endpoint_id=endpoint_id)
endpoint_filter_refs = query.all()
return endpoint_filter_refs
def delete_association_by_endpoint(self, endpoint_id):
session = sql.get_session()
with session.begin():
query = session.query(ProjectEndpoint)
query = query.filter_by(endpoint_id=endpoint_id)
query.delete(synchronize_session=False)
def delete_association_by_project(self, project_id):
session = sql.get_session()
with session.begin():
query = session.query(ProjectEndpoint)
query = query.filter_by(project_id=project_id)
query.delete(synchronize_session=False)

View File

@ -17,11 +17,31 @@ from keystone import assignment
from keystone.catalog import controllers as catalog_controllers
from keystone.common import controller
from keystone.common import dependency
from keystone import notifications
@dependency.requires('assignment_api', 'catalog_api', 'endpoint_filter_api')
class EndpointFilterV3Controller(controller.V3Controller):
def __init__(self):
super(EndpointFilterV3Controller, self).__init__()
notifications.register_event_callback(
'deleted', 'project',
self._on_project_or_endpoint_delete)
notifications.register_event_callback(
'deleted', 'endpoint',
self._on_project_or_endpoint_delete)
def _on_project_or_endpoint_delete(self, service, resource_type, operation,
payload):
project_or_endpoint_id = payload['resource_info']
if resource_type == 'project':
self.endpoint_filter_api.delete_association_by_project(
project_or_endpoint_id)
else:
self.endpoint_filter_api.delete_association_by_endpoint(
project_or_endpoint_id)
@controller.protected()
def add_endpoint_to_project(self, context, project_id, endpoint_id):
"""Establishes an association between an endpoint and a project."""
@ -31,8 +51,6 @@ class EndpointFilterV3Controller(controller.V3Controller):
# project as there are no security implications.
self.catalog_api.get_endpoint(endpoint_id)
self.assignment_api.get_project(project_id)
# NOTE(gyee): we may need to cleanup any existing project-endpoint
# associations here if either project or endpoint is not found.
self.endpoint_filter_api.add_endpoint_to_project(endpoint_id,
project_id)
@ -41,8 +59,6 @@ class EndpointFilterV3Controller(controller.V3Controller):
"""Verifies endpoint is currently associated with given project."""
self.catalog_api.get_endpoint(endpoint_id)
self.assignment_api.get_project(project_id)
# TODO(gyee): we may need to cleanup any existing project-endpoint
# associations here if either project or endpoint is not found.
self.endpoint_filter_api.check_endpoint_in_project(endpoint_id,
project_id)

View File

@ -127,3 +127,25 @@ class Driver(object):
"""
raise exception.NotImplemented() # pragma: no cover
@abc.abstractmethod
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
"""
raise exception.NotImplemented()
@abc.abstractmethod
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
"""
raise exception.NotImplemented()

View File

@ -227,6 +227,32 @@ class AssociateEndpointProjectFilterCRUDTestCase(TestExtensionCase):
body='',
expected_status=404)
def test_endpoint_project_assoc_removed_when_delete_project(self):
self.put(self.default_request_url)
association_url = '/OS-EP-FILTER/endpoints/%(endpoint_id)s/projects' % {
'endpoint_id': self.endpoint_id}
r = self.get(association_url, expected_status=200)
self.assertValidProjectListResponse(r, expected_length=1)
self.delete('/projects/%(project_id)s' % {
'project_id': self.default_domain_project_id})
r = self.get(association_url, expected_status=200)
self.assertValidProjectListResponse(r, expected_length=0)
def test_endpoint_project_assoc_removed_when_delete_endpoint(self):
self.put(self.default_request_url)
association_url = '/OS-EP-FILTER/projects/%(project_id)s/endpoints' % {
'project_id': self.default_domain_project_id}
r = self.get(association_url, expected_status=200)
self.assertValidEndpointListResponse(r, expected_length=1)
self.delete('/endpoints/%(endpoint_id)s' % {
'endpoint_id': self.endpoint_id})
r = self.get(association_url, expected_status=200)
self.assertValidEndpointListResponse(r, expected_length=0)
class AssociateProjectEndpointFilterTokenRequestTestCase(TestExtensionCase):
"""Test OS-EP-FILTER catalog filtering extension."""